laconic-deploy/packages/frontend/src/components/projects/ProjectCard/ProjectCard.tsx
icld 6f64513fc8 feat: Add documentation and context for frontend architecture
This commit introduces several key improvements to the frontend architecture:

- Created comprehensive documentation for TSDoc and TypeDoc usage
- Added WalletContext for managing wallet connection state
- Updated navigation and project components
- Introduced layout and routing strategy documentation
- Removed unused imports and commented code
- Enhanced project search and navigation components
2025-03-02 06:35:03 -08:00

129 lines
3.8 KiB
TypeScript

import { Avatar, AvatarFallback, AvatarImage } from '@/components/ui/avatar';
import { Card, CardContent, CardHeader } from '@/components/ui/card';
import { getInitials } from '@/utils/geInitials';
import { Project } from 'gql-client';
import { AlertTriangle } from 'lucide-react';
import { ComponentPropsWithoutRef, useCallback } from 'react';
import { useNavigate } from 'react-router-dom';
import { ProjectCardActions } from './ProjectCardActions';
import { ProjectDeploymentInfo } from './ProjectDeploymentInfo';
import { ProjectStatusDot } from './ProjectStatusDot';
/**
* Status types for project deployment status
*/
export type ProjectStatus = 'success' | 'in-progress' | 'failure' | 'pending';
/**
* Props for the ProjectCard component
*
* @property {Project} project - The project data to display
* @property {ProjectStatus} [status='failure'] - The current deployment status of the project
*/
interface ProjectCardProps extends ComponentPropsWithoutRef<'div'> {
project: Project;
status?: ProjectStatus;
}
/**
* ProjectCard component
*
* Displays a card with project information including:
* - Project name and icon
* - Domain URL (if available)
* - Deployment status
* - Latest commit information
* - Timestamp and branch information
* - Actions menu for project settings and deletion
*
* The card is clickable and navigates to the project details page.
*
* @example
* ```tsx
* <ProjectCard
* project={projectData}
* status="success"
* />
* ```
*/
export const ProjectCard = ({
className,
project,
status = 'failure',
...props
}: ProjectCardProps) => {
const hasError = status === 'failure';
const navigate = useNavigate();
/**
* Handles click on the card to navigate to project details
*/
const handleClick = useCallback(() => {
navigate(`projects/${project.id}`);
}, [project.id, navigate]);
/**
* Handles click on the settings menu item
* Prevents event propagation to avoid triggering card click
*/
const handleSettingsClick = useCallback(
(e: React.MouseEvent) => {
e.preventDefault();
e.stopPropagation();
navigate(`projects/${project.id}/settings`);
},
[project.id, navigate],
);
/**
* Handles click on the delete menu item
* Prevents event propagation to avoid triggering card click
*/
const handleDeleteClick = useCallback(
(e: React.MouseEvent) => {
e.preventDefault();
e.stopPropagation();
navigate(`projects/${project.id}/settings`);
},
[project.id, navigate],
);
return (
<Card className="w-full" onClick={handleClick} {...props}>
<CardHeader className="flex flex-row items-start justify-between space-y-0 pb-2">
<div className="flex gap-2.5">
<Avatar className="h-10 w-10">
<AvatarImage src={project.icon} alt={project.name} />
<AvatarFallback>{getInitials(project.name)}</AvatarFallback>
</Avatar>
<div className="flex flex-col gap-1.5">
<p className="text-sm font-semibold text-foreground leading-none">
{project.name}
</p>
<p className="text-sm text-muted-foreground leading-5">
{project.deployments[0]?.applicationDeploymentRecordData?.url ??
'No domain'}
</p>
</div>
</div>
<div className="flex items-center gap-2">
{hasError && <AlertTriangle className="text-destructive h-4 w-4" />}
<ProjectCardActions
onSettingsClick={handleSettingsClick}
onDeleteClick={handleDeleteClick}
/>
</div>
</CardHeader>
<CardContent className="flex flex-col gap-3 pt-2">
<div className="flex items-center gap-2">
<ProjectStatusDot status={status} />
<ProjectDeploymentInfo project={project} />
</div>
</CardContent>
</Card>
);
};