chore: first commit
This commit is contained in:
@@ -0,0 +1,142 @@
|
||||
"use client"
|
||||
|
||||
import type { IProjectCardProps } from "./ProjectCard.d"
|
||||
import type { JSX } from "react"
|
||||
|
||||
import { Image as ImageIcon, MoreHorizontal } from "lucide-react"
|
||||
import { FunctionComponent } from "react"
|
||||
|
||||
import cs from "classnames"
|
||||
import moment from "moment"
|
||||
|
||||
import { Card } from "@shared/ui/Card"
|
||||
import { CircularProgress } from "@shared/ui/CircularProgress"
|
||||
import {
|
||||
Dropdown,
|
||||
DropdownContent,
|
||||
DropdownItem,
|
||||
DropdownTrigger,
|
||||
} from "@shared/ui/Dropdown"
|
||||
|
||||
import styles from "./ProjectCard.module.scss"
|
||||
|
||||
export const ProjectCard: FunctionComponent<IProjectCardProps> = ({
|
||||
project,
|
||||
className,
|
||||
progress = 0,
|
||||
currentAction,
|
||||
imageUrl,
|
||||
onClick,
|
||||
}): JSX.Element => {
|
||||
const { name, updated_at, status } = project
|
||||
|
||||
const temporaryStatuses = new Set(["PROCESSING", "RENDERING", "UPLOADING"])
|
||||
const isCompleted = status === "DONE"
|
||||
const isProcessing = temporaryStatuses.has(status)
|
||||
const isDraft = status === "DRAFT"
|
||||
const isFailed = status === "FAILED"
|
||||
|
||||
const shouldShowProgress = isProcessing
|
||||
|
||||
// Helper to determine status color/class
|
||||
const getStatusClass = () => {
|
||||
if (isCompleted) return styles.statusGenerated
|
||||
if (isProcessing) return styles.statusProcessing
|
||||
if (isDraft) return styles.statusDraft
|
||||
if (isFailed) return styles.statusFailed
|
||||
return styles.statusDraft
|
||||
}
|
||||
|
||||
const getStatusLabel = () => {
|
||||
if (isCompleted) return "Завершено"
|
||||
if (isProcessing) return "В процессе" // Or more specific state
|
||||
if (isDraft) return "Черновик"
|
||||
if (isFailed) return "Ошибка"
|
||||
return status
|
||||
}
|
||||
|
||||
const displayAction = currentAction || (isProcessing ? "В процессе" : "")
|
||||
|
||||
return (
|
||||
<Card className={cs(styles.root, className)} onClick={onClick}>
|
||||
<div className={styles.hero}>
|
||||
{imageUrl ? (
|
||||
<img src={imageUrl} alt={name} loading="lazy" />
|
||||
) : (
|
||||
<div className={styles.placeholder}>
|
||||
<ImageIcon />
|
||||
</div>
|
||||
)}
|
||||
|
||||
<div className={styles.statusBadge}>
|
||||
<div className={cs(styles.status, getStatusClass())}>
|
||||
<span className={styles.statusDot} />
|
||||
{getStatusLabel()}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{shouldShowProgress && (
|
||||
<div className={styles.progressOverlay}>
|
||||
<div className={styles.progressCircle}>
|
||||
<CircularProgress
|
||||
percentage={Math.min(100, Math.max(0, progress))}
|
||||
color="var(--purple-500)"
|
||||
bgClassName={styles.progressBg}
|
||||
valueClassName={styles.progressValue}
|
||||
/>
|
||||
<span className={styles.percentage}>{Math.round(progress)}%</span>
|
||||
</div>
|
||||
{displayAction && (
|
||||
<span className={styles.actionName} title={displayAction}>
|
||||
{displayAction}
|
||||
</span>
|
||||
)}
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
|
||||
<div className={styles.content}>
|
||||
<div className={styles.info}>
|
||||
<div className={styles.infoHeader}>
|
||||
<h3 className={styles.title} title={name}>
|
||||
{name}
|
||||
</h3>
|
||||
<div
|
||||
className={styles.menuTrigger}
|
||||
onClick={(e) => e.stopPropagation()}
|
||||
>
|
||||
<Dropdown>
|
||||
<DropdownTrigger asChild>
|
||||
<button type="button" aria-label="Project actions">
|
||||
<MoreHorizontal size={16} />
|
||||
</button>
|
||||
</DropdownTrigger>
|
||||
<DropdownContent align="end">
|
||||
<DropdownItem
|
||||
onSelect={() => console.log("Edit", project.id)}
|
||||
>
|
||||
Изменить
|
||||
</DropdownItem>
|
||||
<DropdownItem
|
||||
onSelect={() => console.log("Rename", project.id)}
|
||||
>
|
||||
Переименовать
|
||||
</DropdownItem>
|
||||
<DropdownItem
|
||||
className="text-red-500"
|
||||
onSelect={() => console.log("Delete", project.id)}
|
||||
>
|
||||
Удалить
|
||||
</DropdownItem>
|
||||
</DropdownContent>
|
||||
</Dropdown>
|
||||
</div>
|
||||
</div>
|
||||
<span className={styles.date}>
|
||||
Создано {moment(updated_at).fromNow()}
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</Card>
|
||||
)
|
||||
}
|
||||
Reference in New Issue
Block a user