forked from cerc-io/snowballtools-base
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
129 lines
3.8 KiB
TypeScript
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>
|
|
);
|
|
};
|