diff --git a/backend/docs/swagger.yaml b/backend/docs/swagger.yaml
index 0b773456..8db8bc6a 100644
--- a/backend/docs/swagger.yaml
+++ b/backend/docs/swagger.yaml
@@ -66,6 +66,7 @@ definitions:
type: integer
type: array
limit:
+ minimum: 0
type: integer
type: object
GenerateRequestInput:
diff --git a/clients/web/src/components/rooms/FilterTag.tsx b/clients/web/src/components/rooms/FilterTag.tsx
new file mode 100644
index 00000000..12e58291
--- /dev/null
+++ b/clients/web/src/components/rooms/FilterTag.tsx
@@ -0,0 +1,28 @@
+import { X } from "lucide-react";
+import { cn } from "@/lib/utils";
+
+type FilterTagProps = {
+ label: string;
+ onRemove: () => void;
+ className?: string;
+};
+
+export function FilterTag({ label, onRemove, className }: FilterTagProps) {
+ return (
+
+ {label}
+
+
+ );
+}
diff --git a/clients/web/src/components/rooms/OrderByDropdown.tsx b/clients/web/src/components/rooms/OrderByDropdown.tsx
new file mode 100644
index 00000000..ba5ef2ce
--- /dev/null
+++ b/clients/web/src/components/rooms/OrderByDropdown.tsx
@@ -0,0 +1,60 @@
+import { ChevronDown } from "lucide-react";
+import { useState } from "react";
+import { cn } from "@/lib/utils";
+
+type OrderByDropdownProps = {
+ ascending: boolean;
+ setAscending: (ascending: boolean) => void;
+};
+
+export function OrderByDropdown({
+ ascending,
+ setAscending,
+}: OrderByDropdownProps) {
+ const [open, setOpen] = useState(false);
+ const label = ascending ? "Ascending" : "Descending";
+
+ return (
+ {
+ if (!e.currentTarget.contains(e.relatedTarget)) setOpen(false);
+ }}
+ >
+
+
+ {open && (
+
+
+
+ )}
+
+ );
+}
diff --git a/clients/web/src/components/rooms/RoomsList.tsx b/clients/web/src/components/rooms/RoomsList.tsx
index 58777a41..cc3e335a 100644
--- a/clients/web/src/components/rooms/RoomsList.tsx
+++ b/clients/web/src/components/rooms/RoomsList.tsx
@@ -1,22 +1,41 @@
+import { useMemo } from "react";
import type { RoomWithOptionalGuestBooking } from "@shared";
import { RoomCard } from "@/components/rooms/RoomCard";
type RoomsListProps = {
rooms: Array;
onRoomSelect: (room: RoomWithOptionalGuestBooking) => void;
+ ascending: boolean;
selectedRoomNumber?: number | null;
};
+function sortRoomsByRoomNumber(
+ rooms: Array,
+ ascending: boolean,
+): Array {
+ return [...rooms].sort((a, b) => {
+ const an = a.room_number ?? 0;
+ const bn = b.room_number ?? 0;
+ return ascending ? an - bn : bn - an;
+ });
+}
+
export function RoomsList({
rooms,
onRoomSelect,
+ ascending,
selectedRoomNumber = null,
}: RoomsListProps) {
+ const sortedRooms = useMemo(
+ () => sortRoomsByRoomNumber(rooms, ascending),
+ [rooms, ascending],
+ );
+
return (