-
Notifications
You must be signed in to change notification settings - Fork 27
Develop #34
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Develop #34
Changes from all commits
960bf44
6576ace
52d2457
c8e9d84
b081101
c9a6f6e
c6bda93
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
This file was deleted.
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,10 +1,11 @@ | ||
| import { Button } from "@/components/ui/button"; | ||
| import { Badge } from "@/components/ui/badge"; | ||
| import { Card, CardContent } from "@/components/ui/card"; | ||
| import { Input } from "@/components/ui/input"; | ||
| import type { JobFile } from "@/types/jobs"; | ||
| import { RefreshCcw, Search } from "lucide-react"; | ||
| import type { Dispatch, SetStateAction } from "react"; | ||
| import type { JobFile, JobsMeta } from "@/types/jobs"; | ||
| import { Search } from "lucide-react"; | ||
| import type { Dispatch, ReactNode, SetStateAction } from "react"; | ||
|
|
||
| import { BriefcaseBusiness, FileSpreadsheet } from "lucide-react"; | ||
| interface JobsFiltersCardProps { | ||
| search: string; | ||
| setSearch: Dispatch<SetStateAction<string>>; | ||
|
|
@@ -14,8 +15,8 @@ interface JobsFiltersCardProps { | |
| selectedFile: string; | ||
| setSelectedFile: Dispatch<SetStateAction<string>>; | ||
| files: JobFile[]; | ||
| loading: boolean; | ||
| onRefresh: () => void; | ||
| meta: JobsMeta; | ||
| actions?: ReactNode; | ||
| } | ||
|
|
||
| export function JobsFiltersCard({ | ||
|
|
@@ -27,50 +28,65 @@ export function JobsFiltersCard({ | |
| selectedFile, | ||
| setSelectedFile, | ||
| files, | ||
| loading, | ||
| onRefresh, | ||
| meta, | ||
| actions, | ||
| }: JobsFiltersCardProps) { | ||
| return ( | ||
| <Card className="border-border/70 bg-card/85 backdrop-blur dark:bg-card/95"> | ||
| <CardContent className="grid gap-3 pt-6 md:grid-cols-4"> | ||
| <div className="relative md:col-span-2"> | ||
| <Search className="pointer-events-none absolute left-3 top-3 h-4 w-4 text-muted-foreground" /> | ||
| <Input | ||
| value={search} | ||
| onChange={(event) => setSearch(event.target.value)} | ||
| className="pl-9" | ||
| placeholder="Buscar por titulo, empresa, local ou link" | ||
| /> | ||
| <CardContent className="flex flex-col gap-3 pt-6"> | ||
| {/* Campo de busca */} | ||
| <div className="flex items-center gap-3"> | ||
| <div className="relative flex-1"> | ||
| <Search className="pointer-events-none absolute left-3 top-3 h-4 w-4 text-muted-foreground" /> | ||
| <Input | ||
| value={search} | ||
| onChange={(event) => setSearch(event.target.value)} | ||
| className="pl-9 w-full" | ||
| placeholder="Buscar por titulo, empresa, local ou link" | ||
| /> | ||
| </div> | ||
| <div className="flex items-center gap-2">{actions}</div> | ||
| </div> | ||
|
|
||
| <select | ||
| className="h-10 w-full rounded-md border border-input bg-background px-3 text-sm" | ||
| value={keywordFilter} | ||
| onChange={(event) => setKeywordFilter(event.target.value)} | ||
| > | ||
| <option value="all">Todas as palavras-chave</option> | ||
| {keywords.map((keyword) => ( | ||
| <option key={keyword} value={keyword}> | ||
| {keyword} | ||
| </option> | ||
| ))} | ||
| </select> | ||
|
|
||
| <div className="flex gap-2"> | ||
| {/* Seção de filtros */} | ||
| <div className="flex items-center gap-2 flex"> | ||
| <select | ||
| className="h-10 w-full rounded-md border border-input bg-background px-3 text-sm" | ||
| value={selectedFile} | ||
| onChange={(event) => setSelectedFile(event.target.value)} | ||
| className="h-10 rounded-md border border-input bg-background px-3 text-sm focus:outline-none focus:ring-2 focus:ring-ring focus:border-ring" | ||
| value={keywordFilter} | ||
|
Comment on lines
+52
to
+55
|
||
| onChange={(event) => setKeywordFilter(event.target.value)} | ||
| > | ||
| {files.map((file) => ( | ||
| <option key={file.file} value={file.file}> | ||
| {file.file} | ||
| <option value="all">Todas as palavras-chave</option> | ||
| {keywords.map((keyword) => ( | ||
| <option key={keyword} value={keyword}> | ||
| {keyword} | ||
| </option> | ||
| ))} | ||
| </select> | ||
| <Button variant="outline" size="sm" onClick={onRefresh} disabled={loading}> | ||
| <RefreshCcw className={`h-4 w-4 ${loading ? "animate-spin" : ""}`} /> | ||
| </Button> | ||
|
|
||
| <div> | ||
| <select | ||
| className="h-10 w-full rounded-md border border-input bg-background px-3 text-sm focus:outline-none focus:ring-2 focus:ring-ring focus:border-ring" | ||
| value={selectedFile} | ||
| onChange={(event) => setSelectedFile(event.target.value)} | ||
| > | ||
| {files.map((file) => ( | ||
| <option key={file.file} value={file.file}> | ||
| {file.file} | ||
| </option> | ||
| ))} | ||
| </select> | ||
| </div> | ||
|
|
||
| <div className="flex items-center gap-2"> | ||
| <Badge variant="secondary" className="gap-1 text-xs"> | ||
| <FileSpreadsheet className="h-3.5 w-3.5" /> | ||
| {meta.file || "Sem arquivo"} | ||
| </Badge> | ||
| <Badge className="gap-1 text-xs"> | ||
| <BriefcaseBusiness className="h-3.5 w-3.5" /> | ||
| {meta.total} vagas | ||
| </Badge> | ||
| </div> | ||
| </div> | ||
| </CardContent> | ||
| </Card> | ||
|
|
||
| Original file line number | Diff line number | Diff line change | ||
|---|---|---|---|---|
| @@ -1,34 +1,27 @@ | ||||
| import { Badge } from "@/components/ui/badge"; | ||||
| import { Card, CardDescription, CardHeader, CardTitle } from "@/components/ui/card"; | ||||
| import type { JobsMeta } from "@/types/jobs"; | ||||
| import { BriefcaseBusiness, FileSpreadsheet } from "lucide-react"; | ||||
| import type { ReactNode } from "react"; | ||||
| import { | ||||
| CardDescription, | ||||
| CardTitle, | ||||
| } from "@/components/ui/card"; | ||||
| import Logo from "../assets/logo-painel-vagas.svg"; | ||||
| import { ThemeToggle } from "@/components/ui/theme-toggle"; | ||||
| import { useTheme } from "@/hooks/useTheme"; | ||||
|
|
||||
| interface JobsHeaderCardProps { | ||||
| meta: JobsMeta; | ||||
| actions?: ReactNode; | ||||
| } | ||||
|
|
||||
| export function JobsHeaderCard({ meta, actions }: JobsHeaderCardProps) { | ||||
| export function JobsHeaderCard() { | ||||
| const { resolvedTheme, toggleTheme } = useTheme(); | ||||
| return ( | ||||
| <Card className="border-border/70 bg-card/85 backdrop-blur dark:bg-card/95"> | ||||
| <CardHeader className="gap-4 pb-4 md:flex-row md:items-center md:justify-between"> | ||||
| <div> | ||||
| <CardTitle className="text-3xl">Painel de Vagas</CardTitle> | ||||
| <CardDescription>Leitura automatica dos arquivos XLSX gerados em output.</CardDescription> | ||||
| </div> | ||||
| <div className="flex flex-wrap items-center gap-2"> | ||||
| {actions} | ||||
| <Badge variant="secondary" className="gap-1 text-xs"> | ||||
| <FileSpreadsheet className="h-3.5 w-3.5" /> | ||||
| {meta.file || "Sem arquivo"} | ||||
| </Badge> | ||||
| <Badge className="gap-1 text-xs"> | ||||
| <BriefcaseBusiness className="h-3.5 w-3.5" /> | ||||
| {meta.total} vagas | ||||
| </Badge> | ||||
| <> | ||||
| <div className="w-screen bg-[#004726] dark:bg-[#003318] p-6 -mx-8 flex items-end"> | ||||
| <CardTitle className="text-3xl text-white"> | ||||
| <img src={Logo} alt="Painel de Vagas" /> | ||||
| </CardTitle> | ||||
| <CardDescription className="text-white"> | ||||
| Leitura automatica dos arquivos XLSX gerados em output. | ||||
| </CardDescription> | ||||
| <div className="ml-auto self-start mr-8"> | ||||
| <ThemeToggle theme={resolvedTheme} onToggle={toggleTheme} /> | ||||
| </div> | ||||
| </CardHeader> | ||||
| </Card> | ||||
| </div> | ||||
|
|
||||
|
||||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There are two separate imports from
lucide-reactin this file. Consolidating them into a single import reduces noise and avoids accidental duplicate specifiers during future edits.