Files
audio-ui/components/dialogs/ProjectsDialog.tsx
Sebastian Krüger 1b30931615 style: add custom-scrollbar styling to all dialog scrollable areas
Added custom-scrollbar class to scrollable elements in:
- EffectBrowser dialog content area
- ProjectsDialog projects list
- CommandPalette results list
- Modal content area
- TrackList automation parameter label containers

This ensures consistent scrollbar styling across all dialogs and UI elements.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-20 12:37:16 +01:00

163 lines
6.1 KiB
TypeScript

'use client';
import * as React from 'react';
import { X, Plus, Trash2, Copy, FolderOpen, Download, Upload } from 'lucide-react';
import { Button } from '@/components/ui/Button';
import type { ProjectMetadata } from '@/lib/storage/db';
import { formatDuration } from '@/lib/audio/decoder';
export interface ProjectsDialogProps {
open: boolean;
onClose: () => void;
projects: ProjectMetadata[];
onNewProject: () => void;
onLoadProject: (projectId: string) => void;
onDeleteProject: (projectId: string) => void;
onDuplicateProject: (projectId: string) => void;
onExportProject: (projectId: string) => void;
onImportProject: () => void;
}
export function ProjectsDialog({
open,
onClose,
projects,
onNewProject,
onLoadProject,
onDeleteProject,
onDuplicateProject,
onExportProject,
onImportProject,
}: ProjectsDialogProps) {
if (!open) return null;
const formatDate = (timestamp: number) => {
return new Date(timestamp).toLocaleString(undefined, {
year: 'numeric',
month: 'short',
day: 'numeric',
hour: '2-digit',
minute: '2-digit',
});
};
return (
<div className="fixed inset-0 z-50 flex items-center justify-center bg-black/50">
<div className="bg-card border border-border rounded-lg shadow-xl w-full max-w-3xl max-h-[80vh] flex flex-col">
{/* Header */}
<div className="flex items-center justify-between p-6 border-b border-border">
<h2 className="text-lg font-semibold text-foreground">Projects</h2>
<div className="flex items-center gap-2">
<Button
onClick={onImportProject}
variant="outline"
size="sm"
className="gap-2"
>
<Upload className="h-4 w-4" />
Import
</Button>
<Button
onClick={onNewProject}
variant="default"
size="sm"
className="gap-2"
>
<Plus className="h-4 w-4" />
New Project
</Button>
<button
onClick={onClose}
className="text-muted-foreground hover:text-foreground transition-colors"
>
<X className="h-5 w-5" />
</button>
</div>
</div>
{/* Projects List */}
<div className="flex-1 overflow-y-auto custom-scrollbar p-6">
{projects.length === 0 ? (
<div className="flex flex-col items-center justify-center py-12 text-center">
<FolderOpen className="h-16 w-16 text-muted-foreground mb-4" />
<h3 className="text-lg font-medium text-foreground mb-2">
No projects yet
</h3>
<p className="text-sm text-muted-foreground mb-4">
Create your first project to get started
</p>
<Button onClick={onNewProject} variant="default">
<Plus className="h-4 w-4 mr-2" />
Create Project
</Button>
</div>
) : (
<div className="grid gap-4">
{projects.map((project) => (
<div
key={project.id}
className="border border-border rounded-lg p-4 hover:bg-accent/50 transition-colors"
>
<div className="flex items-start justify-between">
<div className="flex-1">
<h3 className="font-medium text-foreground mb-1">
{project.name}
</h3>
{project.description && (
<p className="text-sm text-muted-foreground mb-2">
{project.description}
</p>
)}
<div className="flex flex-wrap gap-4 text-xs text-muted-foreground">
<span>{project.trackCount} tracks</span>
<span>{formatDuration(project.duration)}</span>
<span>{project.sampleRate / 1000}kHz</span>
<span>Updated {formatDate(project.updatedAt)}</span>
</div>
</div>
<div className="flex items-center gap-2 ml-4">
<button
onClick={() => onLoadProject(project.id)}
className="px-3 py-1.5 text-sm font-medium text-primary hover:bg-primary/10 rounded transition-colors"
title="Open project"
>
Open
</button>
<button
onClick={() => onExportProject(project.id)}
className="p-1.5 text-muted-foreground hover:text-foreground hover:bg-accent rounded transition-colors"
title="Export project"
>
<Download className="h-4 w-4" />
</button>
<button
onClick={() => onDuplicateProject(project.id)}
className="p-1.5 text-muted-foreground hover:text-foreground hover:bg-accent rounded transition-colors"
title="Duplicate project"
>
<Copy className="h-4 w-4" />
</button>
<button
onClick={() => {
if (confirm(`Delete "${project.name}"? This cannot be undone.`)) {
onDeleteProject(project.id);
}
}}
className="p-1.5 text-muted-foreground hover:text-destructive hover:bg-destructive/10 rounded transition-colors"
title="Delete project"
>
<Trash2 className="h-4 w-4" />
</button>
</div>
</div>
</div>
))}
</div>
)}
</div>
</div>
</div>
);
}