diff --git a/src/App.tsx b/src/App.tsx index 3fe843b..dfd300f 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -7,6 +7,8 @@ import { Mail, Lock, Eye, EyeOff, Search, Users, Calendar, TrendingUp, Clock, Us import { useState } from "react"; import { motion, AnimatePresence } from "motion/react"; import FlightBookingRafiki from "./imports/FlightBookingRafiki"; +import cityCardsLogo from './assets/city-logo.png'; +import { ImageWithFallback } from "./components/figma/ImageWithFallback"; import Sidebar from "./components/Sidebar"; import Header from "./components/Header"; import Dashboard from "./components/Dashboard"; @@ -31,6 +33,7 @@ export default function App() { const [confirmPassword, setConfirmPassword] = useState(""); const [showPasswordPolicies, setShowPasswordPolicies] = useState(false); const [activeNavItem, setActiveNavItem] = useState("dashboard"); + const [showNotifications, setShowNotifications] = useState(false); // Password validation functions const validatePassword = (password) => { @@ -49,42 +52,62 @@ export default function App() { if (isLoggedIn) { return (
- {/* Fixed Sidebar */} - - - {/* Main Content with left margin for sidebar */} -
- {/* Header with notifications and profile */} -
setActiveNavItem("notifications")} - onNavigateToProfile={() => setActiveNavItem("profile")} + {/* Main Layout Container - Blurred together when notifications open */} +
+ {/* Fixed Sidebar */} + - - {activeNavItem === "dashboard" && } - {(activeNavItem === "booking-table" || activeNavItem === "booking-calendar") && ( - setActiveNavItem("recurring-block")} - /> - )} - {activeNavItem === "recurring-block" && ( - setActiveNavItem("booking-calendar")} /> - )} - {activeNavItem === "redemptions" && } - {activeNavItem === "staff" && } - {activeNavItem === "support" && } - {activeNavItem === "notifications" && } - {activeNavItem === "profile" && } - + {/* Main Content with left margin for sidebar */} +
+ {/* Header with notifications and profile */} +
setActiveNavItem("notifications")} + onNavigateToProfile={() => setActiveNavItem("profile")} + onSignOut={() => setIsLoggedIn(false)} + showNotifications={showNotifications} + onNotificationsChange={setShowNotifications} + renderNotificationsOutside={true} + /> + + + {activeNavItem === "dashboard" && } + {(activeNavItem === "booking-table" || activeNavItem === "booking-calendar") && ( + setActiveNavItem("recurring-block")} + /> + )} + {activeNavItem === "recurring-block" && ( + setActiveNavItem("booking-calendar")} /> + )} + {activeNavItem === "redemptions" && } + {activeNavItem === "staff" && } + {activeNavItem === "support" && } + {activeNavItem === "notifications" && } + {activeNavItem === "profile" && } + +
+ + {/* Notifications Panel - Rendered outside of blurred content */} +
setActiveNavItem("notifications")} + onNavigateToProfile={() => setActiveNavItem("profile")} + onSignOut={() => setIsLoggedIn(false)} + showNotifications={showNotifications} + onNotificationsChange={setShowNotifications} + renderOnlyNotifications={true} + />
); } @@ -101,7 +124,11 @@ export default function App() {

Welcome to

-

CityCards

+
@@ -177,7 +204,7 @@ export default function App() { @@ -190,7 +217,7 @@ export default function App() { e.preventDefault(); setIsLoggedIn(true); }} - className="w-full h-12 bg-gray-900 hover:bg-gray-800 text-white rounded-lg font-medium" + className="w-full h-12 bg-[#F95F62] hover:bg-[#E54B4E] text-white rounded-lg font-medium" > Sign In @@ -236,7 +263,7 @@ export default function App() { e.preventDefault(); setShowOTPVerification(true); }} - className="w-full h-12 bg-gray-600 hover:bg-gray-700 text-white rounded-lg font-medium mt-8" + className="w-full h-12 bg-[#F95F62] hover:bg-[#E54B4E] text-white rounded-lg font-medium mt-8" > Continue @@ -246,7 +273,7 @@ export default function App() { @@ -304,7 +331,7 @@ export default function App() { e.preventDefault(); setShowResetPassword(true); }} - className="w-full h-12 bg-gray-600 hover:bg-gray-700 text-white rounded-lg font-medium mt-8" + className="w-full h-12 bg-[#F95F62] hover:bg-[#E54B4E] text-white rounded-lg font-medium mt-8" > Continue @@ -314,7 +341,7 @@ export default function App() { @@ -439,7 +466,7 @@ export default function App() { setIsLoggedIn(true); } }} - className="w-full h-12 bg-gray-600 hover:bg-gray-700 disabled:bg-gray-300 disabled:cursor-not-allowed text-white rounded-lg font-medium mt-8" + className="w-full h-12 bg-[#F95F62] hover:bg-[#E54B4E] disabled:bg-gray-300 disabled:cursor-not-allowed text-white rounded-lg font-medium mt-8" > Continue @@ -449,7 +476,7 @@ export default function App() { diff --git a/src/assets/city-logo.png b/src/assets/city-logo.png new file mode 100644 index 0000000..6a50adc Binary files /dev/null and b/src/assets/city-logo.png differ diff --git a/src/components/BookingDetailView.tsx b/src/components/BookingDetailView.tsx new file mode 100644 index 0000000..0e45aaa --- /dev/null +++ b/src/components/BookingDetailView.tsx @@ -0,0 +1,166 @@ +import { ArrowLeft } from "lucide-react"; +import { motion } from "motion/react"; +import { Button } from "./ui/button"; +import { Badge } from "./ui/badge"; +import { Table, TableBody, TableCell, TableHead, TableHeader, TableRow } from "./ui/table"; + +interface BookingDetailViewProps { + bookingData: { + fullName: string; + email: string; + cardType: string; + bookingId: string; + date: string; + attendantName: string; + }; + onBack: () => void; +} + +export default function BookingDetailView({ bookingData, onBack }: BookingDetailViewProps) { + // Mock redemption history data + const redemptionHistory = [ + { + date: "2024/9/15", + time: "14:30", + scanned: true + }, + { + date: "2024/9/16", + time: "10:15", + scanned: true + }, + { + date: "2024/9/17", + time: "15:45", + scanned: false + }, + { + date: "2024/9/18", + time: "11:20", + scanned: true + } + ]; + + return ( + +
+ {/* Header with Back Button */} +
+ +

Detail View

+
+ +
+ {/* Customer Information */} +
+

Customer Information

+
+
+

Email

+

{bookingData.email}

+
+
+

Name

+

{bookingData.fullName}

+
+
+

Phone

+

(+971) 050 421 4456

+
+
+
+ + {/* City Card Information */} +
+

City Card Information

+
+
+

Card Type

+

{bookingData.cardType}

+
+
+

Validity

+

Valid

+
+
+
+ + {/* Booking Information */} +
+

Booking Information

+
+
+

Attraction Booked

+

The Enchanted Garden

+
+
+

Booking Date

+

{bookingData.date}

+
+
+

Timeslot

+

10:30AM - 3:30PM

+
+
+
+ + {/* Redemption History */} +
+
+

Redemption History

+
+ +
+ + + + Date + Time + Scanned + + + + {redemptionHistory.map((item, index) => ( + + {item.date} + {item.time} + + {item.scanned ? ( + + Scanned + + ) : ( + + Not Scanned + + )} + + + ))} + +
+
+
+
+
+
+ ); +} diff --git a/src/components/BookingManagementPage.tsx b/src/components/BookingManagementPage.tsx index 689a8c9..ef9f982 100644 --- a/src/components/BookingManagementPage.tsx +++ b/src/components/BookingManagementPage.tsx @@ -2,6 +2,7 @@ import { useState } from "react"; import { motion } from "motion/react"; import { Search, Download, Filter, MoreHorizontal, Eye, Trash2 } from "lucide-react"; import CalendarView from "./CalendarView"; +import BookingDetailView from "./BookingDetailView"; import { Button } from "./ui/button"; import { Input } from "./ui/input"; import { @@ -26,6 +27,8 @@ interface BookingManagementPageProps { export default function BookingManagementPage({ activeView, onNavigateToRecurringBlock }: BookingManagementPageProps) { const [searchQuery, setSearchQuery] = useState(""); + const [selectedBooking, setSelectedBooking] = useState(null); + const [showDetailView, setShowDetailView] = useState(false); // Sample booking data const bookings = [ @@ -137,6 +140,23 @@ export default function BookingManagementPage({ activeView, onNavigateToRecurrin booking.attendantName.toLowerCase().includes(searchQuery.toLowerCase()) ); + // Handle view details click + const handleViewDetails = (booking: any) => { + setSelectedBooking(booking); + setShowDetailView(true); + }; + + // Handle back from detail view + const handleBackFromDetail = () => { + setShowDetailView(false); + setSelectedBooking(null); + }; + + // Show detail view if a booking is selected + if (showDetailView && selectedBooking) { + return ; + } + if (activeView === "booking-calendar") { return (
@@ -188,7 +208,7 @@ export default function BookingManagementPage({ activeView, onNavigateToRecurrin
- @@ -231,7 +251,10 @@ export default function BookingManagementPage({ activeView, onNavigateToRecurrin - + handleViewDetails(booking)} + > View Details @@ -257,7 +280,7 @@ export default function BookingManagementPage({ activeView, onNavigateToRecurrin - + + + + {/* Export Panel */} + + {showExportPanel && ( + +
+
+

Export Dashboard Report

+ +
+ +
+ {/* Start Date */} +
+ + + + + + + + + +
+ + {/* End Date */} +
+ + + + + + + startDate ? date < startDate : false} + /> + + +
+
+ + {/* Export Format Options */} +
+ +
+ setExportFormat('pdf')} + className={`flex items-center justify-center gap-3 p-4 rounded-lg border-2 transition-all ${ + exportFormat === 'pdf' + ? 'border-[#F95F62] bg-[#F95F62]/5' + : 'border-gray-200 bg-white hover:border-gray-300' + }`} + > + +
+

PDF

+

Portable Document

+
+
+ + setExportFormat('excel')} + className={`flex items-center justify-center gap-3 p-4 rounded-lg border-2 transition-all ${ + exportFormat === 'excel' + ? 'border-[#F95F62] bg-[#F95F62]/5' + : 'border-gray-200 bg-white hover:border-gray-300' + }`} + > + +
+

Excel

+

Spreadsheet

+
+
+
+
+ + {/* Export Button */} + +
+
+ )} +
+ + {/* Upcoming Bookings */} + + + Upcoming Bookings + +
+ + + + + + July 19, 2024 + + + 10:30AM - 3:30PM + + + + + + + + + July 20, 2024 + + + 10:30AM - 3:30PM + + + + + + + + + July 21, 2024 + + + 10:30AM - 3:30PM + + +
{/* Quick Links Section */} @@ -31,21 +297,21 @@ export default function Dashboard() { className="mb-8" initial={{ opacity: 0, y: 20 }} animate={{ opacity: 1, y: 0 }} - transition={{ duration: 0.6, delay: 0.1, ease: "easeOut" }} + transition={{ duration: 0.6, delay: 0.6, ease: "easeOut" }} >

Quick Links

@@ -53,14 +319,14 @@ export default function Dashboard() { whileHover={{ scale: 1.1, rotate: -5 }} transition={{ duration: 0.2 }} > - + -

View Redemption Logs

+

View Redemption Logs

Check recent activity

@@ -69,7 +335,7 @@ export default function Dashboard() { setIsRedemptionModalOpen(true)} @@ -136,13 +402,13 @@ export default function Dashboard() { className="mb-8" initial={{ opacity: 0, y: 20 }} animate={{ opacity: 1, y: 0 }} - transition={{ duration: 0.6, delay: 0.5, ease: "easeOut" }} + transition={{ duration: 0.6, delay: 1.0, ease: "easeOut" }} >

Summary

Total Redemptions @@ -168,7 +434,7 @@ export default function Dashboard() { className="bg-white rounded-lg p-6 shadow-sm border border-gray-200 hover:shadow-md transition-all group cursor-pointer" initial={{ opacity: 0, y: 20, scale: 0.95 }} animate={{ opacity: 1, y: 0, scale: 1 }} - transition={{ duration: 0.5, delay: 0.8, ease: "easeOut" }} + transition={{ duration: 0.5, delay: 1.3, ease: "easeOut" }} whileHover={{ y: -2, scale: 1.02 }} >
@@ -177,7 +443,7 @@ export default function Dashboard() { whileHover={{ scale: 1.1, rotate: 10 }} transition={{ duration: 0.3 }} > - +
@@ -236,7 +502,7 @@ export default function Dashboard() { className="bg-white rounded-lg p-6 shadow-sm border border-gray-200 hover:shadow-md transition-all group cursor-pointer" initial={{ opacity: 0, y: 20, scale: 0.95 }} animate={{ opacity: 1, y: 0, scale: 1 }} - transition={{ duration: 0.5, delay: 1.0, ease: "easeOut" }} + transition={{ duration: 0.5, delay: 1.5, ease: "easeOut" }} whileHover={{ y: -2, scale: 1.02 }} >
@@ -274,13 +540,13 @@ export default function Dashboard() { className="grid grid-cols-1 lg:grid-cols-2 gap-6 mb-8" initial={{ opacity: 0, y: 20 }} animate={{ opacity: 1, y: 0 }} - transition={{ duration: 0.6, delay: 1.1, ease: "easeOut" }} + transition={{ duration: 0.6, delay: 1.6, ease: "easeOut" }} >
@@ -289,7 +555,7 @@ export default function Dashboard() { whileHover={{ scale: 1.15, rotate: 15 }} transition={{ duration: 0.3 }} > - +
@@ -371,13 +637,13 @@ export default function Dashboard() { className="mb-8" initial={{ opacity: 0, y: 20 }} animate={{ opacity: 1, y: 0 }} - transition={{ duration: 0.6, delay: 1.4, ease: "easeOut" }} + transition={{ duration: 0.6, delay: 1.9, ease: "easeOut" }} > Graphs @@ -387,7 +653,7 @@ export default function Dashboard() { className="bg-white rounded-lg p-6 shadow-sm border border-gray-200 hover:shadow-md transition-all group" initial={{ opacity: 0, y: 20, scale: 0.95 }} animate={{ opacity: 1, y: 0, scale: 1 }} - transition={{ duration: 0.5, delay: 1.6, ease: "easeOut" }} + transition={{ duration: 0.5, delay: 2.1, ease: "easeOut" }} whileHover={{ y: -2, scale: 1.01 }} > (
- - {/* Upcoming Bookings */} - - - Upcoming Bookings - -
- - - - - - July 19, 2024 - - - 10:30AM - 3:30PM - - - - - - - - - July 20, 2024 - - - 10:30AM - 3:30PM - - - - - - - - - July 21, 2024 - - - 10:30AM - 3:30PM - - -
-
{/* Redemption Modal */} diff --git a/src/components/Header.tsx b/src/components/Header.tsx index d7ce6f6..f7416d7 100644 --- a/src/components/Header.tsx +++ b/src/components/Header.tsx @@ -8,10 +8,14 @@ import { Badge } from "./ui/badge"; interface HeaderProps { onNavigateToNotifications?: () => void; onNavigateToProfile?: () => void; + onSignOut?: () => void; + showNotifications?: boolean; + onNotificationsChange?: (show: boolean) => void; + renderNotificationsOutside?: boolean; + renderOnlyNotifications?: boolean; } -export default function Header({ onNavigateToNotifications, onNavigateToProfile }: HeaderProps) { - const [showNotifications, setShowNotifications] = useState(false); +export default function Header({ onNavigateToNotifications, onNavigateToProfile, onSignOut, showNotifications = false, onNotificationsChange, renderNotificationsOutside = false, renderOnlyNotifications = false }: HeaderProps) { const [showProfileMenu, setShowProfileMenu] = useState(false); const notifications = [ @@ -40,6 +44,85 @@ export default function Header({ onNavigateToNotifications, onNavigateToProfile const unreadCount = notifications.filter(n => n.unread).length; + // If renderOnlyNotifications is true, only render the notifications panel and backdrop + if (renderOnlyNotifications) { + return ( + <> + {/* Notifications Full Height Panel */} + + {showNotifications && ( + +
+
+

Notifications

+ {unreadCount > 0 && ( + + Mark all as read + + )} +
+
+
+ {notifications.map((notification) => ( +
+
+
+
+

+ {notification.title} +

+

+ {notification.message} +

+ + {notification.time} + +
+
+
+ ))} +
+
+ +
+
+ )} +
+ + {/* Notifications Backdrop */} + {showNotifications && ( +
onNotificationsChange?.(false)} + /> + )} + + ); + } + return (
@@ -48,7 +131,7 @@ export default function Header({ onNavigateToNotifications, onNavigateToProfile - {/* Notifications Dropdown */} - - {showNotifications && ( - -
-
-

Notifications

- {unreadCount > 0 && ( - - Mark all as read - - )} -
-
-
- {notifications.map((notification) => ( -
-
-
-
-

- {notification.title} -

-

- {notification.message} -

- - {notification.time} + {/* Only render notifications panel here if not rendering outside */} + {!renderNotificationsOutside && ( + <> + {/* Notifications Full Height Panel */} + + {showNotifications && ( + +
+
+

Notifications

+ {unreadCount > 0 && ( + + Mark all as read -
+ )}
- ))} -
-
- -
- - )} - +
+ {notifications.map((notification) => ( +
+
+
+
+

+ {notification.title} +

+

+ {notification.message} +

+ + {notification.time} + +
+
+
+ ))} +
+
+ +
+ + )} + - {/* Notifications Backdrop */} - {showNotifications && ( -
setShowNotifications(false)} - /> + {/* Notifications Backdrop */} + {showNotifications && ( +
onNotificationsChange?.(false)} + /> + )} + )}
@@ -179,6 +267,10 @@ export default function Header({ onNavigateToNotifications, onNavigateToProfile @@ -264,7 +264,7 @@ export default function RecurringBlockPage({ onNavigateBack }: RecurringBlockPag {day}
{expandedDays.includes(day) && ( - + 2 slots selected )} @@ -300,7 +300,7 @@ export default function RecurringBlockPage({ onNavigateBack }: RecurringBlockPag variant={index < 2 ? "default" : "outline"} className={`h-11 justify-start text-sm font-medium transition-all ${ index < 2 - ? "bg-blue-600 hover:bg-blue-700 text-white shadow-sm" + ? "bg-[#F95F62] hover:bg-[#E54B4E] text-white shadow-sm" : "text-gray-600 hover:text-gray-900 hover:bg-gray-50 border-gray-200" }`} > @@ -319,46 +319,46 @@ export default function RecurringBlockPage({ onNavigateBack }: RecurringBlockPag

Selected Slots Configuration

-
+
-
- 10:00AM - 1:30PM +
+ 10:00AM - 1:30PM
-
- +
- -
- 35 + +
+ 35
- +
-
+
-
- 1:00PM - 3:30PM +
+ 1:00PM - 3:30PM
-
- +
- -
- 25 + +
+ 25
- +
@@ -366,11 +366,11 @@ export default function RecurringBlockPage({ onNavigateBack }: RecurringBlockPag
{/* Repeat Toggle */} -
+
- Repeat Every {day} -

This configuration will repeat weekly

+ Repeat Every {day} +

This configuration will repeat weekly

@@ -393,11 +393,11 @@ export default function RecurringBlockPage({ onNavigateBack }: RecurringBlockPag
Every Monday
{/* Preview Card */} - +

The Enchanted Forest Adventure Park

-
2 time slots
+
2 time slots
@@ -429,7 +429,7 @@ export default function RecurringBlockPage({ onNavigateBack }: RecurringBlockPag {/* Create Button */}
-
diff --git a/src/components/RedemptionModal.tsx b/src/components/RedemptionModal.tsx index 270291a..59fb289 100644 --- a/src/components/RedemptionModal.tsx +++ b/src/components/RedemptionModal.tsx @@ -131,7 +131,7 @@ export default function RedemptionModal({ isOpen, onClose }: RedemptionModalProp @@ -218,7 +218,7 @@ export default function RedemptionModal({ isOpen, onClose }: RedemptionModalProp
diff --git a/src/components/RedemptionsPage.tsx b/src/components/RedemptionsPage.tsx index fcbc01f..1abdfca 100644 --- a/src/components/RedemptionsPage.tsx +++ b/src/components/RedemptionsPage.tsx @@ -256,7 +256,7 @@ export default function RedemptionsPage() { const getCardTypeBadge = (cardType: string) => { return cardType === "Unlimited" - ? Unlimited + ? Unlimited : Selective; }; @@ -315,7 +315,7 @@ export default function RedemptionsPage() { Filter diff --git a/src/components/StaffManagementPage.tsx b/src/components/StaffManagementPage.tsx index e1250a9..3561c14 100644 --- a/src/components/StaffManagementPage.tsx +++ b/src/components/StaffManagementPage.tsx @@ -181,8 +181,8 @@ export default function StaffManagementPage() { const getRoleBadge = (role: string) => { return role === "Manager" - ? Manager - : Scanner; + ? Manager + : Scanner; }; const handleToggleStatus = (idNo: string) => { @@ -375,7 +375,7 @@ export default function StaffManagementPage() { @@ -472,7 +472,7 @@ export default function StaffManagementPage() { @@ -511,7 +511,7 @@ export default function StaffManagementPage() { diff --git a/src/index.css b/src/index.css index cdee59c..08d0910 100644 --- a/src/index.css +++ b/src/index.css @@ -1,3 +1,4 @@ +@import url("https://fonts.googleapis.com/css2?family=Poppins:wght@100;200;300;400;500;600;700;800;900&display=swap"); /*! tailwindcss v4.1.3 | MIT License | https://tailwindcss.com */ @layer properties { @supports (((-webkit-hyphens: none)) and (not (margin-trim: inline))) or ((-moz-orient: inline) and (not (color: rgb(from red r g b)))) { @@ -77,33 +78,22 @@ --color-orange-500: oklch(.705 .213 47.604); --color-green-50: oklch(.982 .018 155.826); --color-green-100: oklch(.962 .044 156.743); - --color-green-200: oklch(.925 .084 155.995); - --color-green-300: oklch(.871 .15 154.449); --color-green-500: oklch(.723 .219 149.579); --color-green-600: oklch(.627 .194 149.214); - --color-green-700: oklch(.527 .154 150.069); --color-green-800: oklch(.448 .119 151.328); - --color-green-900: oklch(.393 .095 152.535); --color-emerald-500: oklch(.696 .17 162.48); --color-teal-500: oklch(.704 .14 182.503); --color-blue-50: oklch(.97 .014 254.604); - --color-blue-100: oklch(.932 .032 255.585); --color-blue-200: oklch(.882 .059 254.128); - --color-blue-300: oklch(.809 .105 251.813); --color-blue-500: oklch(.623 .214 259.815); --color-blue-600: oklch(.546 .245 262.881); --color-blue-700: oklch(.488 .243 264.376); - --color-blue-800: oklch(.424 .199 265.638); - --color-blue-900: oklch(.379 .146 265.522); --color-purple-50: oklch(.977 .014 308.299); --color-purple-100: oklch(.946 .033 307.174); --color-purple-500: oklch(.627 .265 303.9); --color-purple-600: oklch(.558 .288 302.321); --color-purple-800: oklch(.438 .218 303.724); - --color-pink-200: oklch(.899 .061 343.231); - --color-pink-300: oklch(.823 .12 346.018); --color-slate-700: oklch(.372 .044 257.287); - --color-slate-800: oklch(.279 .041 260.031); --color-gray-50: oklch(.985 .002 247.839); --color-gray-100: oklch(.967 .003 264.542); --color-gray-200: oklch(.928 .006 264.531); @@ -134,8 +124,6 @@ --text-2xl--line-height: calc(2 / 1.5); --text-3xl: 1.875rem; --text-3xl--line-height: calc(2.25 / 1.875); - --text-4xl: 2.25rem; - --text-4xl--line-height: calc(2.5 / 2.25); --font-weight-normal: 400; --font-weight-medium: 500; --font-weight-semibold: 600; @@ -405,6 +393,11 @@ } } + body { + background-color: var(--background); + color: var(--foreground); + } + * { border-color: var(--border); outline-color: var(--ring); @@ -419,6 +412,7 @@ body { background-color: var(--background); color: var(--foreground); + font-family: Poppins, sans-serif; } :where(:not(:has([class*=" text-"]), :not(:has([class^="text-"])))) h1 { @@ -473,6 +467,10 @@ pointer-events: none; } + .invisible { + visibility: hidden; + } + .sr-only { clip: rect(0, 0, 0, 0); white-space: nowrap; @@ -609,6 +607,10 @@ left: calc(var(--spacing) * 0); } + .left-1 { + left: calc(var(--spacing) * 1); + } + .left-2 { left: calc(var(--spacing) * 2); } @@ -809,6 +811,16 @@ height: calc(var(--spacing) * 5); } + .size-7 { + width: calc(var(--spacing) * 7); + height: calc(var(--spacing) * 7); + } + + .size-8 { + width: calc(var(--spacing) * 8); + height: calc(var(--spacing) * 8); + } + .size-9 { width: calc(var(--spacing) * 9); height: calc(var(--spacing) * 9); @@ -1006,6 +1018,10 @@ width: calc(var(--spacing) * 64); } + .w-72 { + width: calc(var(--spacing) * 72); + } + .w-80 { width: calc(var(--spacing) * 80); } @@ -1042,6 +1058,10 @@ width: 449px; } + .w-auto { + width: auto; + } + .w-fit { width: fit-content; } @@ -1110,10 +1130,18 @@ caption-side: bottom; } + .border-collapse { + border-collapse: collapse; + } + .origin-\(--radix-dropdown-menu-content-transform-origin\) { transform-origin: var(--radix-dropdown-menu-content-transform-origin); } + .origin-\(--radix-popover-content-transform-origin\) { + transform-origin: var(--radix-popover-content-transform-origin); + } + .origin-\(--radix-select-content-transform-origin\) { transform-origin: var(--radix-select-content-transform-origin); } @@ -1307,6 +1335,12 @@ margin-block-end: calc(calc(var(--spacing) * 8) * calc(1 - var(--tw-space-y-reverse))); } + :where(.space-x-1 > :not(:last-child)) { + --tw-space-x-reverse: 0; + margin-inline-start: calc(calc(var(--spacing) * 1) * var(--tw-space-x-reverse)); + margin-inline-end: calc(calc(var(--spacing) * 1) * calc(1 - var(--tw-space-x-reverse))); + } + :where(.space-x-2 > :not(:last-child)) { --tw-space-x-reverse: 0; margin-inline-start: calc(calc(var(--spacing) * 2) * var(--tw-space-x-reverse)); @@ -1447,17 +1481,30 @@ border-bottom-width: 1px; } + .border-l { + border-left-style: var(--tw-border-style); + border-left-width: 1px; + } + .border-dashed { --tw-border-style: dashed; border-style: dashed; } - .border-blue-200 { - border-color: var(--color-blue-200); + .border-\[\#F95F62\] { + border-color: #f95f62; } - .border-blue-300 { - border-color: var(--color-blue-300); + .border-\[\#F95F62\]\/20 { + border-color: oklab(68.6249% .174448 .0719368 / .2); + } + + .border-\[\#F95F62\]\/30 { + border-color: oklab(68.6249% .174448 .0719368 / .3); + } + + .border-\[\#F95F62\]\/50 { + border-color: oklab(68.6249% .174448 .0719368 / .5); } .border-gray-50 { @@ -1476,14 +1523,6 @@ border-color: var(--color-gray-300); } - .border-green-200 { - border-color: var(--color-green-200); - } - - .border-green-300 { - border-color: var(--color-green-300); - } - .border-input { border-color: var(--input); } @@ -1500,10 +1539,30 @@ border-color: #0000; } + .bg-\[\#F95F62\] { + background-color: #f95f62; + } + + .bg-\[\#F95F62\]\/5 { + background-color: oklab(68.6249% .174448 .0719368 / .05); + } + + .bg-\[\#F95F62\]\/10 { + background-color: oklab(68.6249% .174448 .0719368 / .1); + } + + .bg-\[\#F95F62\]\/20 { + background-color: oklab(68.6249% .174448 .0719368 / .2); + } + .bg-\[\#f6f6f6\] { background-color: #f6f6f6; } + .bg-accent { + background-color: var(--accent); + } + .bg-background { background-color: var(--background); } @@ -1532,10 +1591,6 @@ background-color: var(--color-blue-50); } - .bg-blue-100 { - background-color: var(--color-blue-100); - } - .bg-blue-500 { background-color: var(--color-blue-500); } @@ -1576,14 +1631,6 @@ background-color: var(--color-gray-400); } - .bg-gray-600 { - background-color: var(--color-gray-600); - } - - .bg-gray-800 { - background-color: var(--color-gray-800); - } - .bg-gray-900 { background-color: var(--color-gray-900); } @@ -1618,10 +1665,6 @@ } } - .bg-pink-200 { - background-color: var(--color-pink-200); - } - .bg-popover { background-color: var(--popover); } @@ -1654,10 +1697,6 @@ background-color: var(--secondary); } - .bg-slate-800 { - background-color: var(--color-slate-800); - } - .bg-teal-500 { background-color: var(--color-teal-500); } @@ -1689,6 +1728,10 @@ fill: currentColor; } + .object-contain { + object-fit: contain; + } + .p-0 { padding: calc(var(--spacing) * 0); } @@ -1851,11 +1894,6 @@ line-height: var(--tw-leading, var(--text-3xl--line-height)); } - .text-4xl { - font-size: var(--text-4xl); - line-height: var(--tw-leading, var(--text-4xl--line-height)); - } - .text-base { font-size: var(--text-base); line-height: var(--tw-leading, var(--text-base--line-height)); @@ -1881,6 +1919,10 @@ line-height: var(--tw-leading, var(--text-xs--line-height)); } + .text-\[0\.8rem\] { + font-size: .8rem; + } + .text-\[14px\] { font-size: 14px; } @@ -1943,10 +1985,26 @@ white-space: nowrap; } + .text-\[\#C94145\] { + color: #c94145; + } + + .text-\[\#C94145\]\/80 { + color: oklab(57.076% .158645 .0668682 / .8); + } + + .text-\[\#F95F62\] { + color: #f95f62; + } + .text-\[rgba\(0\,0\,0\,0\.42\)\] { color: #0000006b; } + .text-accent-foreground { + color: var(--accent-foreground); + } + .text-black { color: var(--color-black); } @@ -1955,18 +2013,6 @@ color: var(--color-blue-600); } - .text-blue-700 { - color: var(--color-blue-700); - } - - .text-blue-800 { - color: var(--color-blue-800); - } - - .text-blue-900 { - color: var(--color-blue-900); - } - .text-card-foreground { color: var(--card-foreground); } @@ -1999,6 +2045,10 @@ color: var(--color-gray-700); } + .text-gray-800 { + color: var(--color-gray-800); + } + .text-gray-900 { color: var(--color-gray-900); } @@ -2011,10 +2061,6 @@ color: var(--color-green-800); } - .text-green-900 { - color: var(--color-green-900); - } - .text-muted-foreground { color: var(--muted-foreground); } @@ -2059,6 +2105,16 @@ color: var(--color-white); } + .text-white\/80 { + color: #fffc; + } + + @supports (color: color-mix(in lab, red, red)) { + .text-white\/80 { + color: color-mix(in oklab, var(--color-white) 80%, transparent); + } + } + .lowercase { text-transform: lowercase; } @@ -2112,6 +2168,11 @@ box-shadow: var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow); } + .shadow-xl { + --tw-shadow: 0 20px 25px -5px var(--tw-shadow-color, #0000001a), 0 8px 10px -6px var(--tw-shadow-color, #0000001a); + box-shadow: var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow); + } + .shadow-xs { --tw-shadow: 0 1px 2px 0 var(--tw-shadow-color, #0000000d); box-shadow: var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow); @@ -2143,6 +2204,11 @@ outline-width: 1px; } + .blur-\[1px\] { + --tw-blur: blur(1px); + filter: var(--tw-blur, ) var(--tw-brightness, ) var(--tw-contrast, ) var(--tw-grayscale, ) var(--tw-hue-rotate, ) var(--tw-invert, ) var(--tw-saturate, ) var(--tw-sepia, ) var(--tw-drop-shadow, ); + } + .filter { filter: var(--tw-blur, ) var(--tw-brightness, ) var(--tw-contrast, ) var(--tw-grayscale, ) var(--tw-hue-rotate, ) var(--tw-invert, ) var(--tw-saturate, ) var(--tw-sepia, ) var(--tw-drop-shadow, ); } @@ -2198,6 +2264,11 @@ transition-duration: .2s; } + .duration-300 { + --tw-duration: .3s; + transition-duration: .3s; + } + .duration-1000 { --tw-duration: 1s; transition-duration: 1s; @@ -2214,14 +2285,8 @@ } @media (hover: hover) { - .group-hover\:text-blue-500:is(:where(.group):hover *) { - color: var(--color-blue-500); - } - } - - @media (hover: hover) { - .group-hover\:text-blue-600:is(:where(.group):hover *) { - color: var(--color-blue-600); + .group-hover\:text-\[\#F95F62\]:is(:where(.group):hover *) { + color: #f95f62; } } @@ -2340,6 +2405,14 @@ border-right-width: 0; } + .focus-within\:relative:focus-within { + position: relative; + } + + .focus-within\:z-20:focus-within { + z-index: 20; + } + @media (hover: hover) { .hover\:scale-105:hover { --tw-scale-x: 105%; @@ -2349,12 +2422,42 @@ } } + @media (hover: hover) { + .hover\:border-gray-300:hover { + border-color: var(--color-gray-300); + } + } + @media (hover: hover) { .hover\:border-red-400:hover { border-color: var(--color-red-400); } } + @media (hover: hover) { + .hover\:bg-\[\#E54B4E\]:hover { + background-color: #e54b4e; + } + } + + @media (hover: hover) { + .hover\:bg-\[\#F95F62\]\/10:hover { + background-color: oklab(68.6249% .174448 .0719368 / .1); + } + } + + @media (hover: hover) { + .hover\:bg-\[\#F95F62\]\/20:hover { + background-color: oklab(68.6249% .174448 .0719368 / .2); + } + } + + @media (hover: hover) { + .hover\:bg-\[\#F95F62\]\/30:hover { + background-color: oklab(68.6249% .174448 .0719368 / .3); + } + } + @media (hover: hover) { .hover\:bg-accent:hover { background-color: var(--accent); @@ -2367,12 +2470,6 @@ } } - @media (hover: hover) { - .hover\:bg-blue-100:hover { - background-color: var(--color-blue-100); - } - } - @media (hover: hover) { .hover\:bg-blue-700:hover { background-color: var(--color-blue-700); @@ -2421,24 +2518,12 @@ } } - @media (hover: hover) { - .hover\:bg-gray-700:hover { - background-color: var(--color-gray-700); - } - } - @media (hover: hover) { .hover\:bg-gray-800:hover { background-color: var(--color-gray-800); } } - @media (hover: hover) { - .hover\:bg-gray-900:hover { - background-color: var(--color-gray-900); - } - } - @media (hover: hover) { .hover\:bg-green-100:hover { background-color: var(--color-green-100); @@ -2458,8 +2543,8 @@ } @media (hover: hover) { - .hover\:bg-pink-300:hover { - background-color: var(--color-pink-300); + .hover\:bg-primary:hover { + background-color: var(--primary); } } @@ -2523,6 +2608,12 @@ } } + @media (hover: hover) { + .hover\:text-\[\#E54B4E\]:hover { + color: #e54b4e; + } + } + @media (hover: hover) { .hover\:text-accent-foreground:hover { color: var(--accent-foreground); @@ -2560,8 +2651,8 @@ } @media (hover: hover) { - .hover\:text-green-700:hover { - color: var(--color-green-700); + .hover\:text-primary-foreground:hover { + color: var(--primary-foreground); } } @@ -2617,10 +2708,18 @@ background-color: var(--accent); } + .focus\:bg-primary:focus { + background-color: var(--primary); + } + .focus\:text-accent-foreground:focus { color: var(--accent-foreground); } + .focus\:text-primary-foreground:focus { + color: var(--primary-foreground); + } + .focus\:ring-0:focus { --tw-ring-shadow: var(--tw-ring-inset, ) 0 0 0 calc(0px + var(--tw-ring-offset-width)) var(--tw-ring-color, currentcolor); box-shadow: var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow); @@ -2739,6 +2838,30 @@ } } + .aria-selected\:bg-accent[aria-selected="true"] { + background-color: var(--accent); + } + + .aria-selected\:bg-primary[aria-selected="true"] { + background-color: var(--primary); + } + + .aria-selected\:text-accent-foreground[aria-selected="true"] { + color: var(--accent-foreground); + } + + .aria-selected\:text-muted-foreground[aria-selected="true"] { + color: var(--muted-foreground); + } + + .aria-selected\:text-primary-foreground[aria-selected="true"] { + color: var(--primary-foreground); + } + + .aria-selected\:opacity-100[aria-selected="true"] { + opacity: 1; + } + .data-\[active\=true\]\:z-10[data-active="true"] { z-index: 10; } @@ -2880,8 +3003,8 @@ border-color: var(--primary); } - .data-\[state\=checked\]\:bg-green-600[data-state="checked"] { - background-color: var(--color-green-600); + .data-\[state\=checked\]\:bg-\[\#F95F62\][data-state="checked"] { + background-color: #f95f62; } .data-\[state\=checked\]\:bg-primary[data-state="checked"] { @@ -3169,6 +3292,39 @@ border-width: 0; } + .\[\&\:has\(\>\.day-range-end\)\]\:rounded-r-md:has( > .day-range-end) { + border-top-right-radius: calc(var(--radius) - 2px); + border-bottom-right-radius: calc(var(--radius) - 2px); + } + + .\[\&\:has\(\>\.day-range-start\)\]\:rounded-l-md:has( > .day-range-start) { + border-top-left-radius: calc(var(--radius) - 2px); + border-bottom-left-radius: calc(var(--radius) - 2px); + } + + .\[\&\:has\(\[aria-selected\]\)\]\:rounded-md:has([aria-selected]) { + border-radius: calc(var(--radius) - 2px); + } + + .\[\&\:has\(\[aria-selected\]\)\]\:bg-accent:has([aria-selected]) { + background-color: var(--accent); + } + + .first\:\[\&\:has\(\[aria-selected\]\)\]\:rounded-l-md:first-child:has([aria-selected]) { + border-top-left-radius: calc(var(--radius) - 2px); + border-bottom-left-radius: calc(var(--radius) - 2px); + } + + .last\:\[\&\:has\(\[aria-selected\]\)\]\:rounded-r-md:last-child:has([aria-selected]) { + border-top-right-radius: calc(var(--radius) - 2px); + border-bottom-right-radius: calc(var(--radius) - 2px); + } + + .\[\&\:has\(\[aria-selected\]\.day-range-end\)\]\:rounded-r-md:has([aria-selected].day-range-end) { + border-top-right-radius: calc(var(--radius) - 2px); + border-bottom-right-radius: calc(var(--radius) - 2px); + } + .\[\&\:has\(\[role\=checkbox\]\)\]\:pr-0:has([role="checkbox"]) { padding-right: calc(var(--spacing) * 0); } @@ -3269,6 +3425,7 @@ } } + :root { --font-size: 16px; --background: #fff; diff --git a/src/main.tsx b/src/main.tsx index 23d3462..d96f8d8 100644 --- a/src/main.tsx +++ b/src/main.tsx @@ -1,6 +1,6 @@ import { createRoot } from "react-dom/client"; - import App from "./App"; + import App from "./App.tsx"; import "./index.css"; createRoot(document.getElementById("root")!).render(); diff --git a/src/styles/globals.css b/src/styles/globals.css index b835a3f..b09929b 100644 --- a/src/styles/globals.css +++ b/src/styles/globals.css @@ -1,3 +1,5 @@ +@import url('https://fonts.googleapis.com/css2?family=Poppins:wght@100;200;300;400;500;600;700;800;900&display=swap'); + @custom-variant dark (&:is(.dark *)); :root { @@ -126,6 +128,7 @@ body { @apply bg-background text-foreground; + font-family: 'Poppins', sans-serif; } } diff --git a/vite.config.ts b/vite.config.ts index bcafad4..44f7393 100644 --- a/vite.config.ts +++ b/vite.config.ts @@ -56,7 +56,7 @@ import * as path from 'path'; outDir: 'build', }, server: { - port: 4001, + port: 4007, open: true, }, }); \ No newline at end of file