Refactor HomePage and more!

This commit is contained in:
2024-08-30 21:20:40 +02:00
parent b034d2e9c9
commit 2d2992593a
10 changed files with 4024 additions and 79 deletions
+2 -1
View File
@@ -6,7 +6,8 @@
"scripts": { "scripts": {
"dev": "vite", "dev": "vite",
"build": "tsc && vite build", "build": "tsc && vite build",
"lint": "eslint . --ext ts,tsx --report-unused-disable-directives --max-warnings 0", "lint": "eslint . --ext ts,tsx --report-unused-disable-directives --max-warnings 0 && npx prettier . --check",
"pretty": "npx prettier . --write",
"preview": "vite preview" "preview": "vite preview"
}, },
"dependencies": { "dependencies": {
+34 -24
View File
@@ -1,9 +1,10 @@
import { Separator } from "../ui/separator"; import { Separator } from "../ui/separator";
import { Card, CardContent, CardHeader } from "../ui/card"; import { Card, CardContent } from "../ui/card";
import { Typography } from "../ui/typography"; import { Typography } from "../ui/typography";
import { BedDoubleIcon, BedSingleIcon, UserIcon } from "lucide-react"; import { BedDoubleIcon, BedSingleIcon, UserIcon } from "lucide-react";
import { RoomCategory, RoomCategoryPhoto } from "@/model/RoomCategory"; import { RoomCategory, RoomCategoryPhoto } from "@/model/RoomCategory";
import { IconWithTooltipNumber } from "../ui/icon-number-tooltip"; import { IconWithTooltip } from "../ui/icon-number-tooltip";
import roomImg from "@/res/SomniaRoomImage.svg";
interface RoomItemCardProps { interface RoomItemCardProps {
room: RoomCategory; room: RoomCategory;
@@ -34,50 +35,59 @@ export function RoomItemCard({ room = defaultRoom }: RoomItemCardProps) {
bedTypeList.at(1) !== undefined && bedTypeList[1] > 0; bedTypeList.at(1) !== undefined && bedTypeList[1] > 0;
return ( return (
<Card id={room.id.toString()}> <Card id={room.id.toString()} className="relative">
<CardHeader className="p-0 m-0 mb-5"> {/* <CardHeader className="p-0 m-0 mb-5">
</CardHeader> */}
<CardContent className="flex flex-col h-full w-full p-0">
<div className="">
<img <img
src={ src={mainPhoto?.path ?? roomImg}
mainPhoto?.path ?? className="rounded-t-md w-full aspect-[4/3] object-cover"
"https://images.unsplash.com/photo-1618773928121-c32242e63f39"
}
className="rounded-md"
></img> ></img>
<Typography variant={"h2"} as="h1" className="mx-5 py-2"> <Separator className="my-0 border-2" />
</div>
<div>
<Typography variant={"h2"} as="h2" className="pt-4 px-4 border-none">
{room.name} {room.name}
</Typography> </Typography>
</CardHeader> </div>
<CardContent> <div>
<Typography variant={"p"} as="p"> <Typography variant={"p"} as="h2" className="px-5">
{room.description} {room.description}
</Typography> </Typography>
</div>
<div className="pb-4 mt-auto">
<Separator className="my-4" /> <Separator className="my-4" />
<div className="flex justify-around"> <div className="flex justify-around">
<div className="flex flex-row gap-2"> <div className="flex flex-row gap-2">
{hasSingleBed && ( {hasSingleBed && (
<IconWithTooltipNumber <IconWithTooltip
altText="Single bed" tooltipText="Single bed"
amount={bedTypeList[0]} label={bedTypeList[0]?.toString()}
> >
<BedSingleIcon /> <BedSingleIcon />
</IconWithTooltipNumber> </IconWithTooltip>
)} )}
{hasDoubleBed && ( {hasDoubleBed && (
<> <>
<IconWithTooltipNumber <IconWithTooltip
altText="Double bed" tooltipText="Double bed"
amount={bedTypeList[1]} label={bedTypeList[1]?.toString()}
> >
<BedDoubleIcon /> <BedDoubleIcon />
</IconWithTooltipNumber> </IconWithTooltip>
</> </>
)} )}
</div> </div>
<div className="flex flex-row"> <div className="flex flex-row">
<IconWithTooltip
tooltipText="Max. gests"
label={room.maxGuestNum?.toString()}
labelPosition={"right"}
>
<UserIcon /> <UserIcon />
<Typography variant={"p_inline"} className="ml-3"> </IconWithTooltip>
{room.maxGuestNum} </div>
</Typography>
</div> </div>
</div> </div>
</CardContent> </CardContent>
+7 -9
View File
@@ -5,12 +5,11 @@ import "react-day-picker/dist/style.css";
import { DatePickerWithRange } from "../ui/dateRange-picker"; import { DatePickerWithRange } from "../ui/dateRange-picker";
import { Button } from "../ui/button"; import { Button } from "../ui/button";
import { SearchIcon } from "lucide-react"; import { SearchIcon } from "lucide-react";
import { useEffect, useState } from "react"; import { useState } from "react";
import { SearchFilter } from "@/model/SearchFilter"; import { SearchFilter } from "@/model/SearchFilter";
import { DateRange } from "react-day-picker"; import { DateRange } from "react-day-picker";
import { useToast } from "../ui/use-toast"; import { useToast } from "../ui/use-toast";
import { useAppStore } from "@/store"; import { useAppStore } from "@/store";
import { useLocation } from "react-router-dom";
type funOnSearchClick = (newFilter: SearchFilter) => void; type funOnSearchClick = (newFilter: SearchFilter) => void;
@@ -29,10 +28,10 @@ export function SearchFilterCard({
//On location change, try to load searchFilter from state. //On location change, try to load searchFilter from state.
//FIXME: Si llegamos sin state, hay que borrar el state global... //FIXME: Si llegamos sin state, hay que borrar el state global...
const location = useLocation(); // const location = useLocation();
useEffect(() => { // useEffect(() => {
setSearchFilter(location.state); // setSearchFilter(location.state);
}, [location]); // }, [location]);
const { toast } = useToast(); const { toast } = useToast();
@@ -56,8 +55,9 @@ export function SearchFilterCard({
return; return;
} }
if (onSearchClick) {
setAppSearchFilter(searchFilter); setAppSearchFilter(searchFilter);
if (onSearchClick) {
onSearchClick(searchFilter); onSearchClick(searchFilter);
} }
}; };
@@ -68,8 +68,6 @@ export function SearchFilterCard({
...searchFilter, ...searchFilter,
dateRange: newRange, dateRange: newRange,
}); });
console.log("SearchFilterCard filter UPDATED");
}; };
const datePickerElement = const datePickerElement =
+10 -10
View File
@@ -46,13 +46,10 @@ export function DatePickerWithRange({
const handleDayClickFrom = (day: Date, mods: ActiveModifiers) => { const handleDayClickFrom = (day: Date, mods: ActiveModifiers) => {
const newDateRange: DateRange = { const newDateRange: DateRange = {
from: mods.selected ? undefined : day, from: mods.selected ? undefined : day,
to: dateRange?.to, to: undefined,
}; };
setDateRange(newDateRange); fnUpdateRange(newDateRange);
if (updateDateRange !== undefined) {
updateDateRange(newDateRange);
}
}; };
const handleDayClickTo = (day: Date, mods: ActiveModifiers) => { const handleDayClickTo = (day: Date, mods: ActiveModifiers) => {
@@ -61,10 +58,13 @@ export function DatePickerWithRange({
to: mods.selected ? undefined : day, to: mods.selected ? undefined : day,
}; };
setDateRange(newDateRange); fnUpdateRange(newDateRange);
};
const fnUpdateRange = (range: DateRange) => {
setDateRange(range);
if (updateDateRange !== undefined) { if (updateDateRange !== undefined) {
updateDateRange(newDateRange); updateDateRange(range);
} }
}; };
@@ -107,7 +107,7 @@ export function DatePickerWithRange({
)} )}
</Button> </Button>
</PopoverTrigger> </PopoverTrigger>
<PopoverContent className="w-auto p-0" align="start"> <PopoverContent className="w-auto p-0" align="center">
<Calendar <Calendar
initialFocus initialFocus
mode="single" mode="single"
@@ -137,11 +137,11 @@ export function DatePickerWithRange({
)} )}
</Button> </Button>
</PopoverTrigger> </PopoverTrigger>
<PopoverContent className="w-auto p-0" align="start"> <PopoverContent className="w-auto p-0" align="center">
<Calendar <Calendar
initialFocus initialFocus
mode="single" mode="single"
defaultMonth={dateRange?.to} defaultMonth={dateRange?.to ?? dateRange?.from}
selected={dateRange?.to} selected={dateRange?.to}
onDayClick={handleDayClickTo} onDayClick={handleDayClickTo}
numberOfMonths={1} numberOfMonths={1}
+16 -8
View File
@@ -8,21 +8,23 @@ import {
import { PropsWithChildren } from "react"; import { PropsWithChildren } from "react";
interface IconWithTooltipNumberProps { interface IconWithTooltipNumberProps {
amount?: number | null | undefined; label?: string | null | undefined;
altText?: string | null | undefined; labelPosition?: "left" | "right" | null | undefined;
tooltipText?: string | null | undefined;
} }
export function IconWithTooltipNumber({ export function IconWithTooltip({
amount = undefined, label = undefined,
altText = undefined, labelPosition = "left",
tooltipText = undefined,
children, children,
}: PropsWithChildren<IconWithTooltipNumberProps>) { }: PropsWithChildren<IconWithTooltipNumberProps>) {
const iconElement = altText ? ( const iconElement = tooltipText ? (
<TooltipProvider> <TooltipProvider>
<Tooltip> <Tooltip>
<TooltipTrigger asChild>{children}</TooltipTrigger> <TooltipTrigger asChild>{children}</TooltipTrigger>
<TooltipContent> <TooltipContent>
<p>{altText}</p> <p>{tooltipText}</p>
</TooltipContent> </TooltipContent>
</Tooltip> </Tooltip>
</TooltipProvider> </TooltipProvider>
@@ -30,10 +32,16 @@ export function IconWithTooltipNumber({
<>{children}</> <>{children}</>
); );
const labelElement = (
<Typography variant={"p_inline"} className="px-1">
{label}
</Typography>
);
return ( return (
<> <>
{amount && <Typography variant={"p_inline"}>{amount}</Typography>} {label && labelPosition == "left" && labelElement}
{iconElement} {iconElement}
{label && labelPosition == "right" && labelElement}
</> </>
); );
} }
File diff suppressed because it is too large Load Diff

After

Width:  |  Height:  |  Size: 133 KiB

File diff suppressed because it is too large Load Diff

After

Width:  |  Height:  |  Size: 96 KiB

+1 -1
View File
@@ -10,7 +10,7 @@ function Root() {
<> <>
<ThemeProvider defaultTheme="dark" storageKey="vite-ui-theme"> <ThemeProvider defaultTheme="dark" storageKey="vite-ui-theme">
<AppHeader /> <AppHeader />
<div className="appPage bg-background text-foreground"> <div className="w-full sm:w-[90%] md:w-[80%] mx-auto p-8 text-center bg-background text-foreground">
<Outlet /> <Outlet />
</div> </div>
<Toaster /> <Toaster />
+3
View File
@@ -0,0 +1,3 @@
.homePageRoomGrid {
grid-template-columns: repeat(auto-fit, minmax(300px, 3fr));
}
+6 -2
View File
@@ -8,6 +8,8 @@ import { Typography } from "@/components/ui/typography";
import { RoomCategory } from "@/model/RoomCategory"; import { RoomCategory } from "@/model/RoomCategory";
import { SearchFilter } from "@/model/SearchFilter"; import { SearchFilter } from "@/model/SearchFilter";
import { useNavigate } from "react-router-dom"; import { useNavigate } from "react-router-dom";
import { LoaderIcon } from "lucide-react";
import "./home-page.css";
function Homepage() { function Homepage() {
const { roomCategoryList, isLoading, isError } = useAPIRoomCategories(); const { roomCategoryList, isLoading, isError } = useAPIRoomCategories();
@@ -27,13 +29,15 @@ function Homepage() {
<Separator className="my-10" /> <Separator className="my-10" />
<SearchFilterCard onSearchClick={onBtSearchClick} /> <SearchFilterCard onSearchClick={onBtSearchClick} />
<Separator className="my-10" /> <Separator className="my-10" />
<div className="grid grid-cols-2 gap-4">{roomList}</div> <div className="grid gap-4 homePageRoomGrid">{roomList}</div>
{isLoading && ( {isLoading && (
<> <>
<Skeleton className="w-full h-[200px] mx-auto flex justify-center items-center flex-col">
<LoaderIcon />
<Typography variant={"h3"} as="h2"> <Typography variant={"h3"} as="h2">
Loading... Loading...
</Typography> </Typography>
<Skeleton className="w-[400px] h-[200px] mx-auto" /> </Skeleton>
</> </>
)} )}
<Separator className="my-10" /> <Separator className="my-10" />