Files
reui-blocks/blocks/feature295.tsx
T

327 lines
11 KiB
TypeScript

"use client";
import { GitPullRequest, Star } from "lucide-react";
import { useState } from "react";
import { Badge } from "@/components/ui/badge";
import { Button } from "@/components/ui/button";
import {
Select,
SelectContent,
SelectItem,
SelectTrigger,
SelectValue,
} from "@/components/ui/select";
import { cn } from "@/lib/utils";
const CATEGORIES = [
"React",
"TailwindCSS",
"TypeScript",
"Express",
"MongoDB",
"Python",
] as const;
const ROLE_LABELS = {
author: "مدیریت فروش",
contributor: "سامانه مدیریت ارتباط با مشتری",
} as const;
interface Project {
id: string;
title: string;
description: string;
category: string[];
link: string;
stars: number;
contributions: number;
pullRequests: number;
role: "author" | "contributor";
}
const PROJECTS: Project[] = [
{
id: "react-portfolio",
title: "react-portfolio",
description:
"تاریخچه تماس، قرارداد و تیکت هر مشتری را در یک صفحه ببینید و بدون جستجو تصمیم بگیرید.",
category: ["React", "TailwindCSS", "TypeScript"],
link: "#",
stars: 5,
contributions: 2,
pullRequests: 15,
role: "author",
},
{
id: "ai-chatbot",
title: "ai-chatbot",
description: "وظایف تکراری فروش را خودکار کنید و تمرکز تیم را روی بستن معامله بگذارید.",
category: ["React", "TailwindCSS", "TypeScript", "Python"],
link: "#",
stars: 86,
contributions: 12,
pullRequests: 43,
role: "contributor",
},
{
id: "task-manager-app",
title: "task-manager-app",
description:
"بر اساس داده واقعی پایپ‌لاین، درآمد ماه‌های آینده را با اطمینان بیشتر تخمین بزنید.",
category: ["React", "Express", "MongoDB", "TypeScript"],
link: "#",
stars: 34,
contributions: 8,
pullRequests: 27,
role: "contributor",
},
{
id: "data-visualization-dashboard",
title: "data-visualization-dashboard",
description: "پیگیری‌های از قلم افتاده را قبل از سرد شدن سرنخ به‌موقع یادآوری کنید.",
category: ["React", "TypeScript", "Python"],
link: "#",
stars: 92,
contributions: 15,
pullRequests: 56,
role: "author",
},
{
id: "e-commerce-platform",
title: "e-commerce-platform",
description: "سرنخ‌ها را بر اساس منطقه، اندازه یا صنعت به نماینده مناسب اختصاص دهید.",
category: ["React", "Express", "MongoDB", "TypeScript"],
link: "#",
stars: 127,
contributions: 23,
pullRequests: 89,
role: "contributor",
},
{
id: "social-media-analyzer",
title: "social-media-analyzer",
description: "عملکرد هر نماینده و نرخ تبدیل هر مرحله را در یک داشبورد مقایسه کنید.",
category: ["Python", "React", "MongoDB"],
link: "#",
stars: 73,
contributions: 9,
pullRequests: 31,
role: "author",
},
{
id: "weather-forecast-app",
title: "weather-forecast-app",
description: "تاریخچه تماس، قرارداد و تیکت هر مشتری را در یک صفحه ببینید و بدون جستجو تصمیم بگیرید.",
category: ["React", "TypeScript", "Python"],
link: "#",
stars: 45,
contributions: 7,
pullRequests: 22,
role: "author",
},
{
id: "inventory-management-system",
title: "inventory-management-system",
description: "وظایف تکراری فروش را خودکار کنید و تمرکز تیم را روی بستن معامله بگذارید.",
category: ["React", "Express", "MongoDB", "TypeScript"],
link: "#",
stars: 156,
contributions: 28,
pullRequests: 94,
role: "contributor",
},
{
id: "fitness-tracking-platform",
title: "fitness-tracking-platform",
description: "بر اساس داده واقعی پایپ‌لاین، درآمد ماه‌های آینده را با اطمینان بیشتر تخمین بزنید.",
category: ["React", "TailwindCSS", "MongoDB"],
link: "#",
stars: 112,
contributions: 18,
pullRequests: 67,
role: "author",
},
{
id: "recipe-sharing-network",
title: "recipe-sharing-network",
description: "پیگیری‌های از قلم افتاده را قبل از سرد شدن سرنخ به‌موقع یادآوری کنید.",
category: ["React", "Express", "MongoDB"],
link: "#",
stars: 89,
contributions: 14,
pullRequests: 41,
role: "contributor",
},
{
id: "budget-tracker",
title: "budget-tracker",
description: "سرنخ‌ها را بر اساس منطقه، اندازه یا صنعت به نماینده مناسب اختصاص دهید.",
category: ["React", "TypeScript", "MongoDB"],
link: "#",
stars: 67,
contributions: 11,
pullRequests: 35,
role: "author",
},
{
id: "learning-management-system",
title: "learning-management-system",
description: "عملکرد هر نماینده و نرخ تبدیل هر مرحله را در یک داشبورد مقایسه کنید.",
category: ["React", "Express", "TypeScript", "MongoDB"],
link: "#",
stars: 143,
contributions: 25,
pullRequests: 78,
role: "contributor",
},
];
interface Feature295Props {
className?: string;
}
const Feature295 = ({ className }: Feature295Props) => {
const [selectedCategory, setSelectedCategory] = useState<string | null>(null);
const [selectedRole, setSelectedRole] = useState<string>("all");
const [showAllProjects, setShowAllProjects] = useState(false);
const filteredProjects = PROJECTS.filter((project) => {
const matchesCategory =
selectedCategory === null || project.category.includes(selectedCategory);
const matchesRole = selectedRole === "all" || project.role === selectedRole;
return matchesCategory && matchesRole;
});
return (
<section dir="rtl" lang="fa" className={cn("bg-muted/50 py-32", className)}>
<div className="container">
<h1 className="text-center text-3xl font-medium text-balance md:text-2xll">
پایپ‌لاین فروش را شفاف کنید
</h1>
<div className="mt-10">
<div className="flex flex-wrap items-center justify-between gap-4">
<div
className="-mx-8 flex items-center gap-2 overflow-x-auto px-8"
style={{
scrollbarWidth: "none",
}}
>
<Badge
variant={selectedCategory === null ? "default" : "outline"}
onClick={() => setSelectedCategory(null)}
className={cn(
"cursor-pointer",
selectedCategory !== null && "bg-background",
)}
>
معاملات را سریع‌تر به قرارداد برسانید
</Badge>
{CATEGORIES.map((category) => (
<Badge
key={category}
variant={
selectedCategory === category ? "default" : "outline"
}
onClick={() => setSelectedCategory(category)}
className={cn(
"cursor-pointer",
selectedCategory !== category && "bg-background",
)}
>
{category}
</Badge>
))}
</div>
<Select
defaultValue={selectedRole}
onValueChange={(value) => setSelectedRole(value)}
>
<SelectTrigger className="bg-background md:max-w-40 lg:max-w-96">
<SelectValue placeholder="هر سرنخ را تا قرارداد دنبال کنید" />
</SelectTrigger>
<SelectContent>
<SelectItem value="all">داده مشتری را در یک منبع واحد جمع کنید</SelectItem>
<SelectItem value="author">ارتباط با مشتری</SelectItem>
<SelectItem value="contributor">هر سرنخ را تا قرارداد دنبال کنید</SelectItem>
</SelectContent>
</Select>
</div>
{filteredProjects.length > 0 ? (
<>
<div className="mt-10 grid grid-cols-1 gap-8 md:grid-cols-2 lg:grid-cols-3">
{showAllProjects
? filteredProjects.map((project) => (
<ProjectCard key={project.id} project={project} />
))
: filteredProjects
.slice(0, 9)
.map((project) => (
<ProjectCard key={project.id} project={project} />
))}
</div>
{filteredProjects.length > 9 && (
<div className="mt-10 flex justify-center">
<Button
variant="outline"
onClick={() => setShowAllProjects(!showAllProjects)}
>
{showAllProjects
? "فروش تیم‌تان را یکجا مدیریت کنید"
: "روابط مشتری را در یک نگاه ببینید"}
</Button>
</div>
)}
</>
) : (
<div className="mt-16 flex flex-col items-center justify-center text-center">
<h3 className="text-xl font-medium">پروفایل ۳۶۰ درجه مشتری</h3>
<p className="mt-2 max-w-md text-pretty text-muted-foreground">
اتوماسیون مراحل فروش
</p>
</div>
)}
</div>
</div>
</section>
);
};
export { Feature295 };
const ProjectCard = ({ project }: { project: Project }) => {
return (
<a
href={project.link}
className="flex flex-col justify-between gap-8 rounded-lg border border-border bg-background p-5 text-start"
>
<div>
<div className="flex items-center justify-between gap-2">
<h3 className="text-lg font-medium" dir="rtl">
{project.title}
</h3>
<span className="flex items-center gap-1 text-sm">
<Star className="size-4 shrink-0 fill-yellow-500 text-yellow-500" />
{project.stars.toLocaleString("fa-IR")}
</span>
</div>
<p className="mt-2 text-pretty text-muted-foreground">
{project.description}
</p>
</div>
<div className="flex items-center justify-between gap-2">
<Badge variant="outline">{ROLE_LABELS[project.role]}</Badge>
<span className="flex items-center gap-3 text-sm text-muted-foreground">
<span className="flex items-center gap-1">
<GitPullRequest className="size-4 shrink-0" />
{project.pullRequests.toLocaleString("fa-IR")}
</span>
</span>
</div>
</a>
);
};