# SweetHome — Full Project Analysis

**Project:** SweetHome Next.js Real Estate Application
**Date:** June 16, 2026
**Framework:** Next.js 16.1.6 (App Router) + React 18.3.1
**Language:** JavaScript (no TypeScript)
**Styling:** Tailwind CSS v4 + DaisyUI (unused) + Flowbite (unused)
**API:** Custom `.NET` backend at `https://45.93.137.91.nip.io/api`

---

## 1. Project Structure

### Directory Tree (Top 3 Levels)

```
SweetHome/
├── .gitea/workflows/            # CI/CD deployer
├── app/                         # ★ MAIN APP (112 source files)
│   ├── account-verification/    # OTP email/phone verification
│   ├── auth/choose-role/        # Owner/Tenant/Agent role picker
│   ├── blocked/                 # Blocked account page
│   ├── booked-properties/       # User's booked properties
│   ├── change-password/         # Change password form
│   ├── components/              # ★ 14 reusable components
│   │   ├── home/                # HeroSearch, PropertyMap
│   │   ├── property/            # BookingCalendar, PropertyMap
│   │   ├── ratings/             # StarRating, PropertyRatingForm, etc.
│   │   ├── BottomNav.js         # Mobile bottom nav
│   │   ├── FloatingSidebar.js   # Desktop floating sidebar
│   │   ├── NavLinks.js          # Nav link atoms
│   │   ├── NotificationHandler.js # Firebase FCM handler
│   │   └── PropertyMapWithMarkers.js # Standalone Leaflet map
│   ├── contexts/                # ★ 3 context providers
│   │   ├── FavoritesContext.js
│   │   ├── NotificationsContext.js
│   │   └── PropertyContext.js   # ORPHANED (never mounted)
│   ├── enums/                   # 20 enum constant files
│   ├── faq/                     # FAQ accordion page
│   ├── favorites/               # Favorites list page
│   ├── forgot-password/         # 3-step forgot password
│   ├── i18n/                    # i18next config (Arabic/English)
│   ├── login/                   # 2-step login (credential + OTP)
│   ├── my-rates/                # Ratings received from owners
│   ├── notifications/           # Notifications list page
│   ├── onboarding/              # 3-step intro wizard
│   ├── owner/                   # ★ Owner dashboard (6 sub-routes)
│   │   ├── account-book/        # Financial dashboard
│   │   ├── bookings/            # Booking management
│   │   ├── calendar/            # Monthly calendar view
│   │   ├── profits/             # Revenue/profit stats
│   │   ├── properties/          # CRUD property management
│   │   └── reservations/        # Reservation requests
│   ├── payments/                # Deposit payment page
│   ├── privacy/                 # Privacy policy
│   ├── profile/                 # User profile CRUD
│   ├── properties/              # Property listings grid
│   ├── property/[id]/           # Property detail (dynamic route)
│   ├── register/                # Registration (tenant/owner/agent)
│   ├── reports/                 # 3-tab report submission
│   ├── reservations/            # Customer reservations
│   ├── services/                # AuthService.js
│   ├── settings/                # Account settings
│   ├── support/                 # Support contact form
│   ├── terms/                   # Terms of service
│   ├── utils/                   # ★ api.js, calculations, firebase, etc.
│   ├── ClientLayout.js          # Client layout shell (804 lines)
│   ├── layout.js                # Root server layout
│   ├── globals.css              # Tailwind + custom fonts
│   ├── page.js                  # Home page
│   ├── error.js                 # Error boundary
│   ├── loading.js               # Loading state
│   └── not-found.js             # 404 page
├── public/                      # Static files (fonts, images, APK)
│   ├── files/SweetHome.apk      # Android APK
│   ├── fonts/                   # Madani Arabic (woff2 + ttf)
│   └── firebase-messaging-sw.js # FCM service worker
├── package.json                 # 18 prod + 7 dev dependencies
├── next.config.mjs              # Next.js config
├── postcss.config.mjs           # PostCSS + Tailwind
├── jsconfig.json                # Path aliases (@/* → ./)
└── security-audit-report.md     # Previous security audit
```

