Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "elo",
"version": "1.47.0",
"version": "1.50.1",
"private": true,
"type": "module",
"scripts": {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
-- Backfill de filial para veículos legados (filialId NULL) criados antes do
-- vínculo veículo→filial. Atribui automaticamente APENAS quando o mapeamento é
-- inequívoco: o `enterprise` legado do veículo corresponde a uma empresa que
-- possui exatamente UMA filial. Casos ambíguos (empresa com várias filiais)
-- permanecem NULL e devem ser ajustados manualmente pelo admin.
UPDATE "vehicles" v
SET "filialId" = sub."filialId"
FROM (
SELECT f."id" AS "filialId", e."enterprise" AS "enterprise"
FROM "filiais" f
JOIN "empresas" e ON e."id" = f."empresaId"
) sub
WHERE v."filialId" IS NULL
AND v."enterprise" = sub."enterprise"
AND (
SELECT COUNT(*)
FROM "filiais" f2
JOIN "empresas" e2 ON e2."id" = f2."empresaId"
WHERE e2."enterprise" = v."enterprise"
) = 1;
70 changes: 48 additions & 22 deletions src/app/(authenticated)/admin/vehicles/page.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
"use client"

import { useState } from "react"
import { Plus, Search, Edit, Trash2, BarChart3, Car, TrendingUp } from "lucide-react"
import { Plus, Search, Edit, Trash2, BarChart3, Car, TrendingUp, CalendarPlus } from "lucide-react"
import Image from "next/image"
import { api } from "@/trpc/react"
import { Button } from "@/components/ui/button"
Expand All @@ -11,6 +11,7 @@ import { Badge } from "@/components/ui/badge"
import { Dialog, DialogContent, DialogHeader, DialogTitle, DialogTrigger } from "@/components/ui/dialog"
import { Tabs, TabsContent, TabsList, TabsTrigger } from "@/components/ui/tabs"
import { VehicleForm } from "@/components/admin/vehicles/vehicle-form"
import { ManualRentForm } from "@/components/admin/vehicles/manual-rent-form"
import { VehicleMetrics } from "@/components/admin/vehicles/vehicle-metrics"
import { VehicleUsageHistory } from "@/components/admin/vehicles/vehicle-usage-history"
import { UserRanking } from "@/components/admin/vehicles/user-ranking"
Expand All @@ -23,6 +24,7 @@ export default function VehiclesAdminClient() {
const [searchTerm, setSearchTerm] = useState("")
const [selectedVehicle, setSelectedVehicle] = useState<Vehicle | null>(null)
const [isCreateDialogOpen, setIsCreateDialogOpen] = useState(false)
const [isRentDialogOpen, setIsRentDialogOpen] = useState(false)
const [isEditDialogOpen, setIsEditDialogOpen] = useState(false)
const [imageErrors, setImageErrors] = useState<Set<string>>(new Set())

Expand Down Expand Up @@ -101,26 +103,46 @@ export default function VehiclesAdminClient() {
Gerencie a frota de veículos da empresa
</p>
</div>
<Dialog open={isCreateDialogOpen} onOpenChange={setIsCreateDialogOpen}>
<DialogTrigger asChild>
<Button>
<Plus className="mr-2 h-4 w-4" />
Novo Veículo
</Button>
</DialogTrigger>
<DialogContent className="max-w-2xl">
<DialogHeader>
<DialogTitle>Criar Novo Veículo</DialogTitle>
</DialogHeader>
<VehicleForm
onSuccess={() => {
setIsCreateDialogOpen(false)
void refetch()
}}
onCancel={() => setIsCreateDialogOpen(false)}
/>
</DialogContent>
</Dialog>
<div className="flex items-center gap-2">
<Dialog open={isRentDialogOpen} onOpenChange={setIsRentDialogOpen}>
<DialogTrigger asChild>
<Button variant="outline">
<CalendarPlus className="mr-2 h-4 w-4" />
Novo Agendamento
</Button>
</DialogTrigger>
<DialogContent className="max-w-2xl max-h-[90vh] overflow-y-auto">
<DialogHeader>
<DialogTitle>Novo Agendamento</DialogTitle>
</DialogHeader>
<ManualRentForm
onSuccess={() => setIsRentDialogOpen(false)}
onCancel={() => setIsRentDialogOpen(false)}
/>
</DialogContent>
</Dialog>

<Dialog open={isCreateDialogOpen} onOpenChange={setIsCreateDialogOpen}>
<DialogTrigger asChild>
<Button>
<Plus className="mr-2 h-4 w-4" />
Novo Veículo
</Button>
</DialogTrigger>
<DialogContent className="max-w-2xl">
<DialogHeader>
<DialogTitle>Criar Novo Veículo</DialogTitle>
</DialogHeader>
<VehicleForm
onSuccess={() => {
setIsCreateDialogOpen(false)
void refetch()
}}
onCancel={() => setIsCreateDialogOpen(false)}
/>
</DialogContent>
</Dialog>
</div>
</div>

<Tabs defaultValue="vehicles" className="space-y-6">
Expand Down Expand Up @@ -209,7 +231,11 @@ export default function VehiclesAdminClient() {
</div>
<div className="flex justify-between">
<span className="text-muted-foreground">Filial:</span>
<span>{vehicle.filial ? `${vehicle.filial.name} (${vehicle.filial.code})` : "—"}</span>
{vehicle.filial ? (
<span>{`${vehicle.filial.name} (${vehicle.filial.code})`}</span>
) : (
<Badge variant="destructive">Sem filial</Badge>
)}
</div>
<div className="flex justify-between">
<span className="text-muted-foreground">Quilometragem:</span>
Expand Down
Loading
Loading