Add project management support and integrate customer-project functionality
This commit is contained in:
102
internal_frontend/app/projects/[id]/page.tsx
Normal file
102
internal_frontend/app/projects/[id]/page.tsx
Normal file
@@ -0,0 +1,102 @@
|
||||
"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>
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user