|
1 | | -import { JobsFiltersCard } from "@/components/JobsFiltersCard"; |
2 | | -import { JobsHeaderCard } from "@/components/JobsHeaderCard"; |
3 | | -import { JobsTableCard } from "@/components/JobsTableCard"; |
4 | | -import { Button } from "@/components/ui/button"; |
5 | | -import { useJobsData } from "@/hooks/useJobsData"; |
6 | | -import { useJobsFiltering } from "@/hooks/useJobsFiltering"; |
7 | | -import { useJobsPagination } from "@/hooks/useJobsPagination"; |
8 | | -import type { JobsMeta } from "@/types/jobs"; |
9 | | -import { useCallback, type SetStateAction } from "react"; |
10 | | -import { FiRefreshCw } from "react-icons/fi"; |
11 | | - |
12 | | -function formatDate(timestamp: JobsMeta["modifiedAt"]): string { |
13 | | - if (!timestamp) { |
14 | | - return "-"; |
15 | | - } |
16 | | - return new Date(timestamp).toLocaleString("pt-BR"); |
17 | | -} |
| 1 | +import { useState, useEffect } from "react"; |
| 2 | +import { Route, Routes } from "react-router-dom"; |
| 3 | +import LandingPage from "./pages/LandingPage"; |
| 4 | +import Dashboard from "./pages/Dashboard"; |
| 5 | +import NotFound from "./not_found"; |
| 6 | +import Loading from "./Loading"; |
18 | 7 |
|
19 | 8 | function App() { |
20 | | - const { files, selectedFile, setSelectedFile, jobs, meta, loading, scraping, error, triggerScraper } = |
21 | | - useJobsData(); |
22 | | - |
23 | | - const { search, setSearch, keywordFilter, setKeywordFilter, keywords, filteredJobs } = useJobsFiltering(jobs); |
| 9 | + const [appCarregando, setAppCarregando] = useState(true); |
24 | 10 |
|
25 | | - const { currentPage, setCurrentPage, pageSize, setPageSize, resetPagination, totalPages, paginatedJobs } = |
26 | | - useJobsPagination({ |
27 | | - filteredJobs, |
28 | | - }); |
| 11 | + useEffect(() => { |
| 12 | + const timer = setTimeout(() => { |
| 13 | + setAppCarregando(false); |
| 14 | + }, 2000); |
29 | 15 |
|
30 | | - const handleSearchChange = useCallback( |
31 | | - (value: SetStateAction<string>) => { |
32 | | - setSearch((previous) => (typeof value === "function" ? value(previous) : value)); |
33 | | - resetPagination(); |
34 | | - }, |
35 | | - [setSearch, resetPagination], |
36 | | - ); |
37 | | - |
38 | | - const handleKeywordFilterChange = useCallback( |
39 | | - (value: SetStateAction<string[]>) => { |
40 | | - setKeywordFilter((previous) => (typeof value === "function" ? value(previous) : value)); |
41 | | - resetPagination(); |
42 | | - }, |
43 | | - [setKeywordFilter, resetPagination], |
44 | | - ); |
| 16 | + return () => clearTimeout(timer); |
| 17 | + }, []); |
45 | 18 |
|
46 | | - const handleSelectedFileChange = useCallback( |
47 | | - (value: SetStateAction<string>) => { |
48 | | - setSelectedFile((previous) => (typeof value === "function" ? value(previous) : value)); |
49 | | - resetPagination(); |
50 | | - }, |
51 | | - [setSelectedFile, resetPagination], |
52 | | - ); |
53 | | - |
54 | | - const handlePageSizeChange = useCallback( |
55 | | - (value: number) => { |
56 | | - setPageSize(value); |
57 | | - resetPagination(); |
58 | | - }, |
59 | | - [setPageSize, resetPagination], |
60 | | - ); |
61 | | - |
62 | | - const handleScraper = useCallback(() => { |
63 | | - void triggerScraper(); |
64 | | - }, [triggerScraper]); |
| 19 | + if (appCarregando) { |
| 20 | + return <Loading />; |
| 21 | + } |
65 | 22 |
|
66 | 23 | return ( |
67 | | - <main className="relative min-h-screen overflow-hidden bg-background px-4 transition-colors duration-300 md:px-8"> |
68 | | - <div className="pointer-events-none absolute inset-0 -z-10 bg-[radial-gradient(circle_at_20%_15%,rgba(236,195,117,0.35),transparent_30%),radial-gradient(circle_at_80%_10%,rgba(92,151,191,0.28),transparent_35%),radial-gradient(circle_at_50%_95%,rgba(201,120,99,0.22),transparent_40%)] dark:bg-[radial-gradient(circle_at_20%_15%,rgba(240,180,95,0.18),transparent_30%),radial-gradient(circle_at_80%_10%,rgba(92,151,191,0.18),transparent_35%),radial-gradient(circle_at_50%_95%,rgba(201,120,99,0.15),transparent_40%)]" /> |
69 | | - |
70 | | - <section className="mx-auto flex w-full flex-col gap-6"> |
71 | | - <JobsHeaderCard /> |
72 | | - |
73 | | - <JobsFiltersCard |
74 | | - search={search} |
75 | | - setSearch={handleSearchChange} |
76 | | - keywordFilter={keywordFilter} |
77 | | - setKeywordFilter={handleKeywordFilterChange} |
78 | | - keywords={keywords} |
79 | | - selectedFile={selectedFile} |
80 | | - setSelectedFile={handleSelectedFileChange} |
81 | | - files={files} |
82 | | - meta={meta} |
83 | | - actions={ |
84 | | - <> |
85 | | - <Button |
86 | | - onClick={handleScraper} |
87 | | - disabled={scraping} |
88 | | - className="h-12 md:h-14 w-full sm:w-auto rounded-xl md:rounded-2xl bg-[#0c6b35] px-6 text-base text-white shadow-sm hover:bg-[#0a5b2d] whitespace-nowrap flex items-center gap-2" > |
89 | | - <FiRefreshCw className={`h-4 w-4 ${scraping ? "animate-spin" : ""}`} /> |
90 | | - {scraping ? "Buscando vagas..." : "Buscar vagas"} |
91 | | - </Button> |
92 | | - </> |
93 | | - } |
94 | | - /> |
95 | | - |
96 | | - <JobsTableCard |
97 | | - meta={meta} |
98 | | - filteredJobs={filteredJobs} |
99 | | - paginatedJobs={paginatedJobs} |
100 | | - loading={loading || scraping} |
101 | | - error={error} |
102 | | - formatDate={formatDate} |
103 | | - currentPage={currentPage} |
104 | | - totalPages={totalPages} |
105 | | - pageSize={pageSize} |
106 | | - onPageChange={setCurrentPage} |
107 | | - onPageSizeChange={handlePageSizeChange} |
108 | | - /> |
109 | | - </section> |
110 | | - </main> |
| 24 | + <Routes> |
| 25 | + <Route path="/" element={<LandingPage />} /> |
| 26 | + <Route path="/app" element={<Dashboard />} /> |
| 27 | + <Route path="*" element={<NotFound />} /> |
| 28 | + </Routes> |
111 | 29 | ); |
112 | 30 | } |
113 | 31 |
|
|
0 commit comments