### Route Summary (33 pages)

| Type | Routes | Count |
|------|--------|-------|
| Public | `/`, `/login`, `/register/*`, `/forgot-password`, `/auth/choose-role`, `/properties`, `/property/[id]`, `/terms`, `/privacy`, `/faq`, `/support`, `/onboarding` | 14 |
| Protected (auth only) | `/profile`, `/settings`, `/change-password`, `/account-verification`, `/favorites`, `/booked-properties`, `/reservations`, `/notifications`, `/payments`, `/my-rates`, `/reports`, `/blocked` | 12 |
| Owner only | `/owner/properties`, `/owner/properties/add`, `/owner/reservations`, `/owner/bookings`, `/owner/calendar`, `/owner/profits`, `/owner/account-book` | 7 |

---

## 2. Architecture Overview

### Layout Hierarchy

```
app/layout.js (Server Component — root HTML, fonts, metadata)
  └── app/ClientLayout.js (Client Component — 804 lines)
        ├── <NotificationsProvider>     (context)
        │   └── <FavoritesProvider>     (context)
        │       └── <main>{children}</main>
        ├── <BottomNav />               (mobile, authenticated only)
        └── <NotificationHandler />     (FCM push notifications)
```

- **No nested layouts** — flat route structure
- **No `middleware.js`** — all route protection is client-side only
- Nav bar hidden on auth pages (`/login`, `/register/*`, `/blocked`, `/forgot-password`, `/auth/choose-role`)

### Data Flow Pattern

```
Page (useEffect on mount)
  → API call (apiFetch from app/utils/api.js)
    → AuthService.getToken() → Authorization: Bearer <JWT>
    → fetch() to https://45.93.137.91.nip.io/api/{endpoint}
    → Response: auto-unwrap { data: ... } envelope
    → Return parsed data or throw on non-ok
  → Component state (useState)
  → Render UI with Tailwind classes
```

---

## 3. API Layer

**File:** `app/utils/api.js` (1198 lines — 370 commented legacy + 828 active)
**Ratings API:** `app/utils/ratings.js` (separate file with own `apiFetch`)

### Fetch Helpers

| Function | Lines | Method | Auth | Error Handling | Return Type |
|----------|-------|--------|------|----------------|-------------|
| `apiFetch(endpoint, options)` | 421-478 | Any | Auto Bearer | Throws on non-ok (except 206) | `data` (auto-unwrapped) |
| `authFetch(endpoint, body, token)` | 483-524 | POST | Manual param | Returns `{status,data,ok,message}` | Object |
| `reportFetch(endpoint, body)` | 526-558 | POST | None | Returns `{status,data,ok,message}` | Object |
| `multipartAuthFetch(endpoint, formData)` | 772-803 | POST | Auto Bearer | Returns `{status,data,ok,message}` | Object |

### Exported API Functions (47 total)

| Category | Functions | Count |
|----------|-----------|-------|
| Rent Properties | `getRentProperties`, `getRentProperty`, `getRentPropertyLocations`, `filterRentProperties` | 4 |
| Sale Properties | `getSaleProperties`, `getSaleProperty`, `getSalePropertyById` | 3 |
| Generic Property | `getProperty` | 1 |
| Recommendations | `getRecommendations`, `getTopRecommendations` | 2 |
| Reservations | `getAvailableDateRanges`, `getReservations`, `getReservation`, `checkAvailability`, `bookReservation`, `getUserReservations`, `getOwnerReservationRequests`, `getOwnerReservationsByStatuses`, `ownerConfirmReservation`, `confirmDepositPayment`, `adminConfirmDeposit`, `updateBookingStatus`, `payDeposit` | 13 |
| Owner Management | `getMyRentListings`, `getMySaleListings`, `addRentProperty`, `addSaleProperty`, `editRentProperty`, `editSaleProperty`, `updateRentPropertyStatus`, `updateSalePropertyStatus`, `getOwnerContactInformation`, `getOwnerStatistics` | 10 |
| Auth | `loginWithEmail`, `loginWithPhone`, `sendEmailOTP`, `sendPhoneOTP`, `verifyEmail`, `verifyPhone`, `changePassword`, `requestForgetPasswordOtp`, `verifyForgetPasswordOtp`, `resetPassword`, `deleteMyAccount` | 11 |
| Registration | `addOwner`, `addCustomer`, `registerRealEstateAgent` | 3 |
| Favorites | `getUserFavoriteProperties`, `addFavoriteProperty`, `removeFavoriteProperty` | 3 |
| Notifications | `getUserNotifications`, `setFCMToken` | 2 |
| Terms | `getARTerms`, `getENTerms`, `addOrUpdateTerms` | 3 |
| Currencies | `getCurrencies` | 1 |
| Files | `uploadPicture` | 1 |
| Reports | `sendGeneralReport`, `submitReport`, `submitReservationReport`, `updateReservationReport`, `submitSaleReport`, `updateSaleReport` | 6 |
| Profile | `getCustomerByUserId`, `getOwnerByUserId` | 2 |

