| import React from 'react'; |
| import { Link } from 'react-router-dom'; |
| import { Search, ChevronDown, ChevronRight, Plus } from 'lucide-react'; |
| import { Input } from '@/components/ui/input'; |
| import { Button } from '@/components/ui/button'; |
| import { cn } from '@/lib/utils'; |
|
|
| |
| |
| |
| |
| export default function MainTableWorkspace({ |
| tabs = [], |
| primaryAction = null, |
| search = null, |
| right = null, |
| filters = null, |
| /** 'top' = full-width strip above the table card; 'left' = narrow rail beside the table inside the card */ |
| filtersPlacement = 'top', |
| sectionIcon: SectionIcon, |
| sectionTitle, |
| sectionCount, |
| sectionOpen, |
| onSectionToggle, |
| tableToolbar = null, |
| children, |
| }) { |
| return ( |
| <div className="w-full min-w-0 space-y-4"> |
| {tabs.length > 0 && ( |
| <div className="flex flex-wrap gap-2 border-b border-slate-200 pb-3"> |
| {tabs.map((t) => ( |
| <button |
| key={t.label} |
| type="button" |
| onClick={t.onClick} |
| disabled={t.disabled} |
| className={cn( |
| 'rounded-full px-4 py-1.5 text-sm font-medium transition-colors', |
| t.active |
| ? 'bg-violet-100 text-violet-800' |
| : 'text-slate-400 hover:text-slate-600 px-3' |
| )} |
| > |
| {t.label} |
| </button> |
| ))} |
| </div> |
| )} |
| |
| <div className="flex w-full min-w-0 flex-col gap-3 lg:flex-row lg:items-center lg:gap-4"> |
| <div className="shrink-0 order-1"> |
| {primaryAction && |
| (primaryAction.to ? ( |
| <Button |
| asChild |
| size="sm" |
| className="bg-teal-600 hover:bg-teal-700 text-white shadow-sm" |
| > |
| <Link to={primaryAction.to} className="inline-flex items-center gap-1.5"> |
| <Plus className="h-4 w-4" /> |
| {primaryAction.label} |
| </Link> |
| </Button> |
| ) : ( |
| <Button |
| size="sm" |
| type="button" |
| disabled={primaryAction.disabled} |
| className="bg-teal-600 hover:bg-teal-700 text-white shadow-sm inline-flex items-center gap-1.5" |
| onClick={primaryAction.onClick} |
| > |
| <Plus className="h-4 w-4" /> |
| {primaryAction.label} |
| </Button> |
| ))} |
| </div> |
| |
| {search && ( |
| <div className="order-3 flex min-w-0 flex-1 justify-center lg:order-2"> |
| <div className="relative w-full max-w-md lg:max-w-xl xl:max-w-2xl 2xl:max-w-3xl"> |
| <Search className="absolute left-3 top-1/2 -translate-y-1/2 h-4 w-4 text-slate-400 pointer-events-none" /> |
| <Input |
| className="pl-9 border-slate-200 shadow-sm" |
| placeholder={search.placeholder} |
| value={search.value} |
| onChange={search.onChange} |
| /> |
| </div> |
| </div> |
| )} |
| |
| <div className="shrink-0 flex flex-wrap gap-2 justify-end order-2 lg:order-3 lg:ml-auto"> |
| {right} |
| </div> |
| </div> |
| |
| {filtersPlacement === 'top' && filters && ( |
| <div className="rounded-xl border border-slate-200 bg-white p-4 shadow-sm">{filters}</div> |
| )} |
| |
| <div className="w-full min-w-0 overflow-visible rounded-xl border border-slate-200 bg-white shadow-sm"> |
| <button |
| type="button" |
| onClick={onSectionToggle} |
| className="w-full flex items-center gap-2 px-4 py-3 text-left font-semibold text-slate-800 border-b border-slate-100 hover:bg-slate-50" |
| > |
| {sectionOpen ? ( |
| <ChevronDown className="h-5 w-5 text-violet-600 shrink-0" /> |
| ) : ( |
| <ChevronRight className="h-5 w-5 text-violet-600 shrink-0" /> |
| )} |
| {SectionIcon ? <SectionIcon className="h-5 w-5 text-slate-500 shrink-0" /> : null} |
| <span className="truncate">{sectionTitle}</span> |
| <span className="text-slate-400 font-normal text-sm ml-2 shrink-0"> |
| {sectionCount} total |
| </span> |
| </button> |
| |
| {sectionOpen && |
| (filtersPlacement === 'left' && filters ? ( |
| <div className="flex flex-col gap-3 border-t border-slate-100 px-2 pb-3 pt-2 sm:px-4 md:flex-row md:items-start md:gap-3"> |
| <aside className="w-full shrink-0 rounded-lg border border-slate-200 bg-slate-50/80 p-2.5 md:w-52 md:max-w-[13rem] overflow-y-auto max-h-[min(70vh,720px)]"> |
| {filters} |
| </aside> |
| <div className="flex min-w-0 flex-1 flex-col gap-2"> |
| {tableToolbar} |
| {children} |
| </div> |
| </div> |
| ) : ( |
| <> |
| {tableToolbar} |
| {children} |
| </> |
| ))} |
| </div> |
| </div> |
| ); |
| } |
|
|