Files
turnosxpress/txclient/src/app/landing/find/page.tsx
T
2026-07-16 20:48:43 -03:00

254 lines
8.9 KiB
TypeScript

"use client";
import AnimatedContainer from "@components/AnimatedConainer/AnimatedContainer";
import ProductItem, { FindResultsViewMode } from "@core/app/components/ProductItem/ProductItem";
import { PublicServicesResults } from "@models/Service.model";
import { useEffect, useState } from "react";
import { searchPublicServices } from "./Find.Service";
import { HEADER_WIDGETS, useHeaderStore } from "@core/Store/Header.Store";
import Filters from "@core/app/components/Home/Filters/Filters";
import { useEventHandlerStore, EVENT_TYPES } from "@core/Store/EventHandler.Store";
import { useAlert } from "@core/Store/Alert.Store";
import { Breadcrumbs, ButtonGroup, IconButton } from "@mui/material";
import Link from "next/link";
import GridViewOutlinedIcon from "@mui/icons-material/GridViewOutlined";
import SplitscreenOutlinedIcon from "@mui/icons-material/SplitscreenOutlined";
import FilterAltIcon from "@mui/icons-material/FilterAlt";
import Pagination from "@mui/material/Pagination";
import useWindowSize from "@core/app/hooks/WindowSize";
import { ScrollToTop } from "@core/app/components/ScrollTop";
import DefaultLoginAction from "@core/app/components/LoginAction/DefaultLoginAction";
export default function FindPage() {
const headerState = useHeaderStore();
const eventHandler = useEventHandlerStore();
const alert = useAlert();
const [windowWidth] = useWindowSize();
const [filterPage, setFilterPage] = useState<number>(1);
const [filterCompany, setFilterCompany] = useState<string>("");
const [filterCategory, setFilterCategory] = useState<string>("");
const [filterLocation, setFilterLocation] = useState<string>("");
const [filterPriceFrom, setFilterPriceFrom] = useState<number | null>(null);
const [filterPriceTo, setFilterPriceTo] = useState<number | null>(null);
const [filterDurationFrom, setFilterDurationFrom] = useState<number | null>(null);
const [filterDurationTo, setFilterDurationTo] = useState<number | null>(null);
const [viewMode, setViewMode] = useState<FindResultsViewMode>("card");
const [filterVisible, setFilterVisible] = useState<boolean>(true);
const [services, setServices] = useState<PublicServicesResults>({
data: [],
page: filterPage,
pages: 0,
});
const getFilter = () => {
let filter = {};
if (filterCompany) {
filter = { ...filter, ...{ companyId: filterCompany } };
}
if (filterCategory) {
filter = { ...filter, ...{ categoryId: parseInt(filterCategory) } };
}
if (filterLocation) {
filter = { ...filter, ...{ block: filterLocation } };
}
if (filterPriceFrom) {
filter = { ...filter, ...{ priceFrom: filterPriceFrom } };
}
if (filterPriceTo) {
filter = { ...filter, ...{ priceTo: filterPriceTo } };
}
if (filterDurationFrom) {
filter = { ...filter, ...{ lengthFrom: filterDurationFrom } };
}
if (filterDurationTo) {
filter = { ...filter, ...{ lengthTo: filterDurationTo } };
}
return filter;
};
const cargarServicios = () => {
eventHandler.setEventType(EVENT_TYPES.LOADING);
const data = getFilter();
searchPublicServices({
...{
query: headerState.publicFindText,
page: filterPage,
limit: 20,
},
...data,
})
.then((res) => {
setServices(res);
})
.catch((error) => {
alert.showError(error.format());
})
.finally(() => {
headerState.setPublicFindTrigger(false);
eventHandler.setEventType(EVENT_TYPES.SLEEP);
});
};
useEffect(() => {
if (headerState.publicFindTrigger) {
cargarServicios();
}
}, [
headerState.publicFindTrigger,
filterCompany,
filterCategory,
filterLocation,
filterPriceFrom,
filterPriceTo,
filterDurationFrom,
filterDurationTo,
filterPage,
]);
useEffect(() => {
if (windowWidth < 850) {
setFilterVisible(false);
return;
}
setFilterVisible(true);
}, [windowWidth]);
useEffect(() => {
if (windowWidth < 850) {
setViewMode("grid");
return;
}
setViewMode("card");
headerState.setActiveWidget(HEADER_WIDGETS.PUBLIC_FIND);
}, []);
const handleChange = (event: React.ChangeEvent<unknown>, value: number) => {
setFilterPage(value);
headerState.setPublicFindTrigger(true);
};
return (
<AnimatedContainer
color="#aeaeae"
minSize={150}
maxSize={500}
items={10}
style={{
display: "flex",
flexDirection: "column",
justifyContent: "center",
alignItems: "center",
}}
>
<ScrollToTop />
<DefaultLoginAction />
<div
className="homeCentered"
style={{
display: "flex",
justifyContent: "space-between",
paddingLeft: "40px",
}}
>
<Breadcrumbs
aria-label="breadcrumb"
sx={{
"& .MuiBreadcrumbs-separator": {
color: "inherit",
},
marginTop: "15px",
}}
>
<Link href="/">Inicio</Link>
<span>Buscar servicios</span>
</Breadcrumbs>
<ButtonGroup
variant="outlined"
aria-label="Basic button group"
sx={{ marginTop: "10px", marginRight: "30px" }}
>
{windowWidth < 850 && (
<IconButton onClick={() => setFilterVisible(!filterVisible)}>
<FilterAltIcon
sx={{ color: filterVisible ? "var(--wine-red)" : "ineherit" }}
/>
</IconButton>
)}
<IconButton onClick={() => setViewMode("card")}>
<GridViewOutlinedIcon
sx={{ color: viewMode === "card" ? "var(--wine-red)" : "ineherit" }}
/>
</IconButton>
<IconButton onClick={() => setViewMode("grid")}>
<SplitscreenOutlinedIcon
sx={{ color: viewMode === "grid" ? "var(--wine-red)" : "ineherit" }}
/>
</IconButton>
</ButtonGroup>
</div>
<div
className="homeCentered"
style={{
paddingTop: "10px",
paddingLeft: "37px",
paddingRight: "0px",
paddingBottom: "0px",
display: "flex",
flexDirection: "row",
justifyContent: "start",
gap: "20px",
minHeight: "700px",
}}
>
<Filters
onFilter={cargarServicios}
setFilterCompany={setFilterCompany}
setFilterCategory={setFilterCategory}
setFilterLocation={setFilterLocation}
setFilterDurationFrom={setFilterDurationFrom}
setFilterDurationTo={setFilterDurationTo}
setFilterPriceFrom={setFilterPriceFrom}
setFilterPriceTo={setFilterPriceTo}
visible={filterVisible}
/>
<div
style={{
padding: "0px 0px 40px 0px",
display: "flex",
flexDirection: viewMode === "card" ? "row" : "column",
justifyContent: "start",
gap: "20px",
flexWrap: "wrap",
}}
>
{services.data.map((service) => (
<ProductItem
product={service}
key={service.id}
width={260}
viewMode={viewMode}
/>
))}
</div>
</div>
<div style={{ display: "flex", justifyContent: "center", marginBottom: "20px" }}>
<Pagination count={services.pages} variant="outlined" onChange={handleChange} />
</div>
</AnimatedContainer>
);
}