### Ratings API (5 functions)

`addPropertyRating`, `addCustomerRating`, `getPropertyRatings`, `getCustomerRatings`, `getPropertyAverageRating`

### API Endpoint Coverage

| HTTP Method | Count | Examples |
|-------------|-------|----------|
| GET | 26 | `/RentProperties/GetRentProperties`, `/Reservations/GetAvailableDates/available/${id}` |
| POST | 17 | `/Auth/LogInWithEmail`, `/Reservations/PayDeposit/pay-deposit`, `/Rating/AddPropertyRating` |
| PUT | 8 | `/RentProperties/EditRentProperty/${id}`, `/Reservations/AdminConfirmDeposit/admin-confirm-deposit` |
| DELETE | 2 | `/FavoriteProperty/Remove`, `/User/DeleteMyAccount` |

---

## 4. State Management

### Context Providers

| Context | File | State | Consumers | Status |
|---------|------|-------|-----------|--------|
| **FavoritesProvider** | `app/contexts/FavoritesContext.js` | `favorites[]`, `isLoading` | `FloatingSidebar`, `/favorites`, `/properties`, `/property/[id]` | ✅ Active |
| **NotificationsProvider** | `app/contexts/NotificationsContext.js` | `notifications[]`, `unreadCount`, `isLoading` | `BottomNav`, `FloatingSidebar` | ✅ Active |
| **PropertyContext** | `app/contexts/PropertyContext.js` | `properties[]`, `loading`, `error` | None | ❌ Orphaned (never mounted) |
| **PropertyContext** | `app/utils/PropertyContext.js` | Same as above | None | ❌ Orphaned duplicate |

### localStorage Keys (10 actively written, ~5 legacy read-only)

| Key | Data | Written By | Read By |
|-----|------|------------|---------|
| `auth_token` | JWT string | `AuthService.addToken()` | `AuthService.getToken()`, `firebase.js` |
| `cached_user` | User profile JSON | `AuthService.cacheUser()` | `AuthService.getCachedUser()` |
| `language` | "en" or "ar" | `ClientLayout.js` | `ClientLayout.js` |
| `sweethome_onboarding_completed` | "true" | `/onboarding/page.js` | `/onboarding/page.js` |
| `ownerProperties` | Properties array JSON | `/owner/properties/page.js` | `/owner/calendar/page.js` |
| `ownerBookings` | Bookings array JSON | `/owner/bookings/page.js` | `/owner/bookings/page.js` |
| `ownerProfitsTable` | Profit data JSON | `/owner/profits/page.js` | `/owner/profits/page.js` |
| `userProfile` | Profile form data JSON | `/profile/page.js` | `/profile/page.js` |
| `userAvatar` | Base64 data URL | `/profile/page.js` | `/profile/page.js` |
| `token`, `accessToken`, `authToken` | (legacy reads only) | — | `/settings`, `/payments`, `/reservations` |

### Auth Flow

