diff --git a/.gitignore b/.gitignore index 7d2a517..b362b0b 100644 --- a/.gitignore +++ b/.gitignore @@ -5,3 +5,5 @@ dist .next !.env.example data.ms/ +data.ms/ +*.mdb diff --git a/apps/core-api/src/middlewares/rateLimit.middleware.ts b/apps/core-api/src/middlewares/rateLimit.middleware.ts index 834a972..cf4a9d5 100644 --- a/apps/core-api/src/middlewares/rateLimit.middleware.ts +++ b/apps/core-api/src/middlewares/rateLimit.middleware.ts @@ -1,4 +1,5 @@ -import { rateLimit } from 'express-rate-limit'; +import { Request, Response, NextFunction } from 'express'; +import { rateLimit, Options } from 'express-rate-limit'; export const authLimiter = rateLimit({ windowMs: 15 * 60 * 1000, // 15 minutes @@ -9,7 +10,7 @@ export const authLimiter = rateLimit({ success: false, message: "Too many authentication attempts. Please try again later.", }, - handler: (req, res, next, options) => { + handler: (req: Request, res: Response, next: NextFunction, options: Options) => { res.status(429).json(options.message); }, }); diff --git a/apps/web/app/brand-dashboard/bookings/page.tsx b/apps/web/app/brand-dashboard/bookings/page.tsx index 7015f36..91118b3 100644 --- a/apps/web/app/brand-dashboard/bookings/page.tsx +++ b/apps/web/app/brand-dashboard/bookings/page.tsx @@ -1,7 +1,7 @@ "use client"; import React, { useState, useEffect, Suspense } from "react"; -import { Search, ChevronRight, CheckCircle2, Loader2, ShieldCheck, Download, Undo2, Ban } from "lucide-react"; +import { Search, ChevronRight, ChevronLeft, CheckCircle2, Loader2, ShieldCheck, Download, Undo2, Ban, Activity } from "lucide-react"; import { useSearchParams } from "next/navigation"; import Image from "next/image"; @@ -10,15 +10,32 @@ import { SecureMediaPreview } from "@/components/shared/SecureMediaPreview"; export default function BrandBookingsPage() { return ( - }> + }> ); } +interface Order { + _id: string; + connectionId: string; + status: string; + workStatus: string; + deliverableUrl?: string; + amount: number; + createdAt: string; + dueDate?: string; + influencerProfile?: { + fullName?: string; + username?: string; + profileImageUrl?: string; + }; + gigId?: { title: string }; + rejectionNote?: string; +} + function BrandBookingsContent() { - // eslint-disable-next-line @typescript-eslint/no-explicit-any - const [bookingsData, setBookingsData] = useState([]); + const [bookingsData, setBookingsData] = useState([]); const [loading, setLoading] = useState(true); const [selectedId, setSelectedId] = useState(null); const [activeFilter, setActiveFilter] = useState("All"); @@ -44,11 +61,11 @@ function BrandBookingsContent() { const getStatusStyles = (status: string) => { switch (status) { - case "COMPLETED": return "bg-emerald-50 text-emerald-600"; - case "IN_ESCROW": return "bg-blue-50 text-blue-600"; - case "PENDING": return "bg-orange-50 text-orange-600 font-bold"; - case "DISPUTED": return "bg-rose-50 text-rose-600"; - default: return "bg-gray-100 text-gray-800"; + case "COMPLETED": return "bg-emerald-100/80 text-emerald-700 border border-emerald-200"; + case "IN_ESCROW": return "bg-blue-100/80 text-blue-700 border border-blue-200"; + case "PENDING": return "bg-orange-100/80 text-orange-700 border border-orange-200 font-bold"; + case "DISPUTED": return "bg-rose-100/80 text-rose-700 border border-rose-200"; + default: return "bg-slate-100 text-slate-600 border border-slate-200"; } }; @@ -109,7 +126,7 @@ function BrandBookingsContent() { if (loading) { return ( -
+
); @@ -132,102 +149,108 @@ function BrandBookingsContent() { }; return ( -
+
{/* Header Area */} -
+
-

Bookings

-

Track and manage your ongoing collaborations

+

Bookings

+

Track and manage your ongoing collaborations

- {/* Search */} -
- - setSearchQuery(e.target.value)} - /> -
- {/* Filters */} -
+
{["All", "Active", "Completed", "Disputed"].map((filter) => ( ))}
+ + {/* Search */} +
+ + setSearchQuery(e.target.value)} + /> +
-
+
{/* Left Column: Table */} -
-
- +
+
+
- - - - - + + + + + - + {filteredBookings.length === 0 && ( - + )} {filteredBookings.map((booking) => ( setSelectedId(booking._id)} - className={`transition-all cursor-pointer group ${selectedId === booking._id ? "bg-emerald-50/30" : "hover:bg-gray-50/50" + className={`transition-all cursor-pointer group ${selectedId === booking._id ? "bg-emerald-50/30" : "hover:bg-slate-50/80" }`} > - - - - ))} @@ -237,93 +260,101 @@ function BrandBookingsContent() { {/* Right Column: Detail View */} -
-
+
+
{!selectedBooking ? ( -
- Select a booking from the list +
+
+ +
+
+

Select a Booking

+

Click on any row in the table to view its details here.

+
) : ( <> -
-
-
+
+ +
+ +
+
{selectedBooking.influencerProfile?.profileImageUrl ? ( { (e.target as HTMLImageElement).style.display = 'none'; }} /> ) : ( -
+
{(selectedBooking.influencerProfile?.fullName || selectedBooking.influencerProfile?.username || "A").charAt(0).toUpperCase()}
)}
-

{selectedBooking.influencerProfile?.fullName || selectedBooking.influencerProfile?.username || "Unknown Influencer"}

- +

{selectedBooking.influencerProfile?.fullName || selectedBooking.influencerProfile?.username || "Unknown Influencer"}

+ {getStatusLabel(selectedBooking.status)}
-
-
- Gig Name - {selectedBooking.gigId?.title} +
+
+ Gig Name + {selectedBooking.gigId?.title}
-
- Order Status - {getStatusLabel(selectedBooking.status)} -
-
- Booked Date - {new Date(selectedBooking.createdAt).toLocaleDateString()} +
+ Booked + {new Date(selectedBooking.createdAt).toLocaleDateString(undefined, { year: 'numeric', month: 'long', day: 'numeric' })}
{selectedBooking.dueDate && ( -
- Due Date -
-
{new Date(selectedBooking.dueDate).toLocaleDateString()}
-
+
+ Due Date + {new Date(selectedBooking.dueDate).toLocaleDateString(undefined, { year: 'numeric', month: 'long', day: 'numeric' })}
)} -
- Total Price - ₹{(selectedBooking.amount || 0).toLocaleString()} +
+ Total Price + ₹{(selectedBooking.amount || 0).toLocaleString()}
{/* Timeline */}
-

Timeline

+

Timeline

{generateTimeline(selectedBooking.status, selectedBooking.workStatus).map((step, idx) => (
-
{step.status === 'completed' ? ( - + ) : ( -
+
)}
{idx !== 3 && ( -
)}
-

{step.label}

@@ -337,22 +368,24 @@ function BrandBookingsContent() {
-
+
{selectedBooking.status === "IN_ESCROW" && selectedBooking.workStatus === "SUBMITTED" ? (
-
-

Secure Deliverable Preview

- +
+

Secure Deliverable Preview

+ {selectedBooking.deliverableUrl && ( + + )}
{showRejectForm ? (
InfluencerGig NamePrice
InfluencerGig NamePrice
No bookings found +
+ +

No bookings found

+

Try changing the filters above.

+
+
-
-
+
+
+
{booking.influencerProfile?.profileImageUrl ? ( { (e.target as HTMLImageElement).style.display = 'none'; }} /> ) : ( -
+
{(booking.influencerProfile?.fullName || booking.influencerProfile?.username || "A").charAt(0).toUpperCase()}
)}
- {booking.influencerProfile?.fullName || booking.influencerProfile?.username || "Unknown Influencer"} + {booking.influencerProfile?.fullName || booking.influencerProfile?.username || "Unknown Influencer"}
- {booking.gigId?.title} + + {booking.gigId?.title} - + + {getStatusLabel(booking.status)} - + +