129 lines
4.4 KiB
TypeScript
129 lines
4.4 KiB
TypeScript
"use client"
|
|
|
|
import { useState } from "react"
|
|
import { useMutation } from "@tanstack/react-query"
|
|
import { useRouter } from "next/navigation"
|
|
import { Plus, Trash2, Lightbulb } from "lucide-react"
|
|
import { toast } from "sonner"
|
|
|
|
import { useAuthApi } from "@/shared/useApi"
|
|
import { confirm } from "@/shared/components/confirm-dialog"
|
|
import { Button } from "@/shared/components/ui/button"
|
|
import {
|
|
Card,
|
|
CardContent,
|
|
CardHeader,
|
|
CardTitle,
|
|
} from "@/shared/components/ui/card"
|
|
import { Textarea } from "@/shared/components/ui/textarea"
|
|
|
|
type ShopRecommendation = {
|
|
id: number
|
|
recommendation: string
|
|
created_at?: string
|
|
}
|
|
|
|
type Props = {
|
|
jobCardId: string
|
|
recommendations: ShopRecommendation[]
|
|
}
|
|
|
|
export function JobCardRecommendationsList({ jobCardId, recommendations }: Props) {
|
|
const api = useAuthApi()
|
|
const router = useRouter()
|
|
const [newRecommendation, setNewRecommendation] = useState("")
|
|
|
|
const addMutation = useMutation({
|
|
mutationFn: (recommendation: string) =>
|
|
api.jobCards.addShopRecommendation(jobCardId, { recommendation }),
|
|
onSuccess: () => {
|
|
toast.success("Shop recommendation added")
|
|
setNewRecommendation("")
|
|
router.refresh()
|
|
},
|
|
onError: () => {
|
|
toast.error("Failed to add shop recommendation")
|
|
},
|
|
})
|
|
|
|
const deleteMutation = useMutation({
|
|
mutationFn: (recommendationId: number) =>
|
|
api.jobCards.deleteShopRecommendation(jobCardId, recommendationId),
|
|
onSuccess: () => {
|
|
toast.success("Shop recommendation deleted")
|
|
router.refresh()
|
|
},
|
|
onError: () => {
|
|
toast.error("Failed to delete shop recommendation")
|
|
},
|
|
})
|
|
|
|
const handleAdd = () => {
|
|
const trimmed = newRecommendation.trim()
|
|
if (!trimmed) return
|
|
addMutation.mutate(trimmed)
|
|
}
|
|
|
|
const handleDelete = async (recommendation: ShopRecommendation) => {
|
|
const confirmed = await confirm({
|
|
title: "Delete Shop Recommendation",
|
|
description: "Are you sure you want to delete this recommendation?",
|
|
confirmLabel: "Delete",
|
|
variant: "destructive",
|
|
})
|
|
if (confirmed) {
|
|
deleteMutation.mutate(recommendation.id)
|
|
}
|
|
}
|
|
|
|
return (
|
|
<Card>
|
|
<CardHeader>
|
|
<CardTitle className="flex items-center gap-2">
|
|
<Lightbulb className="size-4" />
|
|
Shop Recommendations
|
|
</CardTitle>
|
|
</CardHeader>
|
|
<CardContent className="flex flex-col gap-4">
|
|
{recommendations.length === 0 && (
|
|
<p className="text-sm text-muted-foreground">No shop recommendations yet.</p>
|
|
)}
|
|
{recommendations.map((rec) => (
|
|
<div
|
|
key={rec.id}
|
|
className="flex items-start justify-between gap-3 rounded-lg border px-4 py-3"
|
|
>
|
|
<p className="text-sm whitespace-pre-wrap">{rec.recommendation}</p>
|
|
<Button
|
|
variant="ghost"
|
|
size="icon"
|
|
className="shrink-0 text-muted-foreground hover:text-destructive"
|
|
onClick={() => handleDelete(rec)}
|
|
disabled={deleteMutation.isPending}
|
|
>
|
|
<Trash2 className="size-4" />
|
|
</Button>
|
|
</div>
|
|
))}
|
|
<div className="flex flex-col gap-2">
|
|
<Textarea
|
|
placeholder="Add a shop recommendation..."
|
|
value={newRecommendation}
|
|
onChange={(e) => setNewRecommendation(e.target.value)}
|
|
rows={2}
|
|
/>
|
|
<Button
|
|
size="sm"
|
|
className="self-end"
|
|
onClick={handleAdd}
|
|
disabled={addMutation.isPending || !newRecommendation.trim()}
|
|
>
|
|
<Plus className="size-4" />
|
|
{addMutation.isPending ? "Adding..." : "Add Recommendation"}
|
|
</Button>
|
|
</div>
|
|
</CardContent>
|
|
</Card>
|
|
)
|
|
}
|