```
Login (app/login/page.js)
  → loginWithEmail() / loginWithPhone()
  → authFetch(POST /Auth/LogInWithEmail, { credential, password, device: 0 })
  → 200: AuthService.addToken(token) → localStorage.setItem('auth_token', token)
  → 206: OTP required → sendEmailOTP() → verifyEmail(code) → get final token
  → AuthService.cacheUser(user) → localStorage.setItem('cached_user', ...)
  → router.push('/')

ClientLayout.js (every page navigation)
  → AuthService.getUser() → decode JWT payload (base64 atob)
  → setUser({ name, email, phone, role: isOwner() ? 'owner' : 'customer' })
  → UI branches on user.role (show owner nav / customer nav / guest nav)

Page-level checks
  → Each protected page independently calls:
    AuthService.isAuthenticated() → else router.push('/login')
    AuthService.isOwner() → else router.push('/')
```

---

## 5. Component Architecture

### Component Inventory (14 reusable components)

| Component | File | Lines | Purpose | State |
|-----------|------|-------|---------|-------|
| HeroSearch | `components/home/HeroSearch.js` | 321 | Hero search with filters | `filters`, login dialog |
| PropertyMap (home) | `components/home/PropertyMap.js` | 287 | Map with markers + popup | `selectedProperty`, map ref |
| PropertyMap (property) | `components/property/PropertyMap.js` | 166 | Map at property detail | Tooltip state |
| BookingCalendar | `components/property/BookingCalendar.js` | 124 | Monthly booking grid | `currentMonth`, `selectedStart` |
| PropertyMapWithMarkers | `components/PropertyMapWithMarkers.js` | 100 | Generic Leaflet map | Map ref, markers ref |
| StarRating | `components/ratings/StarRating.js` | 134 | 5-star input | `hoverRating` |
| PropertyRatingList | `components/ratings/PropertyRatingList.js` | 286 | Paginated reviews | `ratings`, `page`, `loading` |
| PropertyRatingForm | `components/ratings/PropertyRatingForm.js` | 317 | 4-field rating form | Clean/services/owner/experience |
| CustomerRatingForm | `components/ratings/CustomerRatingForm.js` | 92 | 3-field rating form | Furn/terms/behavior |
| BottomNav | `components/BottomNav.js` | 58 | Mobile bottom bar | Badge from context |
| FloatingSidebar | `components/FloatingSidebar.js` | 158 | Quick-access buttons | Framer-motion variants |
| NavLinks | `components/NavLinks.js` | 42 | Nav link atoms | `usePathname` active |
| NotificationHandler | `components/NotificationHandler.js` | 151 | FCM push handler | Permission state |

### Largest Page Files

| Rank | File | Lines | Complexity |
|------|------|-------|------------|
| 1 | `api.js` | 1198 | 60+ functions, 4 fetch helpers, 370 lines commented |
| 2 | `PropertyDetail.js` | 1743 | 56 imports, 8+ state vars, booking calendar, image gallery, owner check, ratings, map |
| 3 | `owner/properties/page.js` | 2057 | CRUD + modals + localStorage caching + API calls |
| 4 | `ClientLayout.js` | 804 | Nav (desktop+mobile), user menu, language switcher, context providers |
| 5 | `owner/properties/add/page.js` | 700+ | Multi-step form with map, image upload, pricing |
| 6 | `app/page.js` (Home) | 623 | Property fetching, multi-filter, hero, map, feature cards |

---

## 6. Key Patterns

### Data Fetching (4 Patterns)

| Pattern | Usage | Found In |
|---------|-------|----------|
| `useEffect` + `useState` | ~90% of pages | Most pages |
| Context-level fetch | 2 providers | `FavoritesContext`, `NotificationsContext` |
| localStorage cache | Owner dashboards | `owner/bookings`, `owner/calendar`, `owner/profits` |
| Mock data fallback | 3 owner pages | `owner/bookings`, `owner/calendar`, `owner/profits` |

### Styling

- 100% Tailwind CSS v4 (utility classes, no CSS modules)
- Custom `globals.css`: Madani Arabic fonts (9 weights), Leaflet overrides, keyframe animations
- Color palette: `amber-500/600` (primary), `#ede6e6` (bg), `#156874` (accent teal)
- RTL-first with dynamic LTR switching via `currentLanguage` state

