File size: 6,373 Bytes
2d06acb
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
401b968
 
2d06acb
 
 
 
 
 
 
 
 
97b08c9
2d06acb
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
97b08c9
2d06acb
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
4399645
2d06acb
 
 
 
 
 
 
 
 
 
97b08c9
 
2d06acb
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
401b968
2d06acb
 
 
97b08c9
2d06acb
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
401b968
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2d06acb
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
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';

/**
 * Shared “Deals-style” workspace: tabs, teal primary action, centered search, right actions,
 * optional filters strip, collapsible section header, table area.
 */
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>
    );
}