Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion clients/web/src/components/rooms/OverviewCard.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ export function OverviewCard({
col.valueSecondary != null && "whitespace-nowrap",
)}
>
<span className="text-[32px] font-bold text-text-default">
<span className="text-2xl lg:text-[32px] font-bold text-text-default">
{col.value}
</span>
{col.valueSecondary != null && (
Expand Down
127 changes: 127 additions & 0 deletions clients/web/src/components/rooms/RoomRequestCard.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,127 @@
import { FlagIcon, MapPinIcon, Maximize2Icon, StoreIcon } from "lucide-react";
import type { LucideIcon } from "lucide-react";

import { Button } from "@/components/ui/Button";
import { cn } from "@/lib/utils";

type Priority = "high" | "medium" | "low";

type PriorityConfig = {
label: string;
Icon: LucideIcon;
containerClass: string;
contentClass: string;
};

const priorityConfig: Record<Exclude<Priority, "low">, PriorityConfig> = {
high: {
label: "High Priority",
Icon: FlagIcon,
containerClass: "bg-bg-high-priority",
contentClass: "text-high-priority",
},
medium: {
label: "Medium Priority",
Icon: FlagIcon,
containerClass: "bg-bg-orange",
contentClass: "text-text-orange",
},
};

export type RoomRequestCardData = {
title: string;
floor: number;
roomNumber: number;
department: string;
priority?: Priority;
assignedTo?: string | null;
};

export type RoomRequestCardProps = RoomRequestCardData & {
onAssignToSelf?: () => void;
onExpand?: () => void;
className?: string;
};

export function RoomRequestCard({
title,
floor,
roomNumber,
department,
priority,
assignedTo,
onAssignToSelf,
onExpand,
className = "",
}: RoomRequestCardProps) {
return (
<div
className={cn(
"flex flex-col gap-3 rounded border border-stroke-disabled bg-bg-primary px-3 py-4",
className,
)}
>
<div className="flex flex-col gap-2">
<div className="flex items-start justify-between gap-2">
<span className="text-base font-medium leading-snug tracking-tight text-text-default">
{title}
</span>
<button
type="button"
onClick={onExpand}
className="shrink-0 text-text-subtle hover:text-text-default"
aria-label="Expand request"
>
<Maximize2Icon className="size-[1.125rem]" strokeWidth={1.5} />
</button>
</div>

<div className="flex items-center gap-1">
<MapPinIcon
className="size-3 shrink-0 text-text-subtle"
strokeWidth={1.5}
/>
<span className="text-xs text-text-subtle">
Floor {floor}, Room {roomNumber}
</span>
</div>

<div className="flex flex-wrap items-center gap-3">
{priority &&
(priority == "medium" || priority == "high") &&
(() => {
const { label, Icon, containerClass, contentClass } =
priorityConfig[priority];
return (
<div
className={cn(
"inline-flex items-center gap-1 rounded px-2 py-1",
containerClass,
)}
>
<Icon
className={cn("size-4", contentClass)}
strokeWidth={2}
/>
<span className={cn("text-xs", contentClass)}>{label}</span>
</div>
);
})()}
<div className="inline-flex items-center gap-2 rounded border border-stroke-subtle bg-bg-primary px-2 py-1">
<StoreIcon
className="size-3 shrink-0 text-text-default"
strokeWidth={1.5}
/>
<span className="text-xs text-text-default">{department}</span>
</div>
</div>
</div>

{!assignedTo && (
<Button variant="primary" className="w-full" onClick={onAssignToSelf}>
Assign to Self
</Button>
)}
</div>
);
}
44 changes: 44 additions & 0 deletions clients/web/src/components/rooms/RoomRequestList.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
import type { RoomRequestCardData } from "@/components/rooms/RoomRequestCard";
import { cn } from "@/lib/utils";
import { RoomRequestCard } from "@/components/rooms/RoomRequestCard";

export type RoomRequestItem = RoomRequestCardData & { id: string };

type RoomRequestListProps = {
title: string;
requests: Array<RoomRequestItem>;
onAssignToSelf?: (id: string) => void;
onExpand?: (id: string) => void;
className?: string;
};

export function RoomRequestList({
title,
requests,
onAssignToSelf,
onExpand,
className = "",
}: RoomRequestListProps) {
return (
<section className={cn("flex w-full min-w-0 flex-col", className)}>
<h2 className="my-2 shrink-0 text-sm font-medium leading-tight text-neutral-400">
{title} ({requests.length})
</h2>

<div className="h-0.5 w-full shrink-0 bg-stroke-subtle" />

<div className="mt-3 flex flex-col gap-2">
{requests.map(({ id, ...request }) => (
<RoomRequestCard
key={id}
{...request}
onAssignToSelf={
onAssignToSelf ? () => onAssignToSelf(id) : undefined
}
onExpand={onExpand ? () => onExpand(id) : undefined}
/>
))}
</div>
</section>
);
}
31 changes: 29 additions & 2 deletions clients/web/src/components/rooms/RoomsOverview.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import type { RoomWithOptionalGuestBooking } from "@shared";
import { OverviewCard } from "@/components/rooms/OverviewCard";
import { RoomRequestList } from "@/components/rooms/RoomRequestList";

type RoomsOverviewProps = {
rooms: Array<RoomWithOptionalGuestBooking>;
Expand All @@ -23,7 +24,7 @@ export function RoomsOverview({ rooms }: RoomsOverviewProps) {
const vacantRooms = totalRooms - occupiedRooms;

return (
<aside className="w-1/4 shrink-0 min-h-0 overflow-y-auto px-6">
<aside className="w-full max-w-[24.875rem] shrink-0 min-h-0 overflow-y-auto px-6">
<div className="flex flex-col">
<OverviewCard
title="Tasks"
Expand All @@ -39,7 +40,11 @@ export function RoomsOverview({ rooms }: RoomsOverviewProps) {
value: cleaningOnlyRooms,
description: "Tasks",
},
{ field: "Pending", value: cleaningRooms, description: "Tasks" },
{
field: "Pending",
value: cleaningRooms,
description: "Tasks",
},
]}
/>

Expand All @@ -64,6 +69,28 @@ export function RoomsOverview({ rooms }: RoomsOverviewProps) {
},
]}
/>
<RoomRequestList
title="Unassigned Tasks"
requests={[
{
id: "1",
title: "Room 101",
floor: 1,
roomNumber: 101,
department: "Maintenance",
priority: "low",
},
{
id: "2",
title: "Room 102",
floor: 1,
roomNumber: 102,
department: "Maintenance",
priority: "medium",
assignedTo: "John Doe",
},
]}
/>
</div>
</aside>
);
Expand Down
23 changes: 0 additions & 23 deletions clients/web/src/components/rooms/TaskCard.tsx

This file was deleted.

2 changes: 2 additions & 0 deletions clients/web/src/styles.css
Original file line number Diff line number Diff line change
Expand Up @@ -50,9 +50,11 @@
--color-bg-container: #f8f8f8;
--color-bg-disabled: #bababa;
--color-bg-primary: #ffffff;
--color-bg-orange: #fff3ed;
--color-bg-secondary: #5d5d5d;
--color-bg-high-priority: #ffeded;
--color-text-default: #000;
--color-text-orange: #ff8c3f;
--color-text-subtle: #747474;
--color-text-secondary: #5d5d5d;
--color-bg-selected: #edf5f1;
Expand Down
Loading