From dbbbbd26f4cbe7e07e06f146b35af79c2d5dfa57 Mon Sep 17 00:00:00 2001 From: delta-lynx-89e8 Date: Sun, 22 Feb 2026 15:33:29 -0800 Subject: [PATCH] Add rental system: listings, bookings, payments, payouts, reviews MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Full rental marketplace with 6 categories (apartment, house, car, motorcycle, bicycle, ebike). Booking workflow: create → confirm → pay → active → complete → payout. Landlord dashboard, admin moderation, availability calendar, Stripe Connect payouts. 14 QA bugs found and fixed including validator schemas, API response types, HTTP methods. Co-Authored-By: Claude Opus 4.6 --- client/package.json | 9 +- client/src/components/ReportModal.tsx | 97 ++++ client/src/components/layout/AdminLayout.tsx | 51 ++ .../src/components/layout/DashboardLayout.tsx | 4 +- client/src/components/layout/Header.tsx | 20 +- .../src/components/layout/LandlordLayout.tsx | 48 ++ client/src/components/layout/RequireRole.tsx | 21 + .../rentals/AvailabilityCalendar.tsx | 169 ++++++ client/src/components/rentals/BookingForm.tsx | 176 +++++++ .../components/rentals/BookingStatusBadge.tsx | 25 + .../src/components/rentals/PriceDisplay.tsx | 45 ++ client/src/components/rentals/RentalCard.tsx | 110 ++++ .../rentals/RentalCategorySidebar.tsx | 47 ++ client/src/components/rentals/RentalGrid.tsx | 24 + client/src/components/rentals/ReviewCard.tsx | 70 +++ client/src/components/rentals/ReviewForm.tsx | 111 ++++ client/src/components/ui/DataTable.tsx | 115 +++++ client/src/components/ui/StatCard.tsx | 32 ++ client/src/context/AuthContext.tsx | 11 +- client/src/pages/CreateRentalPage.tsx | 323 ++++++++++++ client/src/pages/EditRentalPage.tsx | 370 ++++++++++++++ client/src/pages/MyBookingsPage.tsx | 216 ++++++++ client/src/pages/NotificationsPage.tsx | 40 +- client/src/pages/ProductDetailPage.tsx | 6 +- client/src/pages/RentalDetailPage.tsx | 288 +++++++++++ client/src/pages/RentalsPage.tsx | 143 ++++++ client/src/pages/admin/AdminBookingsPage.tsx | 130 +++++ client/src/pages/admin/AdminDashboardPage.tsx | 72 +++ client/src/pages/admin/AdminListingsPage.tsx | 95 ++++ .../src/pages/admin/AdminModerationPage.tsx | 111 ++++ client/src/pages/admin/AdminPaymentsPage.tsx | 82 +++ .../pages/admin/AdminRentalPayoutsPage.tsx | 154 ++++++ client/src/pages/admin/AdminRentalsPage.tsx | 184 +++++++ client/src/pages/admin/AdminReportsPage.tsx | 105 ++++ client/src/pages/admin/AdminSettingsPage.tsx | 188 +++++++ .../src/pages/admin/AdminUserDetailPage.tsx | 195 +++++++ client/src/pages/admin/AdminUsersPage.tsx | 89 ++++ .../pages/landlord/LandlordBookingsPage.tsx | 176 +++++++ .../pages/landlord/LandlordCalendarPage.tsx | 272 ++++++++++ .../pages/landlord/LandlordDashboardPage.tsx | 113 +++++ .../pages/landlord/LandlordListingsPage.tsx | 156 ++++++ .../pages/landlord/LandlordPayoutsPage.tsx | 160 ++++++ .../pages/landlord/LandlordReviewsPage.tsx | 170 +++++++ client/src/router.tsx | 62 +++ client/src/types/index.ts | 69 ++- client/src/types/rental.ts | 157 ++++++ docs/README.md | 287 ++++++++--- docs/architecture.md | 332 ++++++++++++ package-lock.json | 399 ++++++++++++++- .../migration.sql | 173 +++++++ .../migration.sql | 336 ++++++++++++ server/prisma/schema.prisma | 480 +++++++++++++++++- server/prisma/seed.ts | 318 ++++++++++++ server/src/index.ts | 21 +- server/src/middleware/auth.ts | 1 + server/src/middleware/checkBanned.ts | 24 + server/src/middleware/requireRole.ts | 47 ++ server/src/routes/admin/bookings.ts | 38 ++ server/src/routes/admin/index.ts | 30 ++ server/src/routes/admin/listings.ts | 187 +++++++ server/src/routes/admin/moderation.ts | 73 +++ server/src/routes/admin/payments.ts | 65 +++ server/src/routes/admin/rental-payouts.ts | 109 ++++ server/src/routes/admin/rentals.ts | 150 ++++++ server/src/routes/admin/reports.ts | 107 ++++ server/src/routes/admin/settings.ts | 43 ++ server/src/routes/admin/stats.ts | 83 +++ server/src/routes/admin/users.ts | 195 +++++++ server/src/routes/auth.ts | 7 +- server/src/routes/booking.ts | 357 +++++++++++++ server/src/routes/listing.ts | 17 +- server/src/routes/offer.ts | 20 + server/src/routes/payment.ts | 9 +- server/src/routes/payout.ts | 116 +++++ server/src/routes/promotion.ts | 72 +++ server/src/routes/rental-payment.ts | 127 +++++ server/src/routes/rental-review.ts | 103 ++++ server/src/routes/rental.ts | 406 +++++++++++++++ server/src/routes/report.ts | 45 ++ server/src/routes/subscription.ts | 76 +++ server/src/utils/moderation.ts | 82 +++ server/src/utils/rental.ts | 134 +++++ server/src/validators/admin.ts | 35 ++ server/src/validators/booking.ts | 17 + server/src/validators/rental-review.ts | 11 + server/src/validators/rental.ts | 39 ++ server/src/validators/report.ts | 8 + отчеты/отчет-реализация.md | 319 ++++++++++++ отчеты/план-админ-модерация-монетизация.md | 274 ++++++++++ отчеты/список-файлов.md | 93 ++++ 90 files changed, 11052 insertions(+), 124 deletions(-) create mode 100644 client/src/components/ReportModal.tsx create mode 100644 client/src/components/layout/AdminLayout.tsx create mode 100644 client/src/components/layout/LandlordLayout.tsx create mode 100644 client/src/components/layout/RequireRole.tsx create mode 100644 client/src/components/rentals/AvailabilityCalendar.tsx create mode 100644 client/src/components/rentals/BookingForm.tsx create mode 100644 client/src/components/rentals/BookingStatusBadge.tsx create mode 100644 client/src/components/rentals/PriceDisplay.tsx create mode 100644 client/src/components/rentals/RentalCard.tsx create mode 100644 client/src/components/rentals/RentalCategorySidebar.tsx create mode 100644 client/src/components/rentals/RentalGrid.tsx create mode 100644 client/src/components/rentals/ReviewCard.tsx create mode 100644 client/src/components/rentals/ReviewForm.tsx create mode 100644 client/src/components/ui/DataTable.tsx create mode 100644 client/src/components/ui/StatCard.tsx create mode 100644 client/src/pages/CreateRentalPage.tsx create mode 100644 client/src/pages/EditRentalPage.tsx create mode 100644 client/src/pages/MyBookingsPage.tsx create mode 100644 client/src/pages/RentalDetailPage.tsx create mode 100644 client/src/pages/RentalsPage.tsx create mode 100644 client/src/pages/admin/AdminBookingsPage.tsx create mode 100644 client/src/pages/admin/AdminDashboardPage.tsx create mode 100644 client/src/pages/admin/AdminListingsPage.tsx create mode 100644 client/src/pages/admin/AdminModerationPage.tsx create mode 100644 client/src/pages/admin/AdminPaymentsPage.tsx create mode 100644 client/src/pages/admin/AdminRentalPayoutsPage.tsx create mode 100644 client/src/pages/admin/AdminRentalsPage.tsx create mode 100644 client/src/pages/admin/AdminReportsPage.tsx create mode 100644 client/src/pages/admin/AdminSettingsPage.tsx create mode 100644 client/src/pages/admin/AdminUserDetailPage.tsx create mode 100644 client/src/pages/admin/AdminUsersPage.tsx create mode 100644 client/src/pages/landlord/LandlordBookingsPage.tsx create mode 100644 client/src/pages/landlord/LandlordCalendarPage.tsx create mode 100644 client/src/pages/landlord/LandlordDashboardPage.tsx create mode 100644 client/src/pages/landlord/LandlordListingsPage.tsx create mode 100644 client/src/pages/landlord/LandlordPayoutsPage.tsx create mode 100644 client/src/pages/landlord/LandlordReviewsPage.tsx create mode 100644 client/src/types/rental.ts create mode 100644 docs/architecture.md create mode 100644 server/prisma/migrations/20260222215922_admin_moderation_monetization/migration.sql create mode 100644 server/prisma/migrations/20260222230611_add_rental_system/migration.sql create mode 100644 server/src/middleware/checkBanned.ts create mode 100644 server/src/middleware/requireRole.ts create mode 100644 server/src/routes/admin/bookings.ts create mode 100644 server/src/routes/admin/index.ts create mode 100644 server/src/routes/admin/listings.ts create mode 100644 server/src/routes/admin/moderation.ts create mode 100644 server/src/routes/admin/payments.ts create mode 100644 server/src/routes/admin/rental-payouts.ts create mode 100644 server/src/routes/admin/rentals.ts create mode 100644 server/src/routes/admin/reports.ts create mode 100644 server/src/routes/admin/settings.ts create mode 100644 server/src/routes/admin/stats.ts create mode 100644 server/src/routes/admin/users.ts create mode 100644 server/src/routes/booking.ts create mode 100644 server/src/routes/payout.ts create mode 100644 server/src/routes/promotion.ts create mode 100644 server/src/routes/rental-payment.ts create mode 100644 server/src/routes/rental-review.ts create mode 100644 server/src/routes/rental.ts create mode 100644 server/src/routes/report.ts create mode 100644 server/src/routes/subscription.ts create mode 100644 server/src/utils/moderation.ts create mode 100644 server/src/utils/rental.ts create mode 100644 server/src/validators/admin.ts create mode 100644 server/src/validators/booking.ts create mode 100644 server/src/validators/rental-review.ts create mode 100644 server/src/validators/rental.ts create mode 100644 server/src/validators/report.ts create mode 100644 отчеты/отчет-реализация.md create mode 100644 отчеты/план-админ-модерация-монетизация.md create mode 100644 отчеты/список-файлов.md diff --git a/client/package.json b/client/package.json index a3af71b..af1d454 100644 --- a/client/package.json +++ b/client/package.json @@ -10,13 +10,14 @@ "preview": "vite preview" }, "dependencies": { + "@stripe/react-stripe-js": "^3.1.0", + "@stripe/stripe-js": "^5.0.0", + "lucide-react": "^0.469.0", "react": "^19.0.0", "react-dom": "^19.0.0", "react-router-dom": "^7.1.0", - "socket.io-client": "^4.8.0", - "@stripe/stripe-js": "^5.0.0", - "@stripe/react-stripe-js": "^3.1.0", - "lucide-react": "^0.469.0" + "recharts": "^3.7.0", + "socket.io-client": "^4.8.0" }, "devDependencies": { "@eslint/js": "^9.17.0", diff --git a/client/src/components/ReportModal.tsx b/client/src/components/ReportModal.tsx new file mode 100644 index 0000000..eec3b9d --- /dev/null +++ b/client/src/components/ReportModal.tsx @@ -0,0 +1,97 @@ +import { useState } from 'react'; +import { Modal } from './ui/Modal'; +import { Button } from './ui/Button'; +import { GradientButton } from './ui/GradientButton'; +import { api } from '../api/client'; +import type { ReportReason } from '../types'; + +interface ReportModalProps { + isOpen: boolean; + onClose: () => void; + targetType: 'LISTING' | 'USER'; + targetId: string; +} + +const REASONS: { value: ReportReason; label: string }[] = [ + { value: 'SPAM', label: 'Spam' }, + { value: 'INAPPROPRIATE', label: 'Inappropriate content' }, + { value: 'SCAM', label: 'Scam / Fraud' }, + { value: 'COUNTERFEIT', label: 'Counterfeit item' }, + { value: 'PROHIBITED_ITEM', label: 'Prohibited item' }, + { value: 'HARASSMENT', label: 'Harassment' }, + { value: 'OTHER', label: 'Other' }, +]; + +export function ReportModal({ isOpen, onClose, targetType, targetId }: ReportModalProps) { + const [reason, setReason] = useState(''); + const [description, setDescription] = useState(''); + const [submitting, setSubmitting] = useState(false); + const [success, setSuccess] = useState(false); + const [error, setError] = useState(''); + + const handleSubmit = async () => { + if (!reason) return; + setSubmitting(true); + setError(''); + try { + await api.post('/reports', { targetType, targetId, reason, description: description || undefined }); + setSuccess(true); + setTimeout(() => { + onClose(); + setSuccess(false); + setReason(''); + setDescription(''); + }, 1500); + } catch (err) { + setError(err instanceof Error ? err.message : 'Failed to submit report'); + } finally { + setSubmitting(false); + } + }; + + return ( + + {success ? ( +
+

Report submitted. Thank you!

+
+ ) : ( + <> + {error &&

{error}

} +

Why are you reporting this?

+
+ {REASONS.map((r) => ( + + ))} +
+
+ +