Refactor HomePage and more!
This commit is contained in:
+2
-1
@@ -6,7 +6,8 @@
|
||||
"scripts": {
|
||||
"dev": "vite",
|
||||
"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"
|
||||
},
|
||||
"dependencies": {
|
||||
|
||||
@@ -1,9 +1,10 @@
|
||||
import { Separator } from "../ui/separator";
|
||||
import { Card, CardContent, CardHeader } from "../ui/card";
|
||||
import { Card, CardContent } from "../ui/card";
|
||||
import { Typography } from "../ui/typography";
|
||||
import { BedDoubleIcon, BedSingleIcon, UserIcon } from "lucide-react";
|
||||
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 {
|
||||
room: RoomCategory;
|
||||
@@ -34,50 +35,59 @@ export function RoomItemCard({ room = defaultRoom }: RoomItemCardProps) {
|
||||
bedTypeList.at(1) !== undefined && bedTypeList[1] > 0;
|
||||
|
||||
return (
|
||||
<Card id={room.id.toString()}>
|
||||
<CardHeader className="p-0 m-0 mb-5">
|
||||
<Card id={room.id.toString()} className="relative">
|
||||
{/* <CardHeader className="p-0 m-0 mb-5">
|
||||
</CardHeader> */}
|
||||
<CardContent className="flex flex-col h-full w-full p-0">
|
||||
<div className="">
|
||||
<img
|
||||
src={
|
||||
mainPhoto?.path ??
|
||||
"https://images.unsplash.com/photo-1618773928121-c32242e63f39"
|
||||
}
|
||||
className="rounded-md"
|
||||
src={mainPhoto?.path ?? roomImg}
|
||||
className="rounded-t-md w-full aspect-[4/3] object-cover"
|
||||
></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}
|
||||
</Typography>
|
||||
</CardHeader>
|
||||
<CardContent>
|
||||
<Typography variant={"p"} as="p">
|
||||
</div>
|
||||
<div>
|
||||
<Typography variant={"p"} as="h2" className="px-5">
|
||||
{room.description}
|
||||
</Typography>
|
||||
</div>
|
||||
<div className="pb-4 mt-auto">
|
||||
<Separator className="my-4" />
|
||||
<div className="flex justify-around">
|
||||
<div className="flex flex-row gap-2">
|
||||
{hasSingleBed && (
|
||||
<IconWithTooltipNumber
|
||||
altText="Single bed"
|
||||
amount={bedTypeList[0]}
|
||||
<IconWithTooltip
|
||||
tooltipText="Single bed"
|
||||
label={bedTypeList[0]?.toString()}
|
||||
>
|
||||
<BedSingleIcon />
|
||||
</IconWithTooltipNumber>
|
||||
</IconWithTooltip>
|
||||
)}
|
||||
{hasDoubleBed && (
|
||||
<>
|
||||
<IconWithTooltipNumber
|
||||
altText="Double bed"
|
||||
amount={bedTypeList[1]}
|
||||
<IconWithTooltip
|
||||
tooltipText="Double bed"
|
||||
label={bedTypeList[1]?.toString()}
|
||||
>
|
||||
<BedDoubleIcon />
|
||||
</IconWithTooltipNumber>
|
||||
</IconWithTooltip>
|
||||
</>
|
||||
)}
|
||||
</div>
|
||||
<div className="flex flex-row">
|
||||
<IconWithTooltip
|
||||
tooltipText="Max. gests"
|
||||
label={room.maxGuestNum?.toString()}
|
||||
labelPosition={"right"}
|
||||
>
|
||||
<UserIcon />
|
||||
<Typography variant={"p_inline"} className="ml-3">
|
||||
{room.maxGuestNum}
|
||||
</Typography>
|
||||
</IconWithTooltip>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</CardContent>
|
||||
|
||||
@@ -5,12 +5,11 @@ import "react-day-picker/dist/style.css";
|
||||
import { DatePickerWithRange } from "../ui/dateRange-picker";
|
||||
import { Button } from "../ui/button";
|
||||
import { SearchIcon } from "lucide-react";
|
||||
import { useEffect, useState } from "react";
|
||||
import { useState } from "react";
|
||||
import { SearchFilter } from "@/model/SearchFilter";
|
||||
import { DateRange } from "react-day-picker";
|
||||
import { useToast } from "../ui/use-toast";
|
||||
import { useAppStore } from "@/store";
|
||||
import { useLocation } from "react-router-dom";
|
||||
|
||||
type funOnSearchClick = (newFilter: SearchFilter) => void;
|
||||
|
||||
@@ -29,10 +28,10 @@ export function SearchFilterCard({
|
||||
|
||||
//On location change, try to load searchFilter from state.
|
||||
//FIXME: Si llegamos sin state, hay que borrar el state global...
|
||||
const location = useLocation();
|
||||
useEffect(() => {
|
||||
setSearchFilter(location.state);
|
||||
}, [location]);
|
||||
// const location = useLocation();
|
||||
// useEffect(() => {
|
||||
// setSearchFilter(location.state);
|
||||
// }, [location]);
|
||||
|
||||
const { toast } = useToast();
|
||||
|
||||
@@ -56,8 +55,9 @@ export function SearchFilterCard({
|
||||
return;
|
||||
}
|
||||
|
||||
if (onSearchClick) {
|
||||
setAppSearchFilter(searchFilter);
|
||||
|
||||
if (onSearchClick) {
|
||||
onSearchClick(searchFilter);
|
||||
}
|
||||
};
|
||||
@@ -68,8 +68,6 @@ export function SearchFilterCard({
|
||||
...searchFilter,
|
||||
dateRange: newRange,
|
||||
});
|
||||
|
||||
console.log("SearchFilterCard filter UPDATED");
|
||||
};
|
||||
|
||||
const datePickerElement =
|
||||
|
||||
@@ -46,13 +46,10 @@ export function DatePickerWithRange({
|
||||
const handleDayClickFrom = (day: Date, mods: ActiveModifiers) => {
|
||||
const newDateRange: DateRange = {
|
||||
from: mods.selected ? undefined : day,
|
||||
to: dateRange?.to,
|
||||
to: undefined,
|
||||
};
|
||||
|
||||
setDateRange(newDateRange);
|
||||
if (updateDateRange !== undefined) {
|
||||
updateDateRange(newDateRange);
|
||||
}
|
||||
fnUpdateRange(newDateRange);
|
||||
};
|
||||
|
||||
const handleDayClickTo = (day: Date, mods: ActiveModifiers) => {
|
||||
@@ -61,10 +58,13 @@ export function DatePickerWithRange({
|
||||
to: mods.selected ? undefined : day,
|
||||
};
|
||||
|
||||
setDateRange(newDateRange);
|
||||
fnUpdateRange(newDateRange);
|
||||
};
|
||||
|
||||
const fnUpdateRange = (range: DateRange) => {
|
||||
setDateRange(range);
|
||||
if (updateDateRange !== undefined) {
|
||||
updateDateRange(newDateRange);
|
||||
updateDateRange(range);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -107,7 +107,7 @@ export function DatePickerWithRange({
|
||||
)}
|
||||
</Button>
|
||||
</PopoverTrigger>
|
||||
<PopoverContent className="w-auto p-0" align="start">
|
||||
<PopoverContent className="w-auto p-0" align="center">
|
||||
<Calendar
|
||||
initialFocus
|
||||
mode="single"
|
||||
@@ -137,11 +137,11 @@ export function DatePickerWithRange({
|
||||
)}
|
||||
</Button>
|
||||
</PopoverTrigger>
|
||||
<PopoverContent className="w-auto p-0" align="start">
|
||||
<PopoverContent className="w-auto p-0" align="center">
|
||||
<Calendar
|
||||
initialFocus
|
||||
mode="single"
|
||||
defaultMonth={dateRange?.to}
|
||||
defaultMonth={dateRange?.to ?? dateRange?.from}
|
||||
selected={dateRange?.to}
|
||||
onDayClick={handleDayClickTo}
|
||||
numberOfMonths={1}
|
||||
|
||||
@@ -8,21 +8,23 @@ import {
|
||||
import { PropsWithChildren } from "react";
|
||||
|
||||
interface IconWithTooltipNumberProps {
|
||||
amount?: number | null | undefined;
|
||||
altText?: string | null | undefined;
|
||||
label?: string | null | undefined;
|
||||
labelPosition?: "left" | "right" | null | undefined;
|
||||
tooltipText?: string | null | undefined;
|
||||
}
|
||||
|
||||
export function IconWithTooltipNumber({
|
||||
amount = undefined,
|
||||
altText = undefined,
|
||||
export function IconWithTooltip({
|
||||
label = undefined,
|
||||
labelPosition = "left",
|
||||
tooltipText = undefined,
|
||||
children,
|
||||
}: PropsWithChildren<IconWithTooltipNumberProps>) {
|
||||
const iconElement = altText ? (
|
||||
const iconElement = tooltipText ? (
|
||||
<TooltipProvider>
|
||||
<Tooltip>
|
||||
<TooltipTrigger asChild>{children}</TooltipTrigger>
|
||||
<TooltipContent>
|
||||
<p>{altText}</p>
|
||||
<p>{tooltipText}</p>
|
||||
</TooltipContent>
|
||||
</Tooltip>
|
||||
</TooltipProvider>
|
||||
@@ -30,10 +32,16 @@ export function IconWithTooltipNumber({
|
||||
<>{children}</>
|
||||
);
|
||||
|
||||
const labelElement = (
|
||||
<Typography variant={"p_inline"} className="px-1">
|
||||
{label}
|
||||
</Typography>
|
||||
);
|
||||
return (
|
||||
<>
|
||||
{amount && <Typography variant={"p_inline"}>{amount}</Typography>}
|
||||
{label && labelPosition == "left" && labelElement}
|
||||
{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
@@ -10,7 +10,7 @@ function Root() {
|
||||
<>
|
||||
<ThemeProvider defaultTheme="dark" storageKey="vite-ui-theme">
|
||||
<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 />
|
||||
</div>
|
||||
<Toaster />
|
||||
|
||||
@@ -0,0 +1,3 @@
|
||||
.homePageRoomGrid {
|
||||
grid-template-columns: repeat(auto-fit, minmax(300px, 3fr));
|
||||
}
|
||||
@@ -8,6 +8,8 @@ import { Typography } from "@/components/ui/typography";
|
||||
import { RoomCategory } from "@/model/RoomCategory";
|
||||
import { SearchFilter } from "@/model/SearchFilter";
|
||||
import { useNavigate } from "react-router-dom";
|
||||
import { LoaderIcon } from "lucide-react";
|
||||
import "./home-page.css";
|
||||
|
||||
function Homepage() {
|
||||
const { roomCategoryList, isLoading, isError } = useAPIRoomCategories();
|
||||
@@ -27,13 +29,15 @@ function Homepage() {
|
||||
<Separator className="my-10" />
|
||||
<SearchFilterCard onSearchClick={onBtSearchClick} />
|
||||
<Separator className="my-10" />
|
||||
<div className="grid grid-cols-2 gap-4">{roomList}</div>
|
||||
<div className="grid gap-4 homePageRoomGrid">{roomList}</div>
|
||||
{isLoading && (
|
||||
<>
|
||||
<Skeleton className="w-full h-[200px] mx-auto flex justify-center items-center flex-col">
|
||||
<LoaderIcon />
|
||||
<Typography variant={"h3"} as="h2">
|
||||
Loading...
|
||||
</Typography>
|
||||
<Skeleton className="w-[400px] h-[200px] mx-auto" />
|
||||
</Skeleton>
|
||||
</>
|
||||
)}
|
||||
<Separator className="my-10" />
|
||||
|
||||
Reference in New Issue
Block a user