mirror of
https://github.com/OpenCut-app/OpenCut.git
synced 2026-07-13 21:52:53 +02:00
lots more icons to do but
This commit is contained in:
@@ -1,12 +1,9 @@
|
||||
import { OcGithubIcon } from "@opencut/ui/icons";
|
||||
import { ExternalLink } from "lucide-react";
|
||||
import type { Metadata } from "next";
|
||||
import Link from "next/link";
|
||||
import { GitHubContributeSection } from "@/components/gitHub-contribute-section";
|
||||
import { Avatar, AvatarFallback, AvatarImage } from "@/components/ui/avatar";
|
||||
import { Button } from "@/components/ui/button";
|
||||
import { Card, CardContent } from "@/components/ui/card";
|
||||
import { EXTERNAL_TOOLS, SOCIAL_LINKS } from "@/constants/site-constants";
|
||||
import { EXTERNAL_TOOLS } from "@/constants/site-constants";
|
||||
import { BasePage } from "../base-page";
|
||||
|
||||
export const metadata: Metadata = {
|
||||
@@ -87,7 +84,6 @@ export default async function ContributorsPage() {
|
||||
{otherContributors.length > 0 && (
|
||||
<AllContributorsSection contributors={otherContributors} />
|
||||
)}
|
||||
{contributors.length === 0 && <EmptyState />}
|
||||
<ExternalToolsSection />
|
||||
<GitHubContributeSection
|
||||
title="Join the community"
|
||||
@@ -210,36 +206,6 @@ function AllContributorsSection({
|
||||
);
|
||||
}
|
||||
|
||||
function EmptyState() {
|
||||
return (
|
||||
<div className="flex flex-col gap-8 py-20 text-center">
|
||||
<div className="flex flex-col gap-6">
|
||||
<div className="bg-muted/50 mx-auto flex size-20 items-center justify-center rounded-full">
|
||||
<OcGithubIcon className="text-muted-foreground size-8" />
|
||||
</div>
|
||||
<div className="flex flex-col gap-3">
|
||||
<h3 className="text-xl font-medium">No contributors found</h3>
|
||||
<p className="text-muted-foreground mx-auto max-w-md">
|
||||
Unable to load contributors at the moment. Check back later or view
|
||||
on GitHub.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
<Link
|
||||
href={`${SOCIAL_LINKS.github}/graphs/contributors`}
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
>
|
||||
<Button variant="outline" className="gap-2">
|
||||
<OcGithubIcon />
|
||||
View on GitHub
|
||||
<ExternalLink />
|
||||
</Button>
|
||||
</Link>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
function ExternalToolsSection() {
|
||||
return (
|
||||
<div className="flex flex-col gap-10">
|
||||
|
||||
@@ -1,16 +1,5 @@
|
||||
"use client";
|
||||
|
||||
import {
|
||||
ArrowDown01,
|
||||
Calendar,
|
||||
ChevronLeft,
|
||||
MoreHorizontal,
|
||||
Plus,
|
||||
Search,
|
||||
Trash2,
|
||||
Video,
|
||||
X,
|
||||
} from "lucide-react";
|
||||
import Image from "next/image";
|
||||
import Link from "next/link";
|
||||
import { useRouter } from "next/navigation";
|
||||
@@ -41,6 +30,18 @@ import {
|
||||
import { useEditor } from "@/hooks/use-editor";
|
||||
import type { TProjectMetadata } from "@/types/project";
|
||||
import { formatDate } from "@/utils/date";
|
||||
import { HugeiconsIcon } from "@hugeicons/react";
|
||||
import {
|
||||
ArrowHorizontalIcon,
|
||||
ArrowLeft01Icon,
|
||||
Calendar04Icon,
|
||||
Delete02Icon,
|
||||
MultiplicationSignIcon,
|
||||
PlusSignIcon,
|
||||
Search01Icon,
|
||||
SortingNineOneIcon,
|
||||
Video01Icon,
|
||||
} from "@hugeicons/core-free-icons";
|
||||
|
||||
export default function ProjectsPage() {
|
||||
const [isSelectionMode, setIsSelectionMode] = useState(false);
|
||||
@@ -160,7 +161,7 @@ export default function ProjectsPage() {
|
||||
href="/"
|
||||
className="hover:text-muted-foreground flex items-center gap-1 transition-colors"
|
||||
>
|
||||
<ChevronLeft className="size-5! shrink-0" />
|
||||
<HugeiconsIcon icon={ArrowLeft01Icon} className="size-5! shrink-0" />
|
||||
<span className="text-sm font-medium">Back</span>
|
||||
</Link>
|
||||
<div className="block md:hidden">
|
||||
@@ -171,7 +172,7 @@ export default function ProjectsPage() {
|
||||
size="sm"
|
||||
onClick={handleCancelSelection}
|
||||
>
|
||||
<X />
|
||||
<HugeiconsIcon icon={MultiplicationSignIcon} />
|
||||
Cancel
|
||||
</Button>
|
||||
{selectedProjects.size > 0 && (
|
||||
@@ -180,7 +181,7 @@ export default function ProjectsPage() {
|
||||
size="sm"
|
||||
onClick={() => setIsBulkDeleteDialogOpen(true)}
|
||||
>
|
||||
<Trash2 />
|
||||
<HugeiconsIcon icon={Delete02Icon} />
|
||||
Delete ({selectedProjects.size})
|
||||
</Button>
|
||||
)}
|
||||
@@ -210,7 +211,7 @@ export default function ProjectsPage() {
|
||||
{isSelectionMode ? (
|
||||
<div className="flex items-center gap-2">
|
||||
<Button variant="outline" onClick={handleCancelSelection}>
|
||||
<X />
|
||||
<HugeiconsIcon icon={MultiplicationSignIcon} />
|
||||
Cancel
|
||||
</Button>
|
||||
<Button
|
||||
@@ -218,7 +219,7 @@ export default function ProjectsPage() {
|
||||
disabled={selectedProjects.size === 0}
|
||||
onClick={() => setIsBulkDeleteDialogOpen(true)}
|
||||
>
|
||||
<Trash2 />
|
||||
<HugeiconsIcon icon={Delete02Icon} />
|
||||
Delete {selectedProjects.size} projects
|
||||
</Button>
|
||||
</div>
|
||||
@@ -257,9 +258,8 @@ export default function ProjectsPage() {
|
||||
variant="outline"
|
||||
className="size-9 items-center justify-center"
|
||||
>
|
||||
<ArrowDown01
|
||||
strokeWidth={1.5}
|
||||
className="!size-[1.05rem]"
|
||||
<HugeiconsIcon
|
||||
icon={SortingNineOneIcon}
|
||||
aria-hidden="true"
|
||||
/>
|
||||
</Button>
|
||||
@@ -430,7 +430,10 @@ function ProjectCard({
|
||||
/>
|
||||
) : (
|
||||
<div className="bg-muted/50 flex size-full items-center justify-center">
|
||||
<Video className="text-muted-foreground size-12 shrink-0" />
|
||||
<HugeiconsIcon
|
||||
icon={Video01Icon}
|
||||
className="text-muted-foreground size-12 shrink-0"
|
||||
/>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
@@ -458,7 +461,10 @@ function ProjectCard({
|
||||
}`}
|
||||
onClick={(event) => event.preventDefault()}
|
||||
>
|
||||
<MoreHorizontal aria-hidden="true" />
|
||||
<HugeiconsIcon
|
||||
icon={ArrowHorizontalIcon}
|
||||
aria-hidden="true"
|
||||
/>
|
||||
</Button>
|
||||
</DropdownMenuTrigger>
|
||||
<DropdownMenuContent
|
||||
@@ -506,7 +512,7 @@ function ProjectCard({
|
||||
|
||||
<div className="space-y-1">
|
||||
<div className="text-muted-foreground flex items-center gap-1.5 text-sm">
|
||||
<Calendar className="size-4!" />
|
||||
<HugeiconsIcon icon={Calendar04Icon} className="size-4" />
|
||||
<span>Created {formatDate({ date: project.createdAt })}</span>
|
||||
</div>
|
||||
</div>
|
||||
@@ -575,7 +581,7 @@ function ProjectsLoader() {
|
||||
function CreateButton({ onClick }: { onClick?: () => void }) {
|
||||
return (
|
||||
<Button className="flex" onClick={onClick}>
|
||||
<Plus />
|
||||
<HugeiconsIcon icon={PlusSignIcon} />
|
||||
<span className="text-sm font-medium">New project</span>
|
||||
</Button>
|
||||
);
|
||||
@@ -596,7 +602,10 @@ function EmptyState({
|
||||
<div className="flex flex-col items-center justify-center gap-6 py-16 text-center">
|
||||
<div className="flex flex-col items-center gap-2">
|
||||
<div className="bg-muted/30 flex size-16 items-center justify-center rounded-full">
|
||||
<Search className="text-muted-foreground size-8" />
|
||||
<HugeiconsIcon
|
||||
icon={Search01Icon}
|
||||
className="text-muted-foreground size-8"
|
||||
/>
|
||||
</div>
|
||||
<h3 className="text-lg font-medium">No results found</h3>
|
||||
<p className="text-muted-foreground max-w-md">
|
||||
@@ -614,7 +623,10 @@ function EmptyState({
|
||||
<div className="flex flex-col items-center justify-center gap-6 py-16 text-center">
|
||||
<div className="flex flex-col items-center gap-2">
|
||||
<div className="bg-muted/30 flex size-16 items-center justify-center rounded-full">
|
||||
<Video className="text-muted-foreground size-8" />
|
||||
<HugeiconsIcon
|
||||
icon={Video01Icon}
|
||||
className="text-muted-foreground size-8"
|
||||
/>
|
||||
</div>
|
||||
<h3 className="text-lg font-medium">No projects yet</h3>
|
||||
<p className="text-muted-foreground max-w-md">
|
||||
@@ -623,7 +635,7 @@ function EmptyState({
|
||||
</p>
|
||||
</div>
|
||||
<Button size="lg" className="gap-2" onClick={onCreateProject}>
|
||||
<Plus />
|
||||
<HugeiconsIcon icon={PlusSignIcon} />
|
||||
Create your first project
|
||||
</Button>
|
||||
</div>
|
||||
|
||||
@@ -1,17 +1,18 @@
|
||||
"use client";
|
||||
|
||||
import {
|
||||
ArrowDown,
|
||||
Clock3,
|
||||
Folder,
|
||||
LayoutGrid,
|
||||
List,
|
||||
MoreHorizontal,
|
||||
Plus,
|
||||
Search,
|
||||
} from "lucide-react";
|
||||
import Image from "next/image";
|
||||
import { useEffect, useMemo, useRef, useState } from "react";
|
||||
import { HugeiconsIcon } from "@hugeicons/react";
|
||||
import {
|
||||
ArrowHorizontalIcon,
|
||||
Clock03Icon,
|
||||
Folder03Icon,
|
||||
GridViewIcon,
|
||||
LeftToRightListDashIcon,
|
||||
PlusSignIcon,
|
||||
SearchIcon,
|
||||
SortingNineOneIcon,
|
||||
} from "@hugeicons/core-free-icons";
|
||||
|
||||
const projects = [
|
||||
{
|
||||
@@ -110,7 +111,7 @@ export default function ProjectsPage() {
|
||||
href="/projects"
|
||||
className="flex items-center gap-3 rounded-2xl bg-blue-50/50 px-4 py-3 text-sm font-medium text-[#00A3FF]"
|
||||
>
|
||||
<LayoutGrid className="size-5" />
|
||||
<HugeiconsIcon icon={GridViewIcon} className="size-5" />
|
||||
Projects
|
||||
</a>
|
||||
<div className="px-4 pt-6 pb-2">
|
||||
@@ -122,14 +123,20 @@ export default function ProjectsPage() {
|
||||
href="/projects"
|
||||
className="flex items-center gap-3 rounded-2xl px-4 py-3 text-sm font-medium text-slate-500 hover:bg-slate-50 hover:text-slate-900"
|
||||
>
|
||||
<Folder className="size-5 text-slate-400" />
|
||||
<HugeiconsIcon
|
||||
icon={Folder03Icon}
|
||||
className="size-5 text-slate-400"
|
||||
/>
|
||||
Marketing
|
||||
</a>
|
||||
<a
|
||||
href="/projects"
|
||||
className="flex items-center gap-3 rounded-2xl px-4 py-3 text-sm font-medium text-slate-500 hover:bg-slate-50 hover:text-slate-900"
|
||||
>
|
||||
<Folder className="size-5 text-slate-400" />
|
||||
<HugeiconsIcon
|
||||
icon={Folder03Icon}
|
||||
className="size-5 text-slate-400"
|
||||
/>
|
||||
Social media
|
||||
</a>
|
||||
</nav>
|
||||
@@ -143,7 +150,10 @@ export default function ProjectsPage() {
|
||||
|
||||
<div className="flex items-center gap-4">
|
||||
<div className="group relative">
|
||||
<Search className="absolute top-1/2 left-3.5 size-4 -translate-y-1/2 text-slate-400" />
|
||||
<HugeiconsIcon
|
||||
icon={SearchIcon}
|
||||
className="absolute top-1/2 left-3.5 size-4 -translate-y-1/2 text-slate-400"
|
||||
/>
|
||||
<input
|
||||
type="text"
|
||||
placeholder="Search..."
|
||||
@@ -157,18 +167,22 @@ export default function ProjectsPage() {
|
||||
className="rounded-full bg-slate-100 p-2 text-slate-900"
|
||||
aria-label="Grid view"
|
||||
>
|
||||
<LayoutGrid className="size-4" aria-hidden="true">
|
||||
<title>Grid view</title>
|
||||
</LayoutGrid>
|
||||
<HugeiconsIcon
|
||||
icon={GridViewIcon}
|
||||
className="size-4"
|
||||
aria-hidden="true"
|
||||
/>
|
||||
</button>
|
||||
<button
|
||||
type="button"
|
||||
className="rounded-full p-2 text-slate-400 hover:text-slate-600"
|
||||
aria-label="List view"
|
||||
>
|
||||
<List className="size-4" aria-hidden="true">
|
||||
<title>List view</title>
|
||||
</List>
|
||||
<HugeiconsIcon
|
||||
icon={LeftToRightListDashIcon}
|
||||
className="size-4"
|
||||
aria-hidden="true"
|
||||
/>
|
||||
</button>
|
||||
</div>
|
||||
|
||||
@@ -176,7 +190,7 @@ export default function ProjectsPage() {
|
||||
type="button"
|
||||
className="flex items-center gap-2 rounded-full bg-[#00A3FF] px-5 py-2.5 text-sm font-semibold text-white hover:bg-[#008BE0] active:scale-95"
|
||||
>
|
||||
<Plus className="size-4" />
|
||||
<HugeiconsIcon icon={PlusSignIcon} className="size-4" />
|
||||
New project
|
||||
</button>
|
||||
</div>
|
||||
@@ -210,7 +224,7 @@ export default function ProjectsPage() {
|
||||
className="inline-flex items-center gap-1.5 rounded-lg p-1 text-sm font-medium text-slate-500 hover:text-slate-900"
|
||||
>
|
||||
Name
|
||||
<ArrowDown className="size-3.5" />
|
||||
<HugeiconsIcon icon={SortingNineOneIcon} className="size-3.5" />
|
||||
</button>
|
||||
</div>
|
||||
|
||||
@@ -243,9 +257,11 @@ export default function ProjectsPage() {
|
||||
className="rounded-full bg-white/90 p-2 text-slate-600 backdrop-blur-sm hover:bg-white hover:text-[#00A3FF]"
|
||||
aria-label="Project menu"
|
||||
>
|
||||
<MoreHorizontal className="size-4" aria-hidden="true">
|
||||
<title>Project menu</title>
|
||||
</MoreHorizontal>
|
||||
<HugeiconsIcon
|
||||
icon={ArrowHorizontalIcon}
|
||||
className="size-4"
|
||||
aria-hidden="true"
|
||||
/>
|
||||
</button>
|
||||
</div>
|
||||
|
||||
@@ -268,7 +284,11 @@ export default function ProjectsPage() {
|
||||
{name}
|
||||
</h3>
|
||||
<div className="mt-2 flex items-center gap-2 text-slate-400">
|
||||
<Clock3 className="size-4" aria-hidden="true" />
|
||||
<HugeiconsIcon
|
||||
icon={Clock03Icon}
|
||||
className="size-4"
|
||||
aria-hidden="true"
|
||||
/>
|
||||
<p className="text-xs font-medium">{createdAtLabel}</p>
|
||||
</div>
|
||||
</div>
|
||||
@@ -281,42 +301,33 @@ export default function ProjectsPage() {
|
||||
</main>
|
||||
|
||||
<style jsx global>{`
|
||||
.project-card:hover .card-actions {
|
||||
.project-card:hover .card-actions
|
||||
opacity: 1;
|
||||
}
|
||||
.checkbox-wrapper:checked + div {
|
||||
.checkbox-wrapper:checked + div
|
||||
border-color: var(--brand-blue);
|
||||
background-color: #eff6ff;
|
||||
}
|
||||
.controls-row.has-selection .controls-select {
|
||||
.controls-row.has-selection .controls-select
|
||||
opacity: 1;
|
||||
}
|
||||
.project-select-wrapper {
|
||||
.project-select-wrapper
|
||||
opacity: 0;
|
||||
}
|
||||
.project-card:hover .project-select-wrapper {
|
||||
.project-card:hover .project-select-wrapper
|
||||
opacity: 1;
|
||||
}
|
||||
.project-card:has(.project-select:checked) .project-select-wrapper {
|
||||
.project-card:has(.project-select:checked) .project-select-wrapper
|
||||
opacity: 1;
|
||||
}
|
||||
.multi-select .project-menu {
|
||||
.multi-select .project-menu
|
||||
opacity: 0 !important;
|
||||
pointer-events: none;
|
||||
}
|
||||
.custom-checkbox {
|
||||
.custom-checkbox
|
||||
appearance: none;
|
||||
background-color: #fff;
|
||||
border: 2px solid #e2e8f0;
|
||||
border-radius: 8px;
|
||||
display: inline-grid;
|
||||
place-content: center;
|
||||
}
|
||||
.custom-checkbox:checked {
|
||||
.custom-checkbox:checked
|
||||
background-color: var(--brand-blue);
|
||||
border-color: var(--brand-blue);
|
||||
}
|
||||
.custom-checkbox:checked::after {
|
||||
.custom-checkbox:checked::after
|
||||
content: "";
|
||||
width: 10px;
|
||||
height: 10px;
|
||||
@@ -329,7 +340,6 @@ export default function ProjectsPage() {
|
||||
86% 10%,
|
||||
40% 70%
|
||||
);
|
||||
}
|
||||
`}</style>
|
||||
</div>
|
||||
);
|
||||
|
||||
@@ -1,10 +1,11 @@
|
||||
import { ExternalLink } from "lucide-react";
|
||||
import type { Metadata } from "next";
|
||||
import Image from "next/image";
|
||||
import Link from "next/link";
|
||||
import { BasePage } from "@/app/base-page";
|
||||
import { Card, CardContent } from "@/components/ui/card";
|
||||
import { SPONSORS, type Sponsor } from "@/constants/site-constants";
|
||||
import { HugeiconsIcon } from "@hugeicons/react";
|
||||
import { LinkSquare02Icon } from "@hugeicons/core-free-icons";
|
||||
|
||||
export const metadata: Metadata = {
|
||||
title: "Sponsors - OpenCut",
|
||||
@@ -25,9 +26,9 @@ export default function SponsorsPage() {
|
||||
<h1 className="text-5xl font-bold tracking-tight md:text-6xl">
|
||||
Sponsors
|
||||
</h1>
|
||||
<p className="text-muted-foreground mx-auto max-w-2xl text-xl leading-relaxed">
|
||||
Support OpenCut and help us build the future of free and open-source
|
||||
video editing.
|
||||
<p className="text-muted-foreground mx-auto max-w-2xl text-xl leading-relaxed text-pretty">
|
||||
Support OpenCut and help us build the future of privacy-first video
|
||||
editing.
|
||||
</p>
|
||||
</div>
|
||||
<SponsorsGrid />
|
||||
@@ -51,7 +52,7 @@ function SponsorCard({ sponsor }: { sponsor: Sponsor }) {
|
||||
href={sponsor.url}
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
className="size-full"
|
||||
className="size-full"
|
||||
>
|
||||
<Card className="h-full">
|
||||
<CardContent className="flex h-full flex-col justify-center gap-8 p-8">
|
||||
@@ -67,7 +68,10 @@ function SponsorCard({ sponsor }: { sponsor: Sponsor }) {
|
||||
<h3 className="text-xl font-semibold group-hover:underline">
|
||||
{sponsor.name}
|
||||
</h3>
|
||||
<ExternalLink className="text-muted-foreground size-4" />
|
||||
<HugeiconsIcon
|
||||
icon={LinkSquare02Icon}
|
||||
className="text-muted-foreground size-4"
|
||||
/>
|
||||
</div>
|
||||
<p className="text-muted-foreground">{sponsor.description}</p>
|
||||
</div>
|
||||
|
||||
Reference in New Issue
Block a user