# Edit Property Flow - Documentation ## Overview The edit property flow allows property owners to update their rent property listing, including all fields and images. It shares the same screen as add property (`add_rent_property_screen.dart`) and switches behavior based on `widget.initialListing != null` (edit mode). ## Screen: `add_rent_property_screen.dart` ### State Variables for Images ```dart // Existing images loaded from the listing (edit mode) List _existingImagePaths = []; // Newly selected images (both add & edit mode) List _formImages = []; List _imageSlotIds = []; List _imageFingerprints = []; List _imagePreviews = []; List _uploadedImagePaths = []; Set _uploadingImageKeys = {}; Set _failedImageKeys = {}; int get _totalImageCount => _existingImagePaths.length + _formImages.length; ``` ### Initialization in Edit Mode When editing, `_prefillFromInitialListing()` populates `_existingImagePaths` from the API response: ```dart _existingImagePaths = info.images .map((path) => path.trim()) .where((path) => path.isNotEmpty) .toList(); ``` ### Image Management UI (Edit Mode) | Feature | Implementation | |---------|---------------| | **View existing images** | `Image.network` with `ApiConstants.resolveApiFileUrl()` | | **Delete existing image** | X button → `_removeExistingImageAt(index)` removes from `_existingImagePaths` | | **Replace existing image** | Tap on image → `_replaceExistingImageAt(index)` → file picker → upload via `POST /Files/UploadPicture` → replaces URL at same index | | **Add new image** | Upload button → `_handleImageUpload()` → `_addSelectedImage()` → upload via `POST /Files/UploadPicture` | | **Reorder existing images** | Up/down arrow buttons → `_moveExistingImage(index, direction)` | | **Reorder new images** | Up/down arrow buttons → `_moveSelectedImage(index, direction)` (moves all 6 parallel lists together) | ### Submit - Image Assembly On submit, the final image list is built from: ```dart final allImagePaths = [ ..._existingImagePaths .map((path) => path.trim()) .where((path) => path.isNotEmpty), ...uploadedImagePaths, ]; ``` This combined list is passed to `AddRentPropertyDto` → `PropertyInformationDto` as `images`. ## API Details ### Image Upload Endpoint ``` POST /Files/UploadPicture Headers: Authorization: Bearer , Content-Type: multipart/form-data Body: image= Response: { "value": "/Pictures/xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx.jpg" } ``` The returned path is used in the edit request. ### Edit Property Endpoint ``` PUT /RentProperties/EditRentProperty/{id} Content-Type: application/json Authorization: Bearer ``` #### Request Body (camelCase contract from swagger) ```json { "propertyInformation": { "activityStatus": 0, "images": [ "/Pictures/xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx.jpg" ], "cordsX": "33.51599774641418", "cordsY": "36.281279544066294", "address": "string", "description": "string", "numberOfBathRooms": 2, "numberOfRooms": 3, "numberOfBedRooms": 3, "space": 120.0, "detailsJSON": "{}", "buildingType": 0, "status": 0, "propertyType": 0, "city": 0 }, "deposit": 5.0, "acceptedCertificate": 0, "monthlyRent": 0.0, "dailyRent": 56.0, "rating": 1.0, "currencyId": 1, "rentType": 1, "isSmokeAllow": false, "specializedFor": false, "isVisitorAllow": false, "allowedPaymentPeriod": "10:02:00", "type": 0 } ``` ### Payload Attempt Order (Flutter side) The app tries multiple payload shapes as fallback: | Order | Label | Structure | Example | |-------|-------|-----------|---------| | 1 | `plain_pascal` | PascalCase direct | `{PropertyInformation: {Images: [...]}}` | | 2 | `wrapped_pascal_outer` | PascalCase with DTO wrapper | `{RentPropertyDto: {PropertyInformation: {Images: [...]}}}` | | 3 | `wrapped_pascal_inner` | PascalCase inside camelCase wrapper | `{rentPropertyDto: {PropertyInformation: {Images: [...]}}}` | | 4 | `wrapped_camel` | camelCase wrapped | `{rentPropertyDto: {propertyInformation: {images: [...]}}}` | | 5 | `plain_camel` | camelCase direct | `{propertyInformation: {images: [...]}}` | | 6 | `multipart_form` | multipart form fields | `PropertyInformation.Images[0] = url` | --- ## 🚨 CONFIRMED BACKEND BUG ### Symptoms - **All scalar fields** (deposit, dailyRent, address, etc.) update correctly via PUT - **`propertyInformation.images`** is ALWAYS ignored by the PUT endpoint - **`propertyInformation.detailsJSON`** is also ignored by the PUT endpoint - The **POST add endpoint** handles both fields correctly ### Evidence from Direct API Tests **Test 1 - camelCase JSON via curl:** ``` PUT /RentProperties/EditRentProperty/1 → images sent: ["/Pictures/test1.jpg", "/Pictures/test2.jpg"] → images response: ["/Pictures/f7062fc863a74306a6a0340982669386.png"] ❌ OLD → address sent: "test address" → address response: "test address" ✅ UPDATED ``` **Test 2 - PascalCase JSON via curl:** ``` PUT /RentProperties/EditRentProperty/1 → Images sent: ["/Pictures/new1.jpg", "/Pictures/new2.jpg"] → images response: ["/Pictures/f7062fc863a74306a6a0340982669386.png"] ❌ OLD → Address sent: "test pascal" → Address response: "test pascal" ✅ UPDATED ``` **Test 3 - POST add endpoint (works correctly):** ``` POST /RentProperties/AddRentProperty → images sent: ["/Pictures/test1.jpg", "/Pictures/test2.jpg"] → images response: ["/Pictures/test1.jpg", "/Pictures/test2.jpg"] ✅ STORED CORRECTLY ``` ### Root Cause (Backend Side) The `EditRentProperty` PUT handler in the backend likely: 1. Creates a new `RentProperty` record (or updates it) - scalar fields work 2. Updates or assigns the `PropertyInformation` record - but only scalar fields are copied 3. The `Images` and `DetailsJSON` properties of `PropertyInformation` are **not mapped/copied** during update Comparison with `AddRentProperty`: - The POST handler correctly maps all `PropertyInformation` fields including `Images` and `DetailsJSON` - The PUT handler appears to skip these two fields specifically ### Required Backend Fix The PUT endpoint handler needs to be updated to persist `propertyInformation.images` and `propertyInformation.detailsJSON` when updating existing property information records. --- ## Summary | Aspect | Status | |--------|--------| | Image upload (to server) | ✅ Working via `POST /Files/UploadPicture` | | Image management UI (edit mode) | ✅ Delete, Replace, Add, Reorder all implemented | | Image assembly for submit | ✅ Correctly combines kept + new uploaded paths | | Payload format (camelCase/PascalCase) | ✅ Both formats tried correctly | | **PUT edit endpoint** | **❌ Does NOT update images or detailsJSON** | | POST add endpoint | ✅ Fully functional |