### Animations (Framer Motion v12.29.2)

- `initial/animate` opacity + y/x translations (section reveals)
- `whileHover`/`whileTap` scale (buttons, interactive elements)
- `AnimatePresence` (property popups, user menus)
- `whileInView` + `viewport` (scroll-triggered animations on home page)
- `staggerChildren` (hero text)
- Spring transitions `{ type: "spring", damping: 25, stiffness: 300 }`

### Form Handling

- **All forms**: Controlled `useState` — no React Hook Form, Formik, or `useReducer`
- **Validation**: Inline `value === 0 && <p className="text-red-500">مطلوب</p>`
- **No form libraries** — all hand-rolled

### Responsive Breakpoints

| Breakpoint | Layout |
|------------|--------|
| Default (mobile) | Single column, BottomNav, hamburger menu |
| `md:` (768px) | Desktop nav, 2-3 column grids |
| `lg:` (1024px) | PropertyDetail sidebar, 3-column grids |

---

## 7. Owner Pages Analysis (Dashboard Section)

| Route | File | Lines | Status | Data Source |
|-------|------|-------|--------|-------------|
| `/owner/properties` | `owner/properties/page.js` | 2057 | ✅ Active | API (`getMyRentListings`, `getMySaleListings`) + localStorage cache |
| `/owner/properties/add` | `owner/properties/add/page.js` | 700+ | ✅ Active | API (`addRentProperty`, `addSaleProperty`, `uploadPicture`) |
| `/owner/reservations` | `owner/reservations/page.js` | 1400+ | ❌ Commented out | Mock data (commented) |
| `/owner/bookings` | `owner/bookings/page.js` | 560+ | ⚠️ Demo | localStorage mock data only |
| `/owner/calendar` | `owner/calendar/page.js` | 580+ | ⚠️ Demo | localStorage mock data only |
| `/owner/profits` | `owner/profits/page.js` | 600+ | ⚠️ Demo | localStorage mock data only |
| `/owner/account-book` | `owner/account-book/page.js` | 500+ | ✅ Active | API (`getOwnerStatistics`) |

---

## 8. Admin Functionality

| Component | Status | Data Source |
|-----------|--------|-------------|
| BookingRequests | ✅ Active | Real API (`getReservations`, `adminConfirmDeposit`) |
| Users | ❌ Not implemented | — |
| Properties | ❌ Not implemented | — |
| LedgerBook | ⚠️ Mock only | 3 hardcoded mock transactions |
| Dashboard | ❌ Not implemented | — |

Designed for internal admin use at `/admin` — tabs for Bookings/Users/Properties/Ledger/Dashboard.

---

## 9. Known Technical Debt

### Dead Code

| File | Dead Lines | Issue |
|------|-----------|-------|
| `api.js` | Lines 1-370 (370 lines) | Entire legacy version commented out |
| `StarRating.js` | Lines 1-93 (93 lines) | Old framer-motion version commented out |
| `PropertyRatingList.js` | ~150 lines | Old version commented out |
| `PropertyRatingForm.js` | ~220 lines | Old version commented out |
| `contexts/PropertyContext.js` | Entire file | Never mounted |
| `utils/PropertyContext.js` | Entire file | Duplicate orphan |

### Code Duplication

| Pattern | Files | Description |
|---------|-------|-------------|
| Leaflet maps | 3 separate files | `PropertyMapWithMarkers.js`, `home/PropertyMap.js`, `property/PropertyMap.js` — all setup Leaflet identically |
| Rating forms | `PropertyRatingForm.js` (317) + `CustomerRatingForm.js` (92) | ~75% code overlap; both define identical `RatingField` inline |
| formatCurrency | 4+ locations | Scattered across files with slightly different logic |
| Image URL building | 4+ locations | Different implementations for same task |
| Notifications page | `/notifications/page.js` vs `NotificationsContext` | Page duplicates all context state/logic |

