102 lines
3.1 KiB
TypeScript
102 lines
3.1 KiB
TypeScript
"use client";
|
|
|
|
import React, {useEffect, useState} from "react";
|
|
import {useParams, useRouter} from "next/navigation";
|
|
import {ChevronLeft} from "lucide-react";
|
|
import {Button} from "@/components/ui/button";
|
|
import {Skeleton} from "@/components/ui/skeleton";
|
|
import {CustomerProject} from "@/services/projects/entities/customer-project";
|
|
|
|
export default function ProjectDetailPage() {
|
|
const router = useRouter();
|
|
const {id} = useParams<{ id: string }>();
|
|
const [project, setProject] = useState<CustomerProject | null>(null);
|
|
const [loading, setLoading] = useState(true);
|
|
const [error, setError] = useState<string | null>(null);
|
|
|
|
useEffect(() => {
|
|
if (!id) {
|
|
setError("No project ID provided");
|
|
setLoading(false);
|
|
return;
|
|
}
|
|
|
|
let isMounted = true;
|
|
setLoading(true);
|
|
setError(null);
|
|
|
|
fetch(`/api/projects/${id}`)
|
|
.then(async (response) => {
|
|
if (!isMounted) return;
|
|
|
|
if (response.status === 404) {
|
|
setError("Project not found");
|
|
setProject(null);
|
|
return;
|
|
}
|
|
|
|
if (!response.ok) {
|
|
throw new Error("Failed to fetch project data");
|
|
}
|
|
|
|
const result = await response.json();
|
|
setProject(result);
|
|
})
|
|
.catch((err) => {
|
|
if (!isMounted) return;
|
|
console.error("Error fetching project:", err);
|
|
setProject(null);
|
|
setError("Error loading project data");
|
|
})
|
|
.finally(() => {
|
|
if (isMounted) {
|
|
setLoading(false);
|
|
}
|
|
});
|
|
|
|
return () => {
|
|
isMounted = false;
|
|
};
|
|
}, [id]);
|
|
|
|
if (loading) {
|
|
return (
|
|
<div className="p-6">
|
|
<Skeleton className="w-full h-8 mb-4"/>
|
|
<Skeleton className="w-full h-6 mb-2"/>
|
|
<Skeleton className="w-3/4 h-6"/>
|
|
</div>
|
|
);
|
|
}
|
|
|
|
if (error) {
|
|
return (
|
|
<div className="p-6 text-red-500">
|
|
<p>{error}</p>
|
|
<Button variant="ghost" onClick={() => router.back()}>
|
|
<ChevronLeft className="w-4 h-4 mr-1"/>
|
|
Go back
|
|
</Button>
|
|
</div>
|
|
);
|
|
}
|
|
|
|
return (
|
|
<div className="h-full w-full p-6 space-y-4 text-sm">
|
|
<div className="flex justify-between items-start">
|
|
<Button
|
|
variant="ghost"
|
|
onClick={() => router.back()}
|
|
aria-label="Go back"
|
|
>
|
|
<ChevronLeft className="w-4 h-4 mr-1"/>
|
|
Zurück
|
|
</Button>
|
|
</div>
|
|
<div className="container mx-auto p-4">
|
|
<h1 className="text-2xl font-bold mb-4">{project?.name}</h1>
|
|
<p className="text-lg">{project?.description}</p>
|
|
</div>
|
|
</div>
|
|
);
|
|
} |