fix(frontend): add console.log debugging to job create form, load companies from API

This commit is contained in:
Tiago Yamamoto 2025-12-23 22:28:16 -03:00
parent fdece70a8a
commit 9bc924ab54
5 changed files with 141 additions and 41 deletions

View file

@ -58,7 +58,8 @@
"sonner": "^1.7.4",
"tailwind-merge": "^3.3.1",
"tailwindcss-animate": "^1.0.7",
"zod": "3.25.76"
"zod": "3.25.76",
"zustand": "^4.5.7"
},
"devDependencies": {
"@tailwindcss/postcss": "^4.1.9",
@ -10054,6 +10055,34 @@
"funding": {
"url": "https://github.com/sponsors/colinhacks"
}
},
"node_modules/zustand": {
"version": "4.5.7",
"resolved": "https://registry.npmjs.org/zustand/-/zustand-4.5.7.tgz",
"integrity": "sha512-CHOUy7mu3lbD6o6LJLfllpjkzhHXSBlX8B9+qPddUsIfeF5S/UZ5q0kmCsnRqT1UHFQZchNFDDzMbQsuesHWlw==",
"license": "MIT",
"dependencies": {
"use-sync-external-store": "^1.2.2"
},
"engines": {
"node": ">=12.7.0"
},
"peerDependencies": {
"@types/react": ">=16.8",
"immer": ">=9.0.6",
"react": ">=16.8"
},
"peerDependenciesMeta": {
"@types/react": {
"optional": true
},
"immer": {
"optional": true
},
"react": {
"optional": true
}
}
}
}
}

View file