### Architecture Issues

| Issue | Impact |
|-------|--------|
| No middleware.js | All route protection is client-side only |
| JWT in localStorage | XSS-vulnerable token storage |
| Client-side role checks | Users can modify JWT to elevate privileges |
| Owner pages use mock data | `/owner/bookings`, `/owner/calendar`, `/owner/profits` are demo-only |
| 3 unused UI libraries | DaisyUI, Flowbite, Yandex Maps imported but never used |
| No TypeScript | 112 JS files, no type safety |
| No ESLint | No linting configured |
| No testing framework | Zero tests |
| Flat route structure | No nested layouts; all pages share root layout |
| Active console.log | ~30+ files with console.log statements (security risk) |

---

## 10. Dependencies

### Production (18)

| Package | Version | Purpose |
|---------|---------|---------|
| next | 16.1.6 | Framework |
| react / react-dom | ^18.3.1 | UI |
| firebase | ^12.11.0 | FCM push notifications |
| leaflet / react-leaflet | 1.9.4 / 4.2.1 | Maps |
| @pbe/react-yandex-maps | ^1.2.5 | Yandex Maps (unused) |
| framer-motion | ^12.29.2 | Animations |
| lucide-react | ^0.563.0 | Icons |
| flowbite / flowbite-react | 4.0.1 / 0.12.16 | UI library (unused) |
| react-hot-toast | ^2.6.0 | Toasts |
| i18next / react-i18next / i18next-browser-languagedetector | 25.8 / 16.5 / 8.2 | i18n |
| jspdf / html2canvas | 4.2.1 / 1.4.1 | PDF generation |
| xlsx | ^0.18.5 | Excel export |
| react-intersection-observer | ^10.0.3 | Scroll detection |

### Dev (7)

| Package | Version | Purpose |
|---------|---------|---------|
| tailwindcss | ^4.1.18 | CSS framework |
| @tailwindcss/postcss | ^4 | PostCSS plugin |
| postcss / autoprefixer | ^8.5.6 / ^10.4.23 | CSS processing |
| daisyui | ^5.5.14 | UI components (unused) |
| babel-plugin-react-compiler | 1.0.0 | React compiler optimization |

### Missing (notable absences)
- No TypeScript
- No ESLint
- No testing (Jest, Playwright, Cypress)
- No state management library (Redux, Zustand)
- No data fetching library (React Query, SWR)
- No form library (React Hook Form, Formik)
- No security lib (helmet, cors, csurf)
- No HTTP client (axios, ky)
- No JWT lib (jsonwebtoken, jose)

---

## 11. Security Summary

*(See `security-audit-report.md` for full details)*

| # | Finding | Severity |
|---|---------|----------|
| 1 | JWT in localStorage (XSS-theft) | 🔴 Critical |
| 2 | Stored XSS via Leaflet popup HTML | 🔴 Critical |
| 3 | OTP code logged to console | 🔴 Critical |
| 4 | No server-side middleware | 🔴 Critical |
| 5 | Passwords in URL query params | 🔴 Critical |
| 6 | IDOR on property edit/status APIs | 🔴 Critical |
| 7 | Client-only role checks | 🟠 High |
| 8 | HTTP endpoints leak tokens | 🟠 High |
| 9 | No CSP/security headers | 🟠 High |
| 10 | Mass assignment via spread | 🟠 High |
| 11 | Error messages leak internals | 🟠 High |
| 12 | Hardcoded IPs (10+ files) | 🟡 Medium |

---

## 12. File Size Heatmap

| Size Range | Files | Examples |
|------------|-------|----------|
| 1500-2100 lines | 2 | `PropertyDetail.js` (1743), `owner/properties/page.js` (2057) |
| 600-1200 lines | 6 | `api.js` (1198), `ClientLayout.js` (804), `login/page.js` (800+), `owner/properties/add/page.js` (700+), `app/page.js` (623), `owner/bookings/page.js` (560+) |
| 200-600 lines | 15 | Most page files |
| < 200 lines | ~70 | Enum files, smaller components, error/loading pages |
