From 72117cdd12967d3895df5fd0269f3b5fb374df9b Mon Sep 17 00:00:00 2001 From: Lok Yx Date: Tue, 2 Dec 2025 09:23:14 +0000 Subject: [PATCH 1/4] Add Room card component with user, admin, and mobile views. --- client/src/app/test/card/page.tsx | 39 ++++ client/src/components/ui/card.tsx | 108 +++++++++ client/src/components/ui/room-card.tsx | 304 +++++++++++++++++++++++++ client/src/types/card.ts | 79 +++++++ 4 files changed, 530 insertions(+) create mode 100644 client/src/app/test/card/page.tsx create mode 100644 client/src/components/ui/card.tsx create mode 100644 client/src/components/ui/room-card.tsx create mode 100644 client/src/types/card.ts diff --git a/client/src/app/test/card/page.tsx b/client/src/app/test/card/page.tsx new file mode 100644 index 0000000..febb2ce --- /dev/null +++ b/client/src/app/test/card/page.tsx @@ -0,0 +1,39 @@ +import { AdminCard, MobileCard, UserCard } from "@/components/ui/room-card"; +import { roomsMock } from "@/types/card"; + +export default function RoomsList() { + return ( +
+

User Meeting Rooms Display

+ +
+ {roomsMock.map((room) => ( + + ))} +
+ +
+ +

+ Admin Meeting Rooms Display +

+ +
+ {roomsMock.map((room) => ( + + ))} +
+
+ +

+ Meeting Rooms Display (Mobile) +

+ +
+ {roomsMock.map((room) => ( + + ))} +
+
+ ); +} diff --git a/client/src/components/ui/card.tsx b/client/src/components/ui/card.tsx new file mode 100644 index 0000000..26e15ca --- /dev/null +++ b/client/src/components/ui/card.tsx @@ -0,0 +1,108 @@ +import * as React from "react"; + +import { cn } from "@/lib/utils"; + +/** + * Card component from shadcn/ui. + * + * Provides a styled container with optional header, title, description, + * content, and footer sections. + * + * @see {@link https://ui.shadcn.com/docs/components/card} for more details. + * + * @example + * + * + * Dashboard + * Summary of recent activity + * + * + *

Your content goes here.

+ *
+ * + * + * + *
+ */ +const Card = React.forwardRef< + HTMLDivElement, + React.HTMLAttributes +>(({ className, ...props }, ref) => ( +
+)); +Card.displayName = "Card"; + +const CardHeader = React.forwardRef< + HTMLDivElement, + React.HTMLAttributes +>(({ className, ...props }, ref) => ( +
+)); +CardHeader.displayName = "CardHeader"; + +const CardTitle = React.forwardRef< + HTMLDivElement, + React.HTMLAttributes +>(({ className, ...props }, ref) => ( +
+)); +CardTitle.displayName = "CardTitle"; + +const CardDescription = React.forwardRef< + HTMLDivElement, + React.HTMLAttributes +>(({ className, ...props }, ref) => ( +
+)); +CardDescription.displayName = "CardDescription"; + +const CardContent = React.forwardRef< + HTMLDivElement, + React.HTMLAttributes +>(({ className, ...props }, ref) => ( +
+)); +CardContent.displayName = "CardContent"; + +const CardFooter = React.forwardRef< + HTMLDivElement, + React.HTMLAttributes +>(({ className, ...props }, ref) => ( +
+)); +CardFooter.displayName = "CardFooter"; + +export { + Card, + CardContent, + CardDescription, + CardFooter, + CardHeader, + CardTitle, +}; diff --git a/client/src/components/ui/room-card.tsx b/client/src/components/ui/room-card.tsx new file mode 100644 index 0000000..e54f671 --- /dev/null +++ b/client/src/components/ui/room-card.tsx @@ -0,0 +1,304 @@ +import Image from "next/image"; +import { FaMicrophone } from "react-icons/fa"; +import { GrStatusUnknown } from "react-icons/gr"; +import { IoMdVideocam } from "react-icons/io"; +import { LuHdmiPort } from "react-icons/lu"; +import { MdPhonelinkRing } from "react-icons/md"; +import { RiArtboardLine } from "react-icons/ri"; + +import { + Card, + CardContent, + CardFooter, + CardHeader, + CardTitle, +} from "@/components/ui/card"; +import { cn } from "@/lib/utils"; +import { Room } from "@/types/card"; + +import { Button } from "./button"; + +// Mapping amenity string -> React icon component +const amenityIcons: Record = { + Default: , + Audio: , + Video: , + HDMI: , + "White Board": , + "Sound System": , +}; + +/** + * Renders a list of amenities using icons or text. + * + * @param {Object} props + * @param {string[]} props.amenities List of amenities to display. + * @param {boolean} [props.hideIcon=false] If true, displays amenities as plain text. + * @param {string} [props.className] Optional class for styling. + * + * @example + * + * + */ +const Amenities = ({ + amenities, + hideIcon = false, + className, +}: { + amenities: string[]; + hideIcon?: boolean; + className?: string; +}) => { + if (hideIcon) { + return {amenities.join(", ")}; + } + + return ( +
+ {amenities.map((amenity) => ( +
+ {amenityIcons[amenity] || amenityIcons["Default"]} +
+ ))} +
+ ); +}; + +/** + * User view card for displaying a room with booking option. + * + * Shows image, title, location and a Book button. + * Intended for general users who want to view and book rooms. + * + * @param {Object} props + * @param {Room} props.room Room data object. + * + * @example + * const room = { + * title: "Meeting Room A", + * image: "/rooms/a.jpg", + * location: "Level 2 Block B", + * seats: 10, + * amenities: ["Audio", "HDMI"], + * bookings: 4, + * available: true + * }; + * + * + */ +function UserCard({ room }: { room: Room }) { + return ( + +
+ {room.title} +
+ + + {room.title} + + + + + {room.location} + + + + + + +
+ ); +} + +/** + * Admin management card for room details. + * + * Displays full room information including + * name, location, seats, amenities and bookings. + * Includes admin action buttons for editing and removal. + * + * Used in admin dashboards to manage rooms. + * + * @param {Object} props + * @param {Room} props.room Room data object. + * + * @example + * const room = { + * title: "Studio Room C", + * image: "/rooms/c.jpg", + * location: "Level 1 Block E", + * seats: 20, + * amenities: ["White Board", "Audio"], + * bookings: 10, + * removed: false + * }; + * + * + */ +function AdminCard({ room }: { room: Room; hideIcon?: boolean }) { + const roomDetailsGroups = [ + { label: "Room Name", value: room.title }, + { label: "Location", value: room.location }, + { label: "No of Seats", value: room.seats }, + { + label: "Amenities", + value: , + }, + { label: "Bookings", value: room.bookings }, + ]; + + return ( +
+
+
+ {room.title} +
+
+ +
+ {roomDetailsGroups.map((item) => ( +
+ {item.label} + {item.value} +
+ ))} +
+ +
+ + + +
+
+ ); +} + +/** + * Mobile friendly version of the room card. + * + * Designed for small screens with grouped details. + * Displays status, amenities and a booking button. + * + * @param {Object} props + * @param {Room} props.room Room data object. + * + * @example + * const room = { + * title: "Training Room D", + * image: "/rooms/d.jpg", + * location: "Level 4 Block A", + * seats: 30, + * amenities: ["Sound System", "HDMI"], + * bookings: 2, + * available: false + * }; + * + * + */ +function MobileCard({ room }: { room: Room; hideIcon?: boolean }) { + const roomDetailsGroups = [ + [ + { label: "Title", value: room.title }, + { label: "Seating Capacity:", value: room.seats }, + ], + [ + { label: "Location:", value: room.location }, + { label: "Available", value: room.available }, + ], + [ + { + label: "Facilities:", + value: , + }, + ], + ]; + + return ( +
+
+
+ {room.title} +
+
+ +
+ {roomDetailsGroups.map((group, i) => ( +
+ {group.map((item) => ( +
+ {item.label === "Title" ? ( + {item.value} + ) : item.label === "Available" ? ( + + {item.value ? "Available" : "Not Available"} + + ) : ( + <> + {item.label} + {item.value} + + )} +
+ ))} +
+ ))} +
+ +
+ +
+
+ ); +} + +export { AdminCard, MobileCard, UserCard }; diff --git a/client/src/types/card.ts b/client/src/types/card.ts new file mode 100644 index 0000000..cce1024 --- /dev/null +++ b/client/src/types/card.ts @@ -0,0 +1,79 @@ +export type Room = { + id: number; + title: string; + image: string; + location: string; + available: boolean; + seats: number; + amenities: string[]; + bookings: number; + removed?: boolean; +}; + +const defaultImage = + "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVR42mP8z/C/HwAFgwJ/lYpukQAAAABJRU5ErkJggg=="; + +export const roomsMock: Room[] = [ + { + id: 1, + title: "BHAGIRATHI", + image: defaultImage, + seats: 4, + location: "Pune Hinjewadi", + available: true, + amenities: ["Audio", "Video", "HDMI", "White Board", "Sound System"], + bookings: 10, + removed: true, + }, + { + id: 2, + title: "GHATAPRABHA", + image: defaultImage, + seats: 8, + location: "St Catherine's college, 2 Park Road", + available: false, + amenities: ["Audio", "Video", "HDMI", "White Board", "Sound System"], + bookings: 5, + }, + { + id: 3, + title: "BHIMA", + image: defaultImage, + seats: 8, + location: "UNIT-1B PNQ- HJ", + available: true, + amenities: ["Audio", "Video", "HDMI", "White Board", "Sound System"], + bookings: 3, + }, + { + id: 4, + title: "TUNGBHADRA", + image: defaultImage, + seats: 4, + location: "St Catherine's college, 2 Park Road", + available: true, + amenities: ["Audio", "Video", "HDMI", "White Board", "Sound System"], + bookings: 8, + removed: true, + }, + { + id: 5, + title: "BRAMHAPUTRA", + image: defaultImage, + seats: 4, + location: "UNIT-1B PNQ- HJ", + available: false, + amenities: ["Audio", "Video", "HDMI", "White Board", "Sound System"], + bookings: 7, + }, + { + id: 6, + title: "SINDU", + image: defaultImage, + seats: 4, + location: "Pune Hinjewadi", + available: true, + amenities: ["Audio", "Video", "HDMI", "White Board", "Sound System"], + bookings: 5, + }, +]; From e2f627162a436d4fe954760cada25890bde38f77 Mon Sep 17 00:00:00 2001 From: Lok Yx Date: Wed, 3 Dec 2025 18:02:13 +0000 Subject: [PATCH 2/4] Refactor color properties in AlertDialog and RoomCard components for consistency --- client/src/components/ui/alert.tsx | 8 ++++---- client/src/components/ui/room-card.tsx | 23 +++++++++++------------ 2 files changed, 15 insertions(+), 16 deletions(-) diff --git a/client/src/components/ui/alert.tsx b/client/src/components/ui/alert.tsx index 68ea6e1..3d8c014 100644 --- a/client/src/components/ui/alert.tsx +++ b/client/src/components/ui/alert.tsx @@ -26,7 +26,7 @@ import { Button } from "./button"; * * @param title Optional title displayed at the top of the dialog * @param successText Text displayed when the operation is complete - * @param color Optional color for the success icon and button (default: `#006DD5`) + * @param color Optional color for the success icon and button (default: `var(--bloom-blue)`) * @param showIcon Whether to show the icon above the content (default: `true`) * @param children React node used as the DialogTrigger * @@ -34,7 +34,7 @@ import { Button } from "./button"; * * * @@ -43,7 +43,7 @@ function AlertDialog({ title, successText, children, - color = "#006DD5", + color = "var(--bloom-blue)", showIcon = true, }: { title?: string; @@ -81,7 +81,7 @@ function AlertDialog({
@@ -107,7 +107,7 @@ function UserCard({ room }: { room: Room }) { - + {room.location} @@ -174,24 +174,23 @@ function AdminCard({ room }: { room: Room; hideIcon?: boolean }) {
{roomDetailsGroups.map((item) => (
- {item.label} + {item.label} {item.value}
))}
- -
@@ -290,8 +289,8 @@ function MobileCard({ room }: { room: Room; hideIcon?: boolean }) { className={cn( "h-[30px] w-[79px] text-[10px] font-bold", room.available - ? "bg-[#2332FF] text-white hover:bg-[#437DD6]" - : "cursor-not-allowed border-[#437DD6] text-[#437DD6] hover:bg-white", + ? "bg-bloom-orbit text-white hover:bg-bloom-orbit-light" + : "cursor-not-allowed border-bloom-orbit text-bloom-orbit hover:bg-white", )} > {room.available ? "Book" : "Booked"} From 9c70db6831251ba77a78d21b3b3ca0686dc95bcc Mon Sep 17 00:00:00 2001 From: Lok Yx Date: Mon, 8 Dec 2025 06:44:03 +0000 Subject: [PATCH 3/4] Improve RoomCard components and update layout for responsiveness --- client/src/app/layout.tsx | 9 +- client/src/app/test/card/page.tsx | 34 ++- client/src/components/ui/room-card.tsx | 404 +++++++++++++++---------- client/src/hooks/use-is-mobile.ts | 24 ++ client/src/types/card.ts | 7 + 5 files changed, 310 insertions(+), 168 deletions(-) create mode 100644 client/src/hooks/use-is-mobile.ts diff --git a/client/src/app/layout.tsx b/client/src/app/layout.tsx index 9409b13..0b5b472 100644 --- a/client/src/app/layout.tsx +++ b/client/src/app/layout.tsx @@ -13,7 +13,14 @@ const montserrat = Montserrat({ export default function RootLayout({ children }: { children: ReactNode }) { return ( - + {children} diff --git a/client/src/app/test/card/page.tsx b/client/src/app/test/card/page.tsx index febb2ce..d8cf3c5 100644 --- a/client/src/app/test/card/page.tsx +++ b/client/src/app/test/card/page.tsx @@ -1,14 +1,24 @@ -import { AdminCard, MobileCard, UserCard } from "@/components/ui/room-card"; +"use client"; + +import { + AdminRoomCard, + BookingRoomCard, + RoomCard, +} from "@/components/ui/room-card"; import { roomsMock } from "@/types/card"; export default function RoomsList() { return (
-

User Meeting Rooms Display

+

Booking Rooms Display

-
+
{roomsMock.map((room) => ( - + alert("Book")} + /> ))}
@@ -18,20 +28,24 @@ export default function RoomsList() { Admin Meeting Rooms Display -
+
{roomsMock.map((room) => ( - + alert("View")} + onEdit={() => alert("Edit")} + onRemove={() => alert("Remove")} + /> ))}
-

- Meeting Rooms Display (Mobile) -

+

General Rooms Display

{roomsMock.map((room) => ( - + ))}
diff --git a/client/src/components/ui/room-card.tsx b/client/src/components/ui/room-card.tsx index 1b07b38..d8a6045 100644 --- a/client/src/components/ui/room-card.tsx +++ b/client/src/components/ui/room-card.tsx @@ -1,3 +1,5 @@ +"use client"; + import Image from "next/image"; import { FaMicrophone } from "react-icons/fa"; import { GrStatusUnknown } from "react-icons/gr"; @@ -6,13 +8,8 @@ import { LuHdmiPort } from "react-icons/lu"; import { MdPhonelinkRing } from "react-icons/md"; import { RiArtboardLine } from "react-icons/ri"; -import { - Card, - CardContent, - CardFooter, - CardHeader, - CardTitle, -} from "@/components/ui/card"; +import { Card } from "@/components/ui/card"; +import { useIsMobile } from "@/hooks/use-is-mobile"; import { cn } from "@/lib/utils"; import { Room } from "@/types/card"; @@ -29,12 +26,12 @@ const amenityIcons: Record = { }; /** - * Renders a list of amenities using icons or text. + * Renders a list of room amenities using icons or plain text. * * @param {Object} props * @param {string[]} props.amenities List of amenities to display. * @param {boolean} [props.hideIcon=false] If true, displays amenities as plain text. - * @param {string} [props.className] Optional class for styling. + * @param {string} [props.className] Optional extra class names for styling. * * @example * @@ -69,10 +66,10 @@ const Amenities = ({ }; /** - * User view card for displaying a room with booking option. + * Displays a room with details in a label-value grid format. * - * Shows image, title, location and a Book button. - * Intended for general users who want to view and book rooms. + * Shows image, room name, location, seats, amenities and availability. + * Intended for general / admin use as an info card. * * @param {Object} props * @param {Room} props.room Room data object. @@ -84,83 +81,114 @@ const Amenities = ({ * location: "Level 2 Block B", * seats: 10, * amenities: ["Audio", "HDMI"], - * bookings: 4, - * available: true + * available: true, * }; * - * + * */ -function UserCard({ room }: { room: Room }) { +function RoomCard({ room }: { room: Room; hideIcon?: boolean }) { + const roomDetailsGroups = [ + { label: "Room Name", value: room.title }, + { label: "Location", value: room.location }, + { label: "No of Seats", value: room.seats }, + { + label: "Amenities", + value: , + }, + { label: "Availability", value: room.availablility }, + ]; + return ( - -
- {room.title} +
+
+
+ {room.title} +
- - {room.title} - - - - - {room.location} - - - - - - - + {/* Info grid ensures perfect alignment */} +
+ {roomDetailsGroups.map((item) => ( +
+ + {item.label} + + {item.value} +
+ ))} +
+
); } +type BookingRoomProps = { + room: Room; + hideIcon?: boolean; + onBook?: () => void; +}; + /** - * Admin management card for room details. - * - * Displays full room information including - * name, location, seats, amenities and bookings. - * Includes admin action buttons for editing and removal. + * User-facing booking card for displaying a room. * - * Used in admin dashboards to manage rooms. + * Responsive: shows compact card on mobile, detailed card on desktop. + * Includes image, title, location, facilities, availability, and a Book button. * * @param {Object} props * @param {Room} props.room Room data object. + * @param {boolean} [props.hideIcon=false] Hide icons for amenities if true. + * @param {() => void} [props.onBook] Callback when the Book button is clicked. * * @example * const room = { - * title: "Studio Room C", - * image: "/rooms/c.jpg", - * location: "Level 1 Block E", - * seats: 20, - * amenities: ["White Board", "Audio"], - * bookings: 10, - * removed: false + * title: "Training Room B", + * image: "/rooms/b.jpg", + * location: "Level 3 Block D", + * seats: 12, + * amenities: ["Audio", "HDMI", "White Board"], + * available: true, * }; * - * + * console.log("Booked!")} /> */ -function AdminCard({ room }: { room: Room; hideIcon?: boolean }) { - const roomDetailsGroups = [ - { label: "Room Name", value: room.title }, - { label: "Location", value: room.location }, - { label: "No of Seats", value: room.seats }, - { - label: "Amenities", - value: , - }, - { label: "Bookings", value: room.bookings }, - ]; +export function BookingRoomCard({ + room, + hideIcon = false, + onBook, +}: BookingRoomProps) { + const isMobile = useIsMobile(); - return ( -
-
+ if (!isMobile) { + // General / desktop version + const roomDetailsGroups = [ + [ + { label: "Title", value: room.title }, + { label: "Seating Capacity", value: room.seats }, + ], + [ + { label: "Location", value: room.location }, + { label: "Available", value: room.available }, + ], + [ + { + label: "Facilities", + value: ( + + ), + }, + ], + ]; + + return ( +
+ +
+ {roomDetailsGroups.map((group, i) => ( +
+ {group.map((item) => ( +
+ {item.label === "Title" ? ( + {item.value} + ) : item.label === "Available" ? ( + + {item.value ? "Available" : "Not Available"} + + ) : ( + <> + {item.label} + {item.value} + + )} +
+ ))} +
+ ))} +
+ +
+ +
+ ); + } -
- {roomDetailsGroups.map((item) => ( -
- {item.label} - {item.value} -
- ))} + // Tight version + return ( + +
+ {room.title}
-
- - +
+ {room.title} + + {room.location} + +
+ +
-
+
); } +type AdminRoomCardProps = { + room: Room; + hideIcon?: boolean; + onView?: () => void; + onEdit?: () => void; + onRemove?: () => void; +}; + /** - * Mobile friendly version of the room card. + * Admin card for managing room details. * - * Designed for small screens with grouped details. - * Displays status, amenities and a booking button. + * Displays full room info: name, location, seats, amenities, and bookings. + * Includes admin action buttons: View Bookings, Edit, Remove. + * Supports disabling the Remove button if room is already removed. * * @param {Object} props * @param {Room} props.room Room data object. + * @param {boolean} [props.hideIcon=false] Hide amenity icons if true. + * @param {() => void} [props.onView] Callback for View Bookings button. + * @param {() => void} [props.onEdit] Callback for Edit button. + * @param {() => void} [props.onRemove] Callback for Remove button. * * @example * const room = { - * title: "Training Room D", - * image: "/rooms/d.jpg", - * location: "Level 4 Block A", - * seats: 30, - * amenities: ["Sound System", "HDMI"], - * bookings: 2, - * available: false + * title: "Studio Room C", + * image: "/rooms/c.jpg", + * location: "Level 1 Block E", + * seats: 20, + * amenities: ["White Board", "Audio"], + * bookings: 10, + * removed: false, * }; * - * + * console.log("View")} + * onEdit={() => console.log("Edit")} + * onRemove={() => console.log("Remove")} + * /> */ -function MobileCard({ room }: { room: Room; hideIcon?: boolean }) { - const roomDetailsGroups = [ - [ - { label: "Title", value: room.title }, - { label: "Seating Capacity:", value: room.seats }, - ], - [ - { label: "Location:", value: room.location }, - { label: "Available", value: room.available }, - ], - [ - { - label: "Facilities:", - value: , - }, - ], +function AdminRoomCard({ + room, + hideIcon, + onView, + onEdit, + onRemove, +}: AdminRoomCardProps) { + const roomDetails = [ + { label: "Room Name", value: room.title }, + { label: "Location", value: room.location }, + { label: "No of Seats", value: room.seats }, + { + label: "Amenities", + value: , + }, + { label: "Bookings", value: room.bookings }, ]; return ( -
-
-
- {room.title} -
+
+ {/* Room Image */} +
+ {room.title}
-
- {roomDetailsGroups.map((group, i) => ( + {/* Room Details */} +
+ {roomDetails.map((item) => (
- {group.map((item) => ( -
- {item.label === "Title" ? ( - {item.value} - ) : item.label === "Available" ? ( - - {item.value ? "Available" : "Not Available"} - - ) : ( - <> - {item.label} - {item.value} - - )} -
- ))} + {item.label} + {item.value}
))}
-
+ {/* Action Buttons */} +
+ +
); } -export { AdminCard, MobileCard, UserCard }; +export { AdminRoomCard, RoomCard }; diff --git a/client/src/hooks/use-is-mobile.ts b/client/src/hooks/use-is-mobile.ts new file mode 100644 index 0000000..d144590 --- /dev/null +++ b/client/src/hooks/use-is-mobile.ts @@ -0,0 +1,24 @@ +import { useEffect, useState } from "react"; + +export function useIsMobile(MOBILE_BREAKPOINT = 768) { + const [isMobile, setIsMobile] = useState(false); + + useEffect(() => { + const mql = window.matchMedia(`(max-width: ${MOBILE_BREAKPOINT - 1}px)`); + + const onChange = () => { + setIsMobile(mql.matches); + }; + + mql.addEventListener("change", onChange); + + // set initial value + setIsMobile(mql.matches); + + return () => { + mql.removeEventListener("change", onChange); + }; + }, [MOBILE_BREAKPOINT]); + + return isMobile; +} diff --git a/client/src/types/card.ts b/client/src/types/card.ts index cce1024..3150232 100644 --- a/client/src/types/card.ts +++ b/client/src/types/card.ts @@ -4,6 +4,7 @@ export type Room = { image: string; location: string; available: boolean; + availablility: string; seats: number; amenities: string[]; bookings: number; @@ -21,6 +22,7 @@ export const roomsMock: Room[] = [ seats: 4, location: "Pune Hinjewadi", available: true, + availablility: "8:00am - 5:00pm, Mon - Fri", amenities: ["Audio", "Video", "HDMI", "White Board", "Sound System"], bookings: 10, removed: true, @@ -32,6 +34,7 @@ export const roomsMock: Room[] = [ seats: 8, location: "St Catherine's college, 2 Park Road", available: false, + availablility: "8:00am - 7:00pm, Mon - Fri", amenities: ["Audio", "Video", "HDMI", "White Board", "Sound System"], bookings: 5, }, @@ -42,6 +45,7 @@ export const roomsMock: Room[] = [ seats: 8, location: "UNIT-1B PNQ- HJ", available: true, + availablility: "9:00am - 5:00pm, Mon - Fri", amenities: ["Audio", "Video", "HDMI", "White Board", "Sound System"], bookings: 3, }, @@ -52,6 +56,7 @@ export const roomsMock: Room[] = [ seats: 4, location: "St Catherine's college, 2 Park Road", available: true, + availablility: "12;00pm - 7:00pm, Wed - Fri", amenities: ["Audio", "Video", "HDMI", "White Board", "Sound System"], bookings: 8, removed: true, @@ -63,6 +68,7 @@ export const roomsMock: Room[] = [ seats: 4, location: "UNIT-1B PNQ- HJ", available: false, + availablility: "10:00am - 4:00pm, Mon - Tues", amenities: ["Audio", "Video", "HDMI", "White Board", "Sound System"], bookings: 7, }, @@ -73,6 +79,7 @@ export const roomsMock: Room[] = [ seats: 4, location: "Pune Hinjewadi", available: true, + availablility: "9:00am - 3:00pm, Mon - Thurs", amenities: ["Audio", "Video", "HDMI", "White Board", "Sound System"], bookings: 5, }, From cdc9a01047f9596c95dd1d38950409b2aed6dff0 Mon Sep 17 00:00:00 2001 From: Lok Yx Date: Sat, 13 Dec 2025 08:00:26 +0000 Subject: [PATCH 4/4] Refactor components and remove mobile version --- client/src/app/test/card/page.tsx | 2 +- client/src/components/ui/room-card.tsx | 96 +------------------------- client/src/hooks/use-is-mobile.ts | 24 ------- 3 files changed, 3 insertions(+), 119 deletions(-) delete mode 100644 client/src/hooks/use-is-mobile.ts diff --git a/client/src/app/test/card/page.tsx b/client/src/app/test/card/page.tsx index d8cf3c5..f74fd58 100644 --- a/client/src/app/test/card/page.tsx +++ b/client/src/app/test/card/page.tsx @@ -12,7 +12,7 @@ export default function RoomsList() {

Booking Rooms Display

-
+
{roomsMock.map((room) => ( console.log("Booked!")} /> */ -export function BookingRoomCard({ - room, - hideIcon = false, - onBook, -}: BookingRoomProps) { - const isMobile = useIsMobile(); - - if (!isMobile) { - // General / desktop version - const roomDetailsGroups = [ - [ - { label: "Title", value: room.title }, - { label: "Seating Capacity", value: room.seats }, - ], - [ - { label: "Location", value: room.location }, - { label: "Available", value: room.available }, - ], - [ - { - label: "Facilities", - value: ( - - ), - }, - ], - ]; - - return ( -
-
- {room.title} -
- -
- {roomDetailsGroups.map((group, i) => ( -
- {group.map((item) => ( -
- {item.label === "Title" ? ( - {item.value} - ) : item.label === "Available" ? ( - - {item.value ? "Available" : "Not Available"} - - ) : ( - <> - {item.label} - {item.value} - - )} -
- ))} -
- ))} -
- -
- -
-
- ); - } - - // Tight version +export function BookingRoomCard({ room, onBook }: BookingRoomProps) { + // Default: User card view return (
diff --git a/client/src/hooks/use-is-mobile.ts b/client/src/hooks/use-is-mobile.ts deleted file mode 100644 index d144590..0000000 --- a/client/src/hooks/use-is-mobile.ts +++ /dev/null @@ -1,24 +0,0 @@ -import { useEffect, useState } from "react"; - -export function useIsMobile(MOBILE_BREAKPOINT = 768) { - const [isMobile, setIsMobile] = useState(false); - - useEffect(() => { - const mql = window.matchMedia(`(max-width: ${MOBILE_BREAKPOINT - 1}px)`); - - const onChange = () => { - setIsMobile(mql.matches); - }; - - mql.addEventListener("change", onChange); - - // set initial value - setIsMobile(mql.matches); - - return () => { - mql.removeEventListener("change", onChange); - }; - }, [MOBILE_BREAKPOINT]); - - return isMobile; -}