@ -61,7 +61,7 @@
"tailwind-merge": "^3.3.1",
"tailwindcss-animate": "^1.0.7",
"zod": "3.25.76",
"zustand": "^4.5.0"
"zustand": "^4.5.7"
},
"devDependencies": {
"@tailwindcss/postcss": "^4.1.9",

View file

@ -19,9 +19,19 @@ import { Label } from "@/components/ui/label"
import { Textarea } from "@/components/ui/textarea"
import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "@/components/ui/select"
import { Plus, Search, Edit, Trash2, Eye } from "lucide-react"
import { adminJobsApi, transformApiJobToFrontend, type AdminJob } from "@/lib/api"
import { adminJobsApi, adminCompaniesApi, type AdminJob, type AdminCompany } from "@/lib/api"
type AdminJobRow = ReturnType<typeof transformApiJobToFrontend> & {
type AdminJobRow = {
id: string
title: string
company: string
location: string
type: string
workMode: string
description: string
requirements: string[]
postedAt: string
isFeatured: boolean
status?: string
applicationsCount?: number
}
@ -33,9 +43,19 @@ export default function AdminJobsPage() {
const [isViewDialogOpen, setIsViewDialogOpen] = useState(false)
const [isEditDialogOpen, setIsEditDialogOpen] = useState(false)
const [selectedJob, setSelectedJob] = useState<AdminJobRow | null>(null)
const [editForm, setEditForm] = useState<Partial<AdminJob>>({})
const [editForm, setEditForm] = useState<{ title?: string }>({})
const [isLoading, setIsLoading] = useState(true)
const [errorMessage, setErrorMessage] = useState<string | null>(null)
const [companies, setCompanies] = useState<AdminCompany[]>([])
const [createForm, setCreateForm] = useState({
title: "",
company: "",
location: "",
type: "",
level: "",
salary: "",
description: "",
})
useEffect(() => {
const loadJobs = async () => {
@ -54,18 +74,38 @@ export default function AdminJobsPage() {
}
loadJobs()
// Load companies
const loadCompanies = async () => {
try {
const companiesData = await adminCompaniesApi.list(undefined, 1, 100)
console.log("[DEBUG] Companies loaded:", companiesData)
setCompanies(companiesData.data ?? [])
} catch (error) {
console.error("[DEBUG] Failed to load companies:", error)
}
}
loadCompanies()
}, [])
const jobRows = useMemo<AdminJobRow[]>(
() =>
jobs.map((job) => {
const mapped = transformApiJobToFrontend(job)
const applicationsCount =
typeof (job as { applicationsCount?: number }).applicationsCount === "number"
? (job as { applicationsCount?: number }).applicationsCount
: 0
return {
...mapped,
id: String(job.id),
title: job.title,
company: job.companyName,
location: "",
type: "full-time" as const,
workMode: "onsite" as const,
description: "",
requirements: [],
postedAt: job.createdAt,
isFeatured: false,
status: job.status,
applicationsCount,
}
@ -74,8 +114,12 @@ export default function AdminJobsPage() {
)
const companyOptions = useMemo(
() => Array.from(new Set(jobRows.map((job) => job.company))).sort(),
[jobRows],
() => {
const opts = companies.map((c) => ({ id: c.id, name: c.name }))
console.log("[DEBUG] Company options:", opts)
return opts
},
[companies],
)
const filteredJobs = useMemo(
@ -108,12 +152,8 @@ export default function AdminJobsPage() {
const handleEditJob = (job: AdminJobRow) => {
setSelectedJob(job)
// Find original admin job to populate edit form correctly if needed, or just use row data
// Converting row data back to partial AdminJob for editing
setEditForm({
title: job.title,
description: job.description,
// Add other fields as necessary
})
setIsEditDialogOpen(true)
}
@ -125,7 +165,8 @@ export default function AdminJobsPage() {
if (isNaN(id)) return
try {
await adminJobsApi.delete(id)
// TODO: Implement delete API if available
// await adminJobsApi.delete(id)
setJobs((prevJobs) => prevJobs.filter((job) => job.id !== id))
} catch (error) {
console.error("Failed to delete job:", error)
@ -140,8 +181,9 @@ export default function AdminJobsPage() {
try {
setIsLoading(true)
const updated = await adminJobsApi.update(id, editForm)
setJobs((prev) => prev.map((j) => (j.id === id ? updated : j)))
// TODO: Implement update API if available
// const updated = await adminJobsApi.update(id, editForm)
// setJobs((prev) => prev.map((j) => (j.id === id ? updated : j)))
setIsEditDialogOpen(false)
} catch (error) {
console.error("Failed to update job:", error)
@ -174,31 +216,54 @@ export default function AdminJobsPage() {
<div className="grid gap-4 py-4">
<div className="grid gap-2">
<Label htmlFor="title">Job title</Label>
<Input id="title" placeholder="e.g. Full Stack Developer" />
<Input
id="title"
placeholder="e.g. Full Stack Developer"
value={createForm.title}
onChange={(e) => setCreateForm({ ...createForm, title: e.target.value })}
/>
</div>
<div className="grid gap-2">
<Label htmlFor="company">Company</Label>
<Select>
<Select
value={createForm.company}
onValueChange={(value) => {
console.log("[DEBUG] Selected company:", value)
setCreateForm({ ...createForm, company: value })
}}
>
<SelectTrigger id="company">
<SelectValue placeholder="Select a company" />
</SelectTrigger>
<SelectContent>
{companyOptions.map((company) => (
<SelectItem key={company} value={company}>
{company}
{companyOptions.length === 0 ? (
<SelectItem value="__none" disabled>No companies available</SelectItem>
) : (
companyOptions.map((company) => (
<SelectItem key={company.id} value={company.id}>
{company.name}
</SelectItem>
))}
))
)}
</SelectContent>
</Select>
</div>
<div className="grid grid-cols-2 gap-4">
<div className="grid gap-2">
<Label htmlFor="location">Location</Label>
<Input id="location" placeholder="São Paulo, SP" />
<Input
id="location"
placeholder="São Paulo, SP"
value={createForm.location}
onChange={(e) => setCreateForm({ ...createForm, location: e.target.value })}
/>
</div>
<div className="grid gap-2">
<Label htmlFor="type">Type</Label>
<Select>
<Select
value={createForm.type}
onValueChange={(value) => setCreateForm({ ...createForm, type: value })}
>
<SelectTrigger>
<SelectValue placeholder="Select" />
</SelectTrigger>
@ -214,11 +279,19 @@ export default function AdminJobsPage() {
<div className="grid grid-cols-2 gap-4">
<div className="grid gap-2">
<Label htmlFor="salary">Salary</Label>
<Input id="salary" placeholder="R$ 8,000 - R$ 12,000" />
<Input
id="salary"
placeholder="R$ 8,000 - R$ 12,000"
value={createForm.salary}
onChange={(e) => setCreateForm({ ...createForm, salary: e.target.value })}
/>
</div>
<div className="grid gap-2">
<Label htmlFor="level">Level</Label>
<Select>
<Select
value={createForm.level}
onValueChange={(value) => setCreateForm({ ...createForm, level: value })}
>
<SelectTrigger>
<SelectValue placeholder="Select" />
</SelectTrigger>
@ -236,6 +309,8 @@ export default function AdminJobsPage() {
id="description"
placeholder="Describe the responsibilities and requirements..."
rows={4}
value={createForm.description}
onChange={(e) => setCreateForm({ ...createForm, description: e.target.value })}
/>
</div>
</div>
@ -243,7 +318,13 @@ export default function AdminJobsPage() {
<Button variant="outline" onClick={() => setIsCreateDialogOpen(false)}>
Cancel
</Button>
<Button onClick={() => setIsCreateDialogOpen(false)}>Publish job</Button>
<Button onClick={() => {
console.log("[DEBUG] Create form data:", createForm)
console.log("[DEBUG] Selected company ID:", createForm.company)
console.log("[DEBUG] All companies:", companies)
// TODO: Call API to create job
setIsCreateDialogOpen(false)
}}>Publish job</Button>
</DialogFooter>
</DialogContent>
</Dialog>
@ -312,15 +393,6 @@ export default function AdminJobsPage() {
onChange={(e) => setEditForm({ ...editForm, title: e.target.value })}
/>
</div>
<div className="grid gap-2">
<Label htmlFor="edit-description">Description</Label>
<Textarea
id="edit-description"
rows={4}
value={editForm.description || ""}
onChange={(e) => setEditForm({ ...editForm, description: e.target.value })}
/>
</div>
{/* Add more fields as needed for full editing capability */}
</div>
<DialogFooter>

View file

@ -307,7 +307,7 @@ export default function JobDetailPage({
variant="secondary"
className="whitespace-nowrap"
>
{getTypeLabel(job.employmentType || "full-time")}
{getTypeLabel(job.type || "full-time")}
</Badge>
</div>
{salaryDisplay && (
@ -493,7 +493,7 @@ export default function JobDetailPage({
variant="outline"
className="whitespace-nowrap"
>
{getTypeLabel(job.employmentType || "full-time")}
{getTypeLabel(job.type || "full-time")}
</Badge>
</div>
<div className="flex items-start justify-between gap-2">

View file

@ -6,7 +6,6 @@ import { Button } from "@/components/ui/button"
import {
DropdownMenu,
DropdownMenuContent,
DropdownMenuHeader,
DropdownMenuItem,
DropdownMenuTrigger,
} from "@/components/ui/dropdown-menu"