import { BreadcrumbSidebar } from "@/components/shared/breadcrumb-sidebar"; import { DateTooltip } from "@/components/shared/date-tooltip"; import { StatusTooltip } from "@/components/shared/status-tooltip"; import { AlertDialog, AlertDialogAction, AlertDialogCancel, AlertDialogContent, AlertDialogDescription, AlertDialogFooter, AlertDialogHeader, AlertDialogTitle, AlertDialogTrigger, } from "@/components/ui/alert-dialog"; import { Button } from "@/components/ui/button"; import { Card, CardContent, CardDescription, CardFooter, CardHeader, CardTitle, } from "@/components/ui/card"; import { DropdownMenu, DropdownMenuContent, DropdownMenuGroup, DropdownMenuItem, DropdownMenuLabel, DropdownMenuSeparator, DropdownMenuTrigger, } from "@/components/ui/dropdown-menu"; import { Input } from "@/components/ui/input"; import { api } from "@/utils/api"; import { AlertTriangle, BookIcon, ExternalLinkIcon, FolderInput, Loader2, MoreHorizontalIcon, Search, TrashIcon, } from "lucide-react"; import Link from "next/link"; import { useMemo, useState } from "react"; import { toast } from "sonner"; import { HandleProject } from "./handle-project"; import { ProjectEnvironment } from "./project-environment"; export const ShowProjects = () => { const utils = api.useUtils(); const { data, isLoading } = api.project.all.useQuery(); const { data: auth } = api.user.get.useQuery(); const { mutateAsync } = api.project.remove.useMutation(); const [searchQuery, setSearchQuery] = useState(""); const filteredProjects = useMemo(() => { if (!data) return []; return data.filter( (project) => project.name.toLowerCase().includes(searchQuery.toLowerCase()) || project.description?.toLowerCase().includes(searchQuery.toLowerCase()), ); }, [data, searchQuery]); return ( <>
Projects Create and manage your projects {(auth?.role === "owner" || auth?.canCreateProjects) && (
)}
{isLoading ? (
Loading...
) : ( <>
setSearchQuery(e.target.value)} className="pr-10" />
{filteredProjects?.length === 0 && (
No projects found
)}
{filteredProjects?.map((project) => { const emptyServices = project?.mariadb.length === 0 && project?.mongo.length === 0 && project?.mysql.length === 0 && project?.postgres.length === 0 && project?.redis.length === 0 && project?.applications.length === 0 && project?.compose.length === 0; const totalServices = project?.mariadb.length + project?.mongo.length + project?.mysql.length + project?.postgres.length + project?.redis.length + project?.applications.length + project?.compose.length; return (
{project.applications.length > 0 || project.compose.length > 0 ? ( e.stopPropagation()} > {project.applications.length > 0 && ( Applications {project.applications.map((app) => (
{app.name} {app.domains.map((domain) => ( {domain.host} ))}
))}
)} {project.compose.length > 0 && ( Compose {project.compose.map((comp) => (
{comp.name} {comp.domains.map((domain) => ( {domain.host} ))}
))}
)}
) : null}
{project.name}
{project.description}
e.stopPropagation()} > Actions
e.stopPropagation()} >
e.stopPropagation()} >
e.stopPropagation()} > {(auth?.role === "owner" || auth?.canDeleteProjects) && ( e.preventDefault() } > Delete Are you sure to delete this project? {!emptyServices ? (
You have active services, please delete them first
) : ( This action cannot be undone )}
Cancel { await mutateAsync({ projectId: project.projectId, }) .then(() => { toast.success( "Project deleted successfully", ); }) .catch(() => { toast.error( "Error deleting this project", ); }) .finally(() => { utils.project.all.invalidate(); }); }} > Delete
)}
Created {totalServices}{" "} {totalServices === 1 ? "service" : "services"}
); })}
)}
); };