Skip to content

Commit e33dc3e

Browse files
authored
Feature/UI fixes after test (#32)
* rewamped the searchbar * primarybutton to open search on mobile * adds about page and other design improvements
1 parent bf53f73 commit e33dc3e

18 files changed

Lines changed: 1276 additions & 642 deletions

File tree

src/components/forms/VenueForm.tsx

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -579,9 +579,7 @@ export function VenueForm({
579579
</CardContent>
580580
</Card>
581581
<Card className="hidden md:block sticky top-6">
582-
<CardHeader>
583-
<CardTitle>Ready to create your venue?</CardTitle>
584-
</CardHeader>
582+
<CardHeader />
585583
<CardContent className="space-y-2">
586584
{secondaryAction}
587585
<Button

src/components/layout/Header.tsx

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,11 @@ export function Header() {
7070
<NavLink to={routes.venues}>Venues</NavLink>
7171
</NavigationMenuLink>
7272
</NavigationMenuItem>
73+
<NavigationMenuItem>
74+
<NavigationMenuLink asChild>
75+
<NavLink to={routes.about}>About</NavLink>
76+
</NavigationMenuLink>
77+
</NavigationMenuItem>
7378
</NavigationMenuList>
7479
</NavigationMenu>
7580
</nav>
@@ -110,6 +115,11 @@ export function Header() {
110115
Venues
111116
</NavLink>
112117
</SheetClose>
118+
<SheetClose asChild>
119+
<NavLink to={routes.about} className={navLinkClass}>
120+
About
121+
</NavLink>
122+
</SheetClose>
113123
</nav>
114124
</SheetContent>
115125
</Sheet>

src/components/layout/PageBreadcrumbs.tsx

Lines changed: 31 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -29,38 +29,39 @@ type Props = {
2929
*/
3030
export function PageBreadcrumbs({ items, className }: Props) {
3131
if (!items.length) return null;
32-
3332
return (
34-
<Breadcrumb className={cn("hidden sm:block", className)}>
35-
<BreadcrumbList>
36-
{items.map((item, idx) => {
37-
const isLast = idx === items.length - 1;
38-
const itemKey = item.key ?? item.to ?? item.label;
39-
return (
40-
<Fragment key={itemKey}>
41-
<BreadcrumbItem>
42-
{item.to && !isLast ? (
43-
<BreadcrumbLink asChild>
44-
<Link
45-
to={item.to}
46-
className="inline-flex items-center gap-1 text-sm"
47-
>
33+
<div className={cn("space-y-1", className)}>
34+
<Breadcrumb className="text-sm text-muted-foreground overflow-x-auto whitespace-nowrap">
35+
<BreadcrumbList>
36+
{items.map((item, idx) => {
37+
const isLast = idx === items.length - 1;
38+
const itemKey = item.key ?? item.to ?? item.label;
39+
return (
40+
<Fragment key={itemKey}>
41+
<BreadcrumbItem>
42+
{item.to && !isLast ? (
43+
<BreadcrumbLink asChild>
44+
<Link
45+
to={item.to}
46+
className="inline-flex items-center gap-1"
47+
>
48+
{item.icon}
49+
<span>{item.label}</span>
50+
</Link>
51+
</BreadcrumbLink>
52+
) : (
53+
<BreadcrumbPage className="inline-flex items-center gap-1 font-medium text-foreground">
4854
{item.icon}
4955
<span>{item.label}</span>
50-
</Link>
51-
</BreadcrumbLink>
52-
) : (
53-
<BreadcrumbPage className="inline-flex items-center gap-1 text-sm">
54-
{item.icon}
55-
<span>{item.label}</span>
56-
</BreadcrumbPage>
57-
)}
58-
</BreadcrumbItem>
59-
{!isLast && <BreadcrumbSeparator />}
60-
</Fragment>
61-
);
62-
})}
63-
</BreadcrumbList>
64-
</Breadcrumb>
56+
</BreadcrumbPage>
57+
)}
58+
</BreadcrumbItem>
59+
{!isLast && <BreadcrumbSeparator />}
60+
</Fragment>
61+
);
62+
})}
63+
</BreadcrumbList>
64+
</Breadcrumb>
65+
</div>
6566
);
6667
}

src/features/auth/ProfileMenu.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ export function ProfileMenu() {
3737
<div className="flex my-2">
3838
<p>{profile?.name}</p>
3939
{profile?.venueManager && (
40-
<span className="ml-2 rounded-full bg-indigo-100 px-2 py-0.5 text-xs font-medium">
40+
<span className="ml-2 rounded-full bg-teal-100 text-teal-950 px-2 py-0.5 text-xs font-medium">
4141
Venue Manager
4242
</span>
4343
)}

src/features/bookings/BookingWidget.tsx

Lines changed: 75 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,14 @@ import { useCreateBooking } from "@/features/venues/hooks";
1515
import { useLocation, useNavigate } from "react-router-dom";
1616
import { routes } from "@/router/routes";
1717
import { Spinner } from "@/components/ui/spinner";
18+
import {
19+
Dialog,
20+
DialogContent,
21+
DialogDescription,
22+
DialogFooter,
23+
DialogHeader,
24+
DialogTitle,
25+
} from "@/components/ui/dialog";
1826

1927
type Props = {
2028
venueId: string;
@@ -31,6 +39,7 @@ export function BookingWidget({
3139
}: Props) {
3240
const [range, setRange] = useState<DateRange | undefined>();
3341
const [guests, setGuests] = useState(1);
42+
const [confirmOpen, setConfirmOpen] = useState(false);
3443
const { token } = useAuth();
3544
const navigate = useNavigate();
3645
const location = useLocation();
@@ -44,7 +53,7 @@ export function BookingWidget({
4453

4554
const { mutateAsync, isPending } = useCreateBooking(venueId);
4655

47-
async function submit() {
56+
function handlePrimaryAction() {
4857
if (!token) {
4958
navigate(routes.auth.login, { state: { from: location } });
5059
return;
@@ -57,15 +66,21 @@ export function BookingWidget({
5766
toast.error(`Guests must be between 1 and ${maxGuests}.`);
5867
return;
5968
}
69+
setConfirmOpen(true);
70+
}
71+
72+
async function confirmBooking() {
73+
if (!range?.from || !range?.to) return;
6074
try {
6175
await mutateAsync({
6276
dateFrom: toISODate(range.from),
63-
dateTo: toISODate(range.to), // checkout day
77+
dateTo: toISODate(range.to),
6478
guests,
6579
});
6680
toast.success("Booking confirmed!");
6781
setRange(undefined);
6882
setGuests(1);
83+
setConfirmOpen(false);
6984
} catch (e: unknown) {
7085
toast.error(e instanceof Error ? e.message : "Booking failed");
7186
}
@@ -155,13 +170,70 @@ export function BookingWidget({
155170

156171
<Button
157172
className="w-full"
158-
onClick={submit}
173+
onClick={handlePrimaryAction}
159174
disabled={isPending || (!!token && (!range?.from || !range?.to))}
160175
aria-busy={isPending}
161176
>
162177
{token && isPending && <Spinner className="mr-2" aria-hidden="true" />}
163178
{token ? (isPending ? "Booking…" : "Book now") : "Sign in to book"}
164179
</Button>
180+
181+
<Dialog
182+
open={confirmOpen}
183+
onOpenChange={(open) => {
184+
if (!isPending) setConfirmOpen(open);
185+
}}
186+
>
187+
<DialogContent>
188+
<DialogHeader>
189+
<DialogTitle>Confirm booking</DialogTitle>
190+
<DialogDescription>
191+
Review your stay details before confirming.
192+
</DialogDescription>
193+
</DialogHeader>
194+
<div className="space-y-2 text-sm">
195+
<div className="flex justify-between">
196+
<span>Dates</span>
197+
<span className="font-medium">
198+
{range?.from && range?.to
199+
? formatDateRange(range.from, range.to)
200+
: "Select dates"}
201+
</span>
202+
</div>
203+
<div className="flex justify-between">
204+
<span>Guests</span>
205+
<span className="font-medium">{guests}</span>
206+
</div>
207+
<div className="flex justify-between">
208+
<span>
209+
{nights} {nights === 1 ? "night" : "nights"}
210+
</span>
211+
<span className="font-semibold">
212+
{formatMoney(total, { currency: "USD" })}
213+
</span>
214+
</div>
215+
</div>
216+
<DialogFooter className="flex flex-col gap-2 sm:flex-row sm:justify-end">
217+
<Button
218+
type="button"
219+
variant="outline"
220+
onClick={() => setConfirmOpen(false)}
221+
disabled={isPending}
222+
>
223+
Cancel
224+
</Button>
225+
<Button
226+
type="button"
227+
onClick={confirmBooking}
228+
disabled={isPending}
229+
aria-busy={isPending}
230+
>
231+
{isPending && <Spinner className="mr-2" aria-hidden="true" />}
232+
Confirm booking
233+
</Button>
234+
</DialogFooter>
235+
</DialogContent>
236+
</Dialog>
165237
</section>
166238
);
167239
}

0 commit comments

Comments
 (0)