feat: enhance UI components and add vibrant theme support

- Updated layout and styling for various dashboard pages including stock adjustments, counts, transfers, wastage, and vendors to improve responsiveness and visual consistency.
- Introduced a vibrant theme option in the theme toggle component, allowing users to switch between light, dark, and vibrant themes.
- Refactored button styles across login and forgot password pages for better accessibility and visual feedback.
- Improved sidebar navigation with expanded functionality for items without dedicated pages.
- Enhanced data table styling for better readability and user interaction.
- Added new background images to support the vibrant theme.
This commit is contained in:
2026-07-27 11:11:26 +05:30
parent ae20bc4e34
commit c564916c60
56 changed files with 331 additions and 264 deletions
@@ -112,7 +112,7 @@ export default function AttendanceBatchDetailPage() {
return (
<div className="flex flex-col gap-6">
<div className="flex items-center justify-between">
<div className="flex flex-col gap-3 sm:flex-row sm:items-center sm:justify-between">
<div>
<h1 className="text-2xl font-bold text-foreground">{batch.docNo}</h1>
<p className="text-base text-muted-foreground">{new Date(batch.periodStart).toLocaleDateString()} {new Date(batch.periodEnd).toLocaleDateString()} · {batch.rowCountTotal} rows</p>
@@ -132,9 +132,9 @@ export default function AttendanceBatchDetailPage() {
<FieldGroup>
<Field><FieldLabel htmlFor="u-reason">Reason</FieldLabel><Input id="u-reason" value={unlockReason} onChange={(e) => setUnlockReason(e.target.value)} /></Field>
</FieldGroup>
<div className="flex justify-center gap-3 pt-2">
<Button variant="outline" className="min-w-32" onClick={() => setUnlockOpen(false)}>Cancel</Button>
<Button className="min-w-32" onClick={unlock} disabled={busy}>Unlock</Button>
<div className="flex flex-col-reverse gap-3 pt-2 sm:flex-row sm:justify-center">
<Button variant="outline" className="w-full sm:w-auto sm:min-w-32" onClick={() => setUnlockOpen(false)}>Cancel</Button>
<Button className="w-full sm:w-auto sm:min-w-32" onClick={unlock} disabled={busy}>Unlock</Button>
</div>
</DialogContent>
</Dialog>
@@ -69,7 +69,7 @@ export default function AttendanceBatchesPage() {
return (
<div className="flex flex-col gap-6">
<div className="flex items-center justify-between">
<div className="flex flex-col gap-3 sm:flex-row sm:items-center sm:justify-between">
<div>
<h1 className="text-2xl font-bold text-foreground">Attendance</h1>
<p className="text-base text-muted-foreground">Upload Preview Confirm. Once Confirmed, a batch becomes payroll&apos;s source of truth.</p>
@@ -86,7 +86,7 @@ export default function AttendanceBatchesPage() {
<DialogDescription>Columns: Employee Code, Date, Check In, Check Out.</DialogDescription>
</DialogHeader>
<FieldGroup>
<div className="grid grid-cols-2 gap-3">
<div className="grid grid-cols-1 gap-3 sm:grid-cols-2">
<Field><FieldLabel htmlFor="a-start">Period start</FieldLabel><Input id="a-start" type="date" value={periodStart} onChange={(e) => setPeriodStart(e.target.value)} /></Field>
<Field><FieldLabel htmlFor="a-end">Period end</FieldLabel><Input id="a-end" type="date" value={periodEnd} onChange={(e) => setPeriodEnd(e.target.value)} /></Field>
</div>
@@ -95,9 +95,9 @@ export default function AttendanceBatchesPage() {
<Input id="a-file" type="file" accept=".xlsx,.csv" onChange={(e) => setFile(e.target.files?.[0] ?? null)} />
</Field>
</FieldGroup>
<div className="flex justify-center gap-3 pt-2">
<Button variant="outline" className="min-w-32" onClick={() => setOpen(false)} disabled={submitting}>Cancel</Button>
<Button className="min-w-32" onClick={handleUpload} disabled={submitting}><Upload className="size-4" />{submitting ? "Uploading…" : "Upload"}</Button>
<div className="flex flex-col-reverse gap-3 pt-2 sm:flex-row sm:justify-center">
<Button variant="outline" className="w-full sm:w-auto sm:min-w-32" onClick={() => setOpen(false)} disabled={submitting}>Cancel</Button>
<Button className="w-full sm:w-auto sm:min-w-32" onClick={handleUpload} disabled={submitting}><Upload className="size-4" />{submitting ? "Uploading…" : "Upload"}</Button>
</div>
</DialogContent>
</Dialog>
@@ -208,7 +208,7 @@ export default function EmployeeDetailPage() {
return (
<div className="flex flex-col gap-6">
<div className="flex items-center justify-between">
<div className="flex flex-col gap-3 sm:flex-row sm:items-center sm:justify-between">
<div>
<h1 className="text-2xl font-bold text-foreground">{employee.fullName}</h1>
<p className="text-base text-muted-foreground">
@@ -237,7 +237,7 @@ export default function EmployeeDetailPage() {
{tab === "Overview" && (
<FieldGroup className="max-w-2xl">
<div className="grid grid-cols-2 gap-3">
<div className="grid grid-cols-1 gap-3 sm:grid-cols-2">
<Field><FieldLabel>Full name</FieldLabel><Input value={employee.fullName} onChange={(e) => setEmployee({ ...employee, fullName: e.target.value })} /></Field>
<Field><FieldLabel>Email</FieldLabel><Input type="email" value={employee.email ?? ""} onChange={(e) => setEmployee({ ...employee, email: e.target.value })} /></Field>
<Field><FieldLabel>NIC</FieldLabel><Input value={employee.nic ?? ""} onChange={(e) => setEmployee({ ...employee, nic: e.target.value })} /></Field>
@@ -363,7 +363,7 @@ export default function EmployeeDetailPage() {
<DialogDescription>Supersedes the current open-ended structure from this date.</DialogDescription>
</DialogHeader>
<FieldGroup>
<div className="grid grid-cols-2 gap-3">
<div className="grid grid-cols-1 gap-3 sm:grid-cols-2">
<Field><FieldLabel>Effective from</FieldLabel><Input type="date" value={structureEffectiveFrom} onChange={(e) => setStructureEffectiveFrom(e.target.value)} /></Field>
<Field><FieldLabel>Basic salary</FieldLabel><Input type="number" min={0} value={structureBasic} onChange={(e) => setStructureBasic(Number(e.target.value))} /></Field>
</div>
@@ -383,9 +383,9 @@ export default function EmployeeDetailPage() {
</div>
</Field>
</FieldGroup>
<div className="flex justify-center gap-3 pt-2">
<Button variant="outline" className="min-w-32" onClick={() => setStructureOpen(false)} disabled={busy}>Cancel</Button>
<Button className="min-w-32" onClick={createStructure} disabled={busy}>{busy ? "Saving…" : "Save"}</Button>
<div className="flex flex-col-reverse gap-3 pt-2 sm:flex-row sm:justify-center">
<Button variant="outline" className="w-full sm:w-auto sm:min-w-32" onClick={() => setStructureOpen(false)} disabled={busy}>Cancel</Button>
<Button className="w-full sm:w-auto sm:min-w-32" onClick={createStructure} disabled={busy}>{busy ? "Saving…" : "Save"}</Button>
</div>
</DialogContent>
</Dialog>
@@ -433,7 +433,7 @@ export default function EmployeeDetailPage() {
<SelectContent><SelectItem value="Loan">Loan</SelectItem><SelectItem value="Advance">Advance</SelectItem></SelectContent>
</Select>
</Field>
<div className="grid grid-cols-2 gap-3">
<div className="grid grid-cols-1 gap-3 sm:grid-cols-2">
<Field><FieldLabel>Principal</FieldLabel><Input type="number" min={0} value={loanPrincipal} onChange={(e) => setLoanPrincipal(Number(e.target.value))} /></Field>
<Field><FieldLabel>Installment amount</FieldLabel><Input type="number" min={0} value={loanInstallmentAmount} onChange={(e) => setLoanInstallmentAmount(Number(e.target.value))} /></Field>
<Field><FieldLabel># installments</FieldLabel><Input type="number" min={1} value={loanCount} onChange={(e) => setLoanCount(Number(e.target.value))} /></Field>
@@ -445,9 +445,9 @@ export default function EmployeeDetailPage() {
</Field>
</div>
</FieldGroup>
<div className="flex justify-center gap-3 pt-2">
<Button variant="outline" className="min-w-32" onClick={() => setLoanOpen(false)} disabled={busy}>Cancel</Button>
<Button className="min-w-32" onClick={createLoan} disabled={busy}>{busy ? "Creating…" : "Create"}</Button>
<div className="flex flex-col-reverse gap-3 pt-2 sm:flex-row sm:justify-center">
<Button variant="outline" className="w-full sm:w-auto sm:min-w-32" onClick={() => setLoanOpen(false)} disabled={busy}>Cancel</Button>
<Button className="w-full sm:w-auto sm:min-w-32" onClick={createLoan} disabled={busy}>{busy ? "Creating…" : "Create"}</Button>
</div>
</DialogContent>
</Dialog>
@@ -121,7 +121,7 @@ export default function EmployeesPage() {
return (
<div className="flex flex-col gap-6">
<div className="flex items-center justify-between">
<div className="flex flex-col gap-3 sm:flex-row sm:items-center sm:justify-between">
<div>
<h1 className="text-2xl font-bold text-foreground">Employees</h1>
<p className="text-base text-muted-foreground">Staff records separate from system login accounts (see the link chip below).</p>
@@ -134,7 +134,7 @@ export default function EmployeesPage() {
<DialogDescription>Not every employee needs a login a system user account is optional and separate.</DialogDescription>
</DialogHeader>
<FieldGroup>
<div className="grid grid-cols-2 gap-3">
<div className="grid grid-cols-1 gap-3 sm:grid-cols-2">
<Field data-invalid={!!errors.employeeCode}>
<FieldLabel htmlFor="e-code">Employee code</FieldLabel>
<Input id="e-code" value={form.employeeCode} onChange={(e) => setForm((f) => ({ ...f, employeeCode: e.target.value }))} aria-invalid={!!errors.employeeCode} />
@@ -170,7 +170,7 @@ export default function EmployeesPage() {
</div>
)}
</Field>
<div className="grid grid-cols-2 gap-3">
<div className="grid grid-cols-1 gap-3 sm:grid-cols-2">
<Field data-invalid={!!errors.departmentId}>
<FieldLabel htmlFor="e-dept">Department</FieldLabel>
<Select value={form.departmentId ? String(form.departmentId) : undefined} onValueChange={(v) => setForm((f) => ({ ...f, departmentId: Number(v) }))}>
@@ -205,9 +205,9 @@ export default function EmployeesPage() {
</Field>
</div>
</FieldGroup>
<div className="flex justify-center gap-3 pt-2">
<Button variant="outline" className="min-w-32" onClick={() => setOpen(false)} disabled={submitting}>Cancel</Button>
<Button className="min-w-32" onClick={handleCreate} disabled={submitting}>{submitting ? "Creating…" : "Create"}</Button>
<div className="flex flex-col-reverse gap-3 pt-2 sm:flex-row sm:justify-center">
<Button variant="outline" className="w-full sm:w-auto sm:min-w-32" onClick={() => setOpen(false)} disabled={submitting}>Cancel</Button>
<Button className="w-full sm:w-auto sm:min-w-32" onClick={handleCreate} disabled={submitting}>{submitting ? "Creating…" : "Create"}</Button>
</div>
</DialogContent>
</Dialog>
@@ -102,7 +102,7 @@ export default function LeaveRequestsPage() {
return (
<div className="flex flex-col gap-6">
<div className="flex items-center justify-between">
<div className="flex flex-col gap-3 sm:flex-row sm:items-center sm:justify-between">
<div>
<h1 className="text-2xl font-bold text-foreground">Leave</h1>
<p className="text-base text-muted-foreground">Approved leave feeds Attendance&apos;s OnLeave status and Payroll&apos;s No-Pay calculation.</p>
@@ -129,15 +129,15 @@ export default function LeaveRequestsPage() {
<SelectContent>{leaveTypes.map((t) => <SelectItem key={t.leaveTypeId} value={String(t.leaveTypeId)}>{t.name}</SelectItem>)}</SelectContent>
</Select>
</Field>
<div className="grid grid-cols-2 gap-3">
<div className="grid grid-cols-1 gap-3 sm:grid-cols-2">
<Field><FieldLabel>Start date</FieldLabel><Input type="date" value={startDate} onChange={(e) => setStartDate(e.target.value)} /></Field>
<Field><FieldLabel>End date</FieldLabel><Input type="date" value={endDate} onChange={(e) => setEndDate(e.target.value)} /></Field>
</div>
<Field><FieldLabel>Reason (optional)</FieldLabel><Input value={reason} onChange={(e) => setReason(e.target.value)} /></Field>
</FieldGroup>
<div className="flex justify-center gap-3 pt-2">
<Button variant="outline" className="min-w-32" onClick={() => setOpen(false)} disabled={submitting}>Cancel</Button>
<Button className="min-w-32" onClick={handleCreate} disabled={submitting}>{submitting ? "Submitting…" : "Submit"}</Button>
<div className="flex flex-col-reverse gap-3 pt-2 sm:flex-row sm:justify-center">
<Button variant="outline" className="w-full sm:w-auto sm:min-w-32" onClick={() => setOpen(false)} disabled={submitting}>Cancel</Button>
<Button className="w-full sm:w-auto sm:min-w-32" onClick={handleCreate} disabled={submitting}>{submitting ? "Submitting…" : "Submit"}</Button>
</div>
</DialogContent>
</Dialog>
@@ -64,7 +64,7 @@ export default function PayrollLineDetailPage() {
</table>
</div>
<div className="grid grid-cols-3 gap-3 text-sm text-muted-foreground">
<div className="grid grid-cols-2 gap-3 text-sm text-muted-foreground sm:grid-cols-3">
<div>Present days: {line.presentDays}</div>
<div>Absent days: {line.absentDays}</div>
<div>Leave days: {line.leaveDays}</div>
@@ -88,12 +88,12 @@ export default function PayrollRunDetailPage() {
return (
<div className="flex flex-col gap-6">
<div className="flex items-center justify-between">
<div className="flex flex-col gap-3 sm:flex-row sm:items-center sm:justify-between">
<div>
<h1 className="text-2xl font-bold text-foreground">{run.docNo}</h1>
<p className="text-base text-muted-foreground">{run.periodMonth.toString().padStart(2, "0")}/{run.periodYear} · {run.employeeCount} employees</p>
</div>
<div className="flex items-center gap-3">
<div className="flex flex-wrap items-center gap-3">
<Badge variant="outline" className="h-7 px-3 text-sm">{run.status}</Badge>
{run.status === "Draft" && <Button onClick={approve} disabled={busy}>Approve</Button>}
{run.status === "Approved" && <Button onClick={lock} disabled={busy}>Lock Payroll</Button>}
@@ -110,9 +110,9 @@ export default function PayrollRunDetailPage() {
<FieldGroup>
<Field><FieldLabel htmlFor="p-reason">Reason</FieldLabel><Input id="p-reason" value={unlockReason} onChange={(e) => setUnlockReason(e.target.value)} /></Field>
</FieldGroup>
<div className="flex justify-center gap-3 pt-2">
<Button variant="outline" className="min-w-32" onClick={() => setUnlockOpen(false)}>Cancel</Button>
<Button className="min-w-32" onClick={unlock} disabled={busy}>Unlock</Button>
<div className="flex flex-col-reverse gap-3 pt-2 sm:flex-row sm:justify-center">
<Button variant="outline" className="w-full sm:w-auto sm:min-w-32" onClick={() => setUnlockOpen(false)}>Cancel</Button>
<Button className="w-full sm:w-auto sm:min-w-32" onClick={unlock} disabled={busy}>Unlock</Button>
</div>
</DialogContent>
</Dialog>
@@ -63,7 +63,7 @@ export default function PayrollRunsPage() {
return (
<div className="flex flex-col gap-6">
<div className="flex items-center justify-between">
<div className="flex flex-col gap-3 sm:flex-row sm:items-center sm:justify-between">
<div>
<h1 className="text-2xl font-bold text-foreground">Payroll</h1>
<p className="text-base text-muted-foreground">Generate Review Approve Lock Payslips.</p>
@@ -76,14 +76,14 @@ export default function PayrollRunsPage() {
<DialogDescription>Blocked if attendance for this period isn&apos;t fully Confirmed yet.</DialogDescription>
</DialogHeader>
<FieldGroup>
<div className="grid grid-cols-2 gap-3">
<div className="grid grid-cols-1 gap-3 sm:grid-cols-2">
<Field><FieldLabel>Year</FieldLabel><Input type="number" value={periodYear} onChange={(e) => setPeriodYear(Number(e.target.value))} /></Field>
<Field><FieldLabel>Month</FieldLabel><Input type="number" min={1} max={12} value={periodMonth} onChange={(e) => setPeriodMonth(Number(e.target.value))} /></Field>
</div>
</FieldGroup>
<div className="flex justify-center gap-3 pt-2">
<Button variant="outline" className="min-w-32" onClick={() => setOpen(false)} disabled={submitting}>Cancel</Button>
<Button className="min-w-32" onClick={handleGenerate} disabled={submitting}>{submitting ? "Generating…" : "Generate"}</Button>
<div className="flex flex-col-reverse gap-3 pt-2 sm:flex-row sm:justify-center">
<Button variant="outline" className="w-full sm:w-auto sm:min-w-32" onClick={() => setOpen(false)} disabled={submitting}>Cancel</Button>
<Button className="w-full sm:w-auto sm:min-w-32" onClick={handleGenerate} disabled={submitting}>{submitting ? "Generating…" : "Generate"}</Button>
</div>
</DialogContent>
</Dialog>
@@ -92,7 +92,7 @@ export default function DepartmentsPage() {
return (
<div className="flex flex-col gap-6">
<div className="flex items-center justify-between">
<div className="flex flex-col gap-3 sm:flex-row sm:items-center sm:justify-between">
<div>
<h1 className="text-2xl font-bold text-foreground">Departments</h1>
<p className="text-base text-muted-foreground">Org structure unlimited nesting, optionally scoped to a branch.</p>
@@ -140,9 +140,9 @@ export default function DepartmentsPage() {
</Select>
</Field>
</FieldGroup>
<div className="flex justify-center gap-3 pt-2">
<Button variant="outline" className="min-w-32" onClick={() => setOpen(false)} disabled={submitting}>Cancel</Button>
<Button className="min-w-32" onClick={handleCreate} disabled={submitting}>{submitting ? "Creating…" : "Create"}</Button>
<div className="flex flex-col-reverse gap-3 pt-2 sm:flex-row sm:justify-center">
<Button variant="outline" className="w-full sm:w-auto sm:min-w-32" onClick={() => setOpen(false)} disabled={submitting}>Cancel</Button>
<Button className="w-full sm:w-auto sm:min-w-32" onClick={handleCreate} disabled={submitting}>{submitting ? "Creating…" : "Create"}</Button>
</div>
</DialogContent>
</Dialog>
@@ -79,7 +79,7 @@ export default function DocumentTypesPage() {
return (
<div className="flex flex-col gap-6">
<div className="flex items-center justify-between">
<div className="flex flex-col gap-3 sm:flex-row sm:items-center sm:justify-between">
<div>
<h1 className="text-2xl font-bold text-foreground">Document Types</h1>
<p className="text-base text-muted-foreground">The staff document catalog NIC, contracts, certificates, etc.</p>
@@ -120,9 +120,9 @@ export default function DocumentTypesPage() {
<FieldLabel htmlFor="dt-expiry">Track expiry date (e.g. passport, visa)</FieldLabel>
</Field>
</FieldGroup>
<div className="flex justify-center gap-3 pt-2">
<Button variant="outline" className="min-w-32" onClick={() => setOpen(false)} disabled={submitting}>Cancel</Button>
<Button className="min-w-32" onClick={handleCreate} disabled={submitting}>{submitting ? "Creating…" : "Create"}</Button>
<div className="flex flex-col-reverse gap-3 pt-2 sm:flex-row sm:justify-center">
<Button variant="outline" className="w-full sm:w-auto sm:min-w-32" onClick={() => setOpen(false)} disabled={submitting}>Cancel</Button>
<Button className="w-full sm:w-auto sm:min-w-32" onClick={handleCreate} disabled={submitting}>{submitting ? "Creating…" : "Create"}</Button>
</div>
</DialogContent>
</Dialog>
@@ -81,7 +81,7 @@ export default function LeaveTypesPage() {
return (
<div className="flex flex-col gap-6">
<div className="flex items-center justify-between">
<div className="flex flex-col gap-3 sm:flex-row sm:items-center sm:justify-between">
<div>
<h1 className="text-2xl font-bold text-foreground">Leave Types</h1>
<p className="text-base text-muted-foreground">Annual, Casual, Medical, Unpaid, etc. drives Attendance&apos;s OnLeave classification and Payroll&apos;s No-Pay calc.</p>
@@ -121,9 +121,9 @@ export default function LeaveTypesPage() {
<FieldLabel htmlFor="lt-carry">Carry-forward allowed</FieldLabel>
</Field>
</FieldGroup>
<div className="flex justify-center gap-3 pt-2">
<Button variant="outline" className="min-w-32" onClick={() => setOpen(false)} disabled={submitting}>Cancel</Button>
<Button className="min-w-32" onClick={handleCreate} disabled={submitting}>{submitting ? "Creating…" : "Create"}</Button>
<div className="flex flex-col-reverse gap-3 pt-2 sm:flex-row sm:justify-center">
<Button variant="outline" className="w-full sm:w-auto sm:min-w-32" onClick={() => setOpen(false)} disabled={submitting}>Cancel</Button>
<Button className="w-full sm:w-auto sm:min-w-32" onClick={handleCreate} disabled={submitting}>{submitting ? "Creating…" : "Create"}</Button>
</div>
</DialogContent>
</Dialog>
@@ -78,7 +78,7 @@ export default function SalaryComponentsPage() {
return (
<div className="flex flex-col gap-6">
<div className="flex items-center justify-between">
<div className="flex flex-col gap-3 sm:flex-row sm:items-center sm:justify-between">
<div>
<h1 className="text-2xl font-bold text-foreground">Salary Components</h1>
<p className="text-base text-muted-foreground">Allowances and ad hoc other deductions OT/Late/No-Pay/Loan/EPF/ETF/Tax are computed automatically, not components.</p>
@@ -120,9 +120,9 @@ export default function SalaryComponentsPage() {
<FieldLabel htmlFor="sc-epfetf">EPF/ETF applicable</FieldLabel>
</Field>
</FieldGroup>
<div className="flex justify-center gap-3 pt-2">
<Button variant="outline" className="min-w-32" onClick={() => setOpen(false)} disabled={submitting}>Cancel</Button>
<Button className="min-w-32" onClick={handleCreate} disabled={submitting}>{submitting ? "Creating…" : "Create"}</Button>
<div className="flex flex-col-reverse gap-3 pt-2 sm:flex-row sm:justify-center">
<Button variant="outline" className="w-full sm:w-auto sm:min-w-32" onClick={() => setOpen(false)} disabled={submitting}>Cancel</Button>
<Button className="w-full sm:w-auto sm:min-w-32" onClick={handleCreate} disabled={submitting}>{submitting ? "Creating…" : "Create"}</Button>
</div>
</DialogContent>
</Dialog>
@@ -85,7 +85,7 @@ export default function StatutorySettingsPage() {
{error && <div className="rounded-lg border border-destructive/30 bg-destructive/5 p-5 text-base text-destructive">{error}</div>}
<section className="flex flex-col gap-4">
<div className="flex items-center justify-between">
<div className="flex flex-col gap-3 sm:flex-row sm:items-center sm:justify-between">
<h2 className="text-lg font-semibold text-foreground">EPF / ETF Rates</h2>
<Dialog open={settingOpen} onOpenChange={setSettingOpen}>
<DialogTrigger render={<Button size="sm"><Plus className="size-4" />New Setting</Button>} />
@@ -101,9 +101,9 @@ export default function StatutorySettingsPage() {
<Field><FieldLabel>ETF employer rate (0-1)</FieldLabel><Input type="number" step="0.001" value={etfEmployerRate} onChange={(e) => setEtfEmployerRate(Number(e.target.value))} /></Field>
<Field><FieldLabel>Default OT multiplier</FieldLabel><Input type="number" step="0.1" value={otMultiplierDefault} onChange={(e) => setOtMultiplierDefault(Number(e.target.value))} /></Field>
</FieldGroup>
<div className="flex justify-center gap-3 pt-2">
<Button variant="outline" className="min-w-32" onClick={() => setSettingOpen(false)} disabled={submitting}>Cancel</Button>
<Button className="min-w-32" onClick={createSetting} disabled={submitting}>{submitting ? "Saving…" : "Save"}</Button>
<div className="flex flex-col-reverse gap-3 pt-2 sm:flex-row sm:justify-center">
<Button variant="outline" className="w-full sm:w-auto sm:min-w-32" onClick={() => setSettingOpen(false)} disabled={submitting}>Cancel</Button>
<Button className="w-full sm:w-auto sm:min-w-32" onClick={createSetting} disabled={submitting}>{submitting ? "Saving…" : "Save"}</Button>
</div>
</DialogContent>
</Dialog>
@@ -133,7 +133,7 @@ export default function StatutorySettingsPage() {
</section>
<section className="flex flex-col gap-4">
<div className="flex items-center justify-between">
<div className="flex flex-col gap-3 sm:flex-row sm:items-center sm:justify-between">
<h2 className="text-lg font-semibold text-foreground">Tax Slabs</h2>
<Dialog open={slabOpen} onOpenChange={setSlabOpen}>
<DialogTrigger render={<Button size="sm"><Plus className="size-4" />New Slab</Button>} />
@@ -148,9 +148,9 @@ export default function StatutorySettingsPage() {
<Field><FieldLabel>Upper bound (optional)</FieldLabel><Input type="number" value={upperBound} onChange={(e) => setUpperBound(e.target.value)} placeholder="And above" /></Field>
<Field><FieldLabel>Rate (0-1)</FieldLabel><Input type="number" step="0.01" value={rate} onChange={(e) => setRate(Number(e.target.value))} /></Field>
</FieldGroup>
<div className="flex justify-center gap-3 pt-2">
<Button variant="outline" className="min-w-32" onClick={() => setSlabOpen(false)} disabled={submitting}>Cancel</Button>
<Button className="min-w-32" onClick={createSlab} disabled={submitting}>{submitting ? "Creating…" : "Create"}</Button>
<div className="flex flex-col-reverse gap-3 pt-2 sm:flex-row sm:justify-center">
<Button variant="outline" className="w-full sm:w-auto sm:min-w-32" onClick={() => setSlabOpen(false)} disabled={submitting}>Cancel</Button>
<Button className="w-full sm:w-auto sm:min-w-32" onClick={createSlab} disabled={submitting}>{submitting ? "Creating…" : "Create"}</Button>
</div>
</DialogContent>
</Dialog>
@@ -99,7 +99,7 @@ export default function WorkShiftsPage() {
return (
<div className="flex flex-col gap-6">
<div className="flex items-center justify-between">
<div className="flex flex-col gap-3 sm:flex-row sm:items-center sm:justify-between">
<div>
<h1 className="text-2xl font-bold text-foreground">Work Shifts</h1>
<p className="text-base text-muted-foreground">The baseline Attendance computes Late/Early/OT against.</p>
@@ -122,7 +122,7 @@ export default function WorkShiftsPage() {
<Input id="w-name" value={name} onChange={(e) => setName(e.target.value)} aria-invalid={!!errors.name} />
<FieldError errors={[errors.name ? { message: errors.name } : undefined]} />
</Field>
<div className="grid grid-cols-2 gap-3">
<div className="grid grid-cols-1 gap-3 sm:grid-cols-2">
<Field>
<FieldLabel htmlFor="w-start">Start time</FieldLabel>
<Input id="w-start" type="time" value={startTime} onChange={(e) => setStartTime(e.target.value)} />
@@ -136,7 +136,7 @@ export default function WorkShiftsPage() {
<Checkbox id="w-overnight" checked={isOvernight} onCheckedChange={(v) => setIsOvernight(v === true)} />
<FieldLabel htmlFor="w-overnight">Overnight shift (end time rolls past midnight)</FieldLabel>
</Field>
<div className="grid grid-cols-2 gap-3">
<div className="grid grid-cols-1 gap-3 sm:grid-cols-2">
<Field>
<FieldLabel htmlFor="w-grace">Grace (minutes)</FieldLabel>
<Input id="w-grace" type="number" min={0} value={graceMinutes} onChange={(e) => setGraceMinutes(Number(e.target.value))} />
@@ -166,9 +166,9 @@ export default function WorkShiftsPage() {
</div>
</Field>
</FieldGroup>
<div className="flex justify-center gap-3 pt-2">
<Button variant="outline" className="min-w-32" onClick={() => setOpen(false)} disabled={submitting}>Cancel</Button>
<Button className="min-w-32" onClick={handleCreate} disabled={submitting}>{submitting ? "Creating…" : "Create"}</Button>
<div className="flex flex-col-reverse gap-3 pt-2 sm:flex-row sm:justify-center">
<Button variant="outline" className="w-full sm:w-auto sm:min-w-32" onClick={() => setOpen(false)} disabled={submitting}>Cancel</Button>
<Button className="w-full sm:w-auto sm:min-w-32" onClick={handleCreate} disabled={submitting}>{submitting ? "Creating…" : "Create"}</Button>
</div>
</DialogContent>
</Dialog>
+3 -3
View File
@@ -13,10 +13,10 @@ export default function DashboardLayout({
<AuthProvider>
<div className="flex h-screen overflow-hidden bg-background">
<AppSidebar />
<main className="flex flex-1 flex-col">
<main className="flex min-w-0 flex-1 flex-col">
<Header />
<div className="flex-1 overflow-auto">
<div className="p-6 lg:p-8">
<div className="min-w-0 flex-1 overflow-auto">
<div className="min-w-0 px-6 pt-3 pb-6 lg:px-8 lg:pt-4 lg:pb-8">
<Breadcrumbs />
<div className="rounded-xl bg-card border border-border shadow-sm">
<div className="p-6">
@@ -267,7 +267,7 @@ export default function PurchaseOrderDetailPage() {
return (
<div className="flex flex-col gap-6">
<div className="flex items-center justify-between">
<div className="flex flex-col gap-3 sm:flex-row sm:items-center sm:justify-between">
<div className="flex items-center gap-3">
<Link href="/dashboard/procurement/purchase-orders" className={cn(buttonVariants({ variant: "ghost", size: "icon-lg" }))}>
<ArrowLeft className="size-5" />
@@ -283,7 +283,7 @@ export default function PurchaseOrderDetailPage() {
</div>
</div>
<div className="flex items-center gap-3">
<div className="flex flex-wrap items-center gap-3">
{po.status === "Draft" && (
<>
<Button variant="outline" size="lg" onClick={handleSubmitPo} disabled={submitting || deleting}>
@@ -64,7 +64,7 @@ export default function PurchaseOrdersListPage() {
return (
<div className="flex flex-col gap-6">
<div className="flex items-center justify-between">
<div className="flex flex-col gap-3 sm:flex-row sm:items-center sm:justify-between">
<div>
<h1 className="text-2xl font-bold text-foreground">Purchase Orders</h1>
<p className="text-base text-muted-foreground">Auto-approved on creation and freely editable while open (FR-PROC-03..05).</p>
@@ -48,7 +48,7 @@ export default function PurchaseReturnsListPage() {
return (
<div className="flex flex-col gap-6">
<div className="flex items-center justify-between">
<div className="flex flex-col gap-3 sm:flex-row sm:items-center sm:justify-between">
<div>
<h1 className="text-2xl font-bold text-foreground">Purchase Returns</h1>
<p className="text-base text-muted-foreground">Return received goods to a vendor, referencing the original GRN line (FR-PROC-08).</p>
@@ -72,7 +72,7 @@ export default function RequisitionDetailPage() {
return (
<div className="flex flex-col gap-6">
<div className="flex items-center justify-between">
<div className="flex flex-col gap-3 sm:flex-row sm:items-center sm:justify-between">
<div className="flex items-center gap-3">
<Link href="/dashboard/procurement/requisitions" className={cn(buttonVariants({ variant: "ghost", size: "icon-lg" }))}>
<ArrowLeft className="size-5" />
@@ -86,7 +86,7 @@ export default function RequisitionDetailPage() {
</div>
</div>
<div className="flex items-center gap-2">
<div className="flex flex-wrap items-center gap-2">
{requisition.status === "Draft" && (
<Button size="lg" onClick={handleSubmit} disabled={submitting}>
<Send className="size-5" />
@@ -43,7 +43,7 @@ export default function RequisitionsListPage() {
return (
<div className="flex flex-col gap-6">
<div className="flex items-center justify-between">
<div className="flex flex-col gap-3 sm:flex-row sm:items-center sm:justify-between">
<div>
<h1 className="text-2xl font-bold text-foreground">Requisitions</h1>
<p className="text-base text-muted-foreground">Raise a purchase requisition and submit it into procurement (FR-PROC-01).</p>
@@ -28,7 +28,7 @@ export default function RfqsListPage() {
return (
<div className="flex flex-col gap-6">
<div className="flex items-center justify-between">
<div className="flex flex-col gap-3 sm:flex-row sm:items-center sm:justify-between">
<div>
<h1 className="text-2xl font-bold text-foreground">RFQs</h1>
<p className="text-base text-muted-foreground">Request quotations from vendors and compare pricing (FR-PROC-02).</p>
@@ -181,7 +181,7 @@ export default function ItemDetailPage() {
return (
<div className="flex flex-col gap-6">
<div className="flex items-center justify-between">
<div className="flex flex-col gap-3 sm:flex-row sm:items-center sm:justify-between">
<div className="flex items-center gap-3">
<Link href="/dashboard/products" className={cn(buttonVariants({ variant: "ghost", size: "icon-lg" }))}>
<ArrowLeft className="size-5" />
@@ -155,7 +155,7 @@ export default function BrandsPage() {
return (
<div className="flex flex-col gap-6">
<div className="flex items-center justify-between">
<div className="flex flex-col gap-3 sm:flex-row sm:items-center sm:justify-between">
<div className="flex items-center gap-3">
<Link href="/dashboard/products" className={cn(buttonVariants({ variant: "ghost", size: "icon-lg" }))}>
<ArrowLeft className="size-5" />
@@ -180,11 +180,11 @@ export default function BrandsPage() {
<FieldError errors={[errors.name ? { message: errors.name } : undefined]} />
</Field>
</FieldGroup>
<div className="flex justify-center gap-3 pt-2">
<Button variant="outline" className="min-w-36" onClick={() => setOpen(false)} disabled={submitting}>
<div className="flex flex-col-reverse gap-3 pt-2 sm:flex-row sm:justify-center">
<Button variant="outline" className="w-full sm:w-auto sm:min-w-36" onClick={() => setOpen(false)} disabled={submitting}>
Cancel
</Button>
<Button className="min-w-36" onClick={handleSubmit} disabled={submitting}>
<Button className="w-full sm:w-auto sm:min-w-36" onClick={handleSubmit} disabled={submitting}>
{submitting ? (editing ? "Saving…" : "Creating…") : editing ? "Save" : "Create"}
</Button>
</div>
@@ -111,7 +111,7 @@ export default function CategorySubCategoriesPage() {
return (
<div className="flex flex-col gap-6">
<div className="flex items-center justify-between">
<div className="flex flex-col gap-3 sm:flex-row sm:items-center sm:justify-between">
<div className="flex items-center gap-3">
<Link href="/dashboard/products/categories" className={cn(buttonVariants({ variant: "ghost", size: "icon-lg" }))}>
<ArrowLeft className="size-5" />
@@ -138,11 +138,11 @@ export default function CategorySubCategoriesPage() {
<FieldError errors={[errors.name ? { message: errors.name } : undefined]} />
</Field>
</FieldGroup>
<div className="flex justify-center gap-3 pt-2">
<Button variant="outline" className="min-w-36" onClick={() => setOpen(false)} disabled={submitting}>
<div className="flex flex-col-reverse gap-3 pt-2 sm:flex-row sm:justify-center">
<Button variant="outline" className="w-full sm:w-auto sm:min-w-36" onClick={() => setOpen(false)} disabled={submitting}>
Cancel
</Button>
<Button className="min-w-36" onClick={handleSubmit} disabled={submitting}>
<Button className="w-full sm:w-auto sm:min-w-36" onClick={handleSubmit} disabled={submitting}>
{submitting ? (editing ? "Saving…" : "Creating…") : editing ? "Save" : "Create"}
</Button>
</div>
@@ -154,7 +154,7 @@ export default function CategoriesPage() {
return (
<div className="flex flex-col gap-6">
<div className="flex items-center justify-between">
<div className="flex flex-col gap-3 sm:flex-row sm:items-center sm:justify-between">
<div className="flex items-center gap-3">
<Link href="/dashboard/products" className={cn(buttonVariants({ variant: "ghost", size: "icon-lg" }))}>
<ArrowLeft className="size-5" />
@@ -179,11 +179,11 @@ export default function CategoriesPage() {
<FieldError errors={[errors.name ? { message: errors.name } : undefined]} />
</Field>
</FieldGroup>
<div className="flex justify-center gap-3 pt-2">
<Button variant="outline" className="min-w-36" onClick={() => setOpen(false)} disabled={submitting}>
<div className="flex flex-col-reverse gap-3 pt-2 sm:flex-row sm:justify-center">
<Button variant="outline" className="w-full sm:w-auto sm:min-w-36" onClick={() => setOpen(false)} disabled={submitting}>
Cancel
</Button>
<Button className="min-w-36" onClick={handleSubmit} disabled={submitting}>
<Button className="w-full sm:w-auto sm:min-w-36" onClick={handleSubmit} disabled={submitting}>
{submitting ? (editing ? "Saving…" : "Creating…") : editing ? "Save" : "Create"}
</Button>
</div>
@@ -108,7 +108,7 @@ export default function ItemTypesPage() {
return (
<div className="flex flex-col gap-6">
<div className="flex items-center justify-between">
<div className="flex flex-col gap-3 sm:flex-row sm:items-center sm:justify-between">
<div className="flex items-center gap-3">
<Link href="/dashboard/products" className={cn(buttonVariants({ variant: "ghost", size: "icon-lg" }))}>
<ArrowLeft className="size-5" />
@@ -141,11 +141,11 @@ export default function ItemTypesPage() {
<FieldError errors={[errors.name ? { message: errors.name } : undefined]} />
</Field>
</FieldGroup>
<div className="flex justify-center gap-3 pt-2">
<Button variant="outline" className="min-w-36" onClick={() => setOpen(false)} disabled={submitting}>
<div className="flex flex-col-reverse gap-3 pt-2 sm:flex-row sm:justify-center">
<Button variant="outline" className="w-full sm:w-auto sm:min-w-36" onClick={() => setOpen(false)} disabled={submitting}>
Cancel
</Button>
<Button className="min-w-36" onClick={handleSubmit} disabled={submitting}>
<Button className="w-full sm:w-auto sm:min-w-36" onClick={handleSubmit} disabled={submitting}>
{submitting ? (editing ? "Saving…" : "Creating…") : editing ? "Save" : "Create"}
</Button>
</div>
@@ -100,7 +100,7 @@ export default function ItemsPage() {
return (
<div className="flex flex-col gap-6">
<div className="flex items-center justify-between">
<div className="flex flex-col gap-3 sm:flex-row sm:items-center sm:justify-between">
<div>
<h1 className="text-2xl font-bold text-foreground">Items</h1>
<p className="text-base text-muted-foreground">Item master SKU, tracking mode, category, default vendor (FR-MD-01).</p>
@@ -57,7 +57,7 @@ export default function UomsPage() {
return (
<div className="flex flex-col gap-6">
<div className="flex items-center justify-between">
<div className="flex flex-col gap-3 sm:flex-row sm:items-center sm:justify-between">
<div className="flex items-center gap-3">
<Link href="/dashboard/products" className={cn(buttonVariants({ variant: "ghost", size: "icon-lg" }))}>
<ArrowLeft className="size-5" />
@@ -82,11 +82,11 @@ export default function UomsPage() {
<FieldError errors={[errors.name ? { message: errors.name } : undefined]} />
</Field>
</FieldGroup>
<div className="flex justify-center gap-3 pt-2">
<Button variant="outline" className="min-w-36" onClick={() => setOpen(false)} disabled={submitting}>
<div className="flex flex-col-reverse gap-3 pt-2 sm:flex-row sm:justify-center">
<Button variant="outline" className="w-full sm:w-auto sm:min-w-36" onClick={() => setOpen(false)} disabled={submitting}>
Cancel
</Button>
<Button className="min-w-36" onClick={handleCreate} disabled={submitting}>
<Button className="w-full sm:w-auto sm:min-w-36" onClick={handleCreate} disabled={submitting}>
{submitting ? "Creating…" : "Create"}
</Button>
</div>
@@ -116,7 +116,7 @@ export default function GrnDetailPage() {
return (
<div className="flex flex-col gap-6">
<div className="flex items-center justify-between">
<div className="flex flex-col gap-3 sm:flex-row sm:items-center sm:justify-between">
<div className="flex items-center gap-3">
<Link href="/dashboard/receiving/grn" className={cn(buttonVariants({ variant: "ghost", size: "icon-lg" }))}>
<ArrowLeft className="size-5" />
@@ -400,20 +400,7 @@ export default function NewGrnPage() {
)}
<div className="flex flex-col gap-3">
<div className="flex items-center justify-between">
<div>
<h2 className="text-base font-semibold text-foreground">Lines</h2>
{mode === "po" && (
<p className="text-sm text-muted-foreground">
Lines default from the PO&apos;s open quantities add a row for anything received that wasn&apos;t ordered.
</p>
)}
</div>
<Button type="button" variant="outline" onClick={() => setLines((prev) => [...prev, emptyLine()])}>
<Plus className="size-5" />
Add line
</Button>
<div className="flex items-center justify-between gap-3">
<div className="flex flex-col gap-3 sm:flex-row sm:items-center sm:justify-between">
<div>
<h2 className="text-base font-semibold text-foreground">Lines</h2>
{mode === "po" && (
@@ -422,7 +409,7 @@ export default function NewGrnPage() {
</p>
)}
</div>
<div className="flex items-center gap-2">
<div className="flex flex-wrap items-center gap-2">
{/* Off-PO items are allowed on a PO-based GRN — the server treats a line with
no poLineId as a direct receipt (docs/10 FR-GRN-01, revised). */}
<Button type="button" variant="outline" onClick={() => setLines((prev) => [...prev, emptyLine()])}>
@@ -72,7 +72,7 @@ export default function GrnListPage() {
return (
<div className="flex flex-col gap-6">
<div className="flex items-center justify-between">
<div className="flex flex-col gap-3 sm:flex-row sm:items-center sm:justify-between">
<div>
<h1 className="text-2xl font-bold text-foreground">Goods Receipt Notes</h1>
<p className="text-base text-muted-foreground">
@@ -123,7 +123,7 @@ export default function RolesPage() {
return (
<div className="flex flex-col gap-6">
<div className="flex items-center justify-between">
<div className="flex flex-col gap-3 sm:flex-row sm:items-center sm:justify-between">
<div>
<h1 className="text-2xl font-bold text-foreground">Roles</h1>
<p className="text-base text-muted-foreground">
@@ -182,11 +182,11 @@ export default function RolesPage() {
)}
</div>
<div className="flex justify-center gap-3 pt-2">
<Button variant="outline" className="min-w-36" onClick={() => setOpen(false)} disabled={submitting}>
<div className="flex flex-col-reverse gap-3 pt-2 sm:flex-row sm:justify-center">
<Button variant="outline" className="w-full sm:w-auto sm:min-w-36" onClick={() => setOpen(false)} disabled={submitting}>
Cancel
</Button>
<Button className="min-w-36" onClick={handleCreate} disabled={submitting}>
<Button className="w-full sm:w-auto sm:min-w-36" onClick={handleCreate} disabled={submitting}>
{submitting ? "Creating…" : "Create"}
</Button>
</div>
@@ -147,7 +147,7 @@ export default function UsersPage() {
return (
<div className="flex flex-col gap-6">
<div className="flex items-center justify-between">
<div className="flex flex-col gap-3 sm:flex-row sm:items-center sm:justify-between">
<div>
<h1 className="text-2xl font-bold text-foreground">Users</h1>
<p className="text-base text-muted-foreground">
@@ -242,11 +242,11 @@ export default function UsersPage() {
<FieldError errors={[errors.userTypeId ? { message: errors.userTypeId } : undefined]} />
</Field>
</FieldGroup>
<div className="flex justify-center gap-3 pt-2">
<Button variant="outline" className="min-w-36" onClick={() => setOpen(false)} disabled={submitting}>
<div className="flex flex-col-reverse gap-3 pt-2 sm:flex-row sm:justify-center">
<Button variant="outline" className="w-full sm:w-auto sm:min-w-36" onClick={() => setOpen(false)} disabled={submitting}>
Cancel
</Button>
<Button className="min-w-36" onClick={handleCreate} disabled={submitting}>
<Button className="w-full sm:w-auto sm:min-w-36" onClick={handleCreate} disabled={submitting}>
{submitting ? "Creating…" : "Create"}
</Button>
</div>
@@ -37,7 +37,7 @@ export default function AdjustmentsListPage() {
return (
<div className="flex flex-col gap-6">
<div className="flex items-center justify-between">
<div className="flex flex-col gap-3 sm:flex-row sm:items-center sm:justify-between">
<div className="flex items-center gap-3">
<Link href="/dashboard/stock" className={cn(buttonVariants({ variant: "ghost", size: "icon-lg" }))}>
<ArrowLeft className="size-5" />
@@ -89,7 +89,7 @@ export default function CountDetailPage() {
return (
<div className="flex flex-col gap-6">
<div className="flex items-center justify-between">
<div className="flex flex-col gap-3 sm:flex-row sm:items-center sm:justify-between">
<div className="flex items-center gap-3">
<Link href="/dashboard/stock/counts" className={cn(buttonVariants({ variant: "ghost", size: "icon-lg" }))}>
<ArrowLeft className="size-5" />
@@ -34,7 +34,7 @@ export default function CountsListPage() {
return (
<div className="flex flex-col gap-6">
<div className="flex items-center justify-between">
<div className="flex flex-col gap-3 sm:flex-row sm:items-center sm:justify-between">
<div className="flex items-center gap-3">
<Link href="/dashboard/stock" className={cn(buttonVariants({ variant: "ghost", size: "icon-lg" }))}>
<ArrowLeft className="size-5" />
@@ -83,7 +83,7 @@ export default function TransferDetailPage() {
return (
<div className="flex flex-col gap-6">
<div className="flex items-center justify-between">
<div className="flex flex-col gap-3 sm:flex-row sm:items-center sm:justify-between">
<div className="flex items-center gap-3">
<Link href="/dashboard/stock/transfers" className={cn(buttonVariants({ variant: "ghost", size: "icon-lg" }))}>
<ArrowLeft className="size-5" />
@@ -34,7 +34,7 @@ export default function TransfersListPage() {
return (
<div className="flex flex-col gap-6">
<div className="flex items-center justify-between">
<div className="flex flex-col gap-3 sm:flex-row sm:items-center sm:justify-between">
<div className="flex items-center gap-3">
<Link href="/dashboard/stock" className={cn(buttonVariants({ variant: "ghost", size: "icon-lg" }))}>
<ArrowLeft className="size-5" />
@@ -66,7 +66,7 @@ export default function WastagePage() {
return (
<div className="flex flex-col gap-6">
<div className="flex items-center justify-between">
<div className="flex flex-col gap-3 sm:flex-row sm:items-center sm:justify-between">
<div className="flex items-center gap-3">
<Link href="/dashboard/stock" className={cn(buttonVariants({ variant: "ghost", size: "icon-lg" }))}>
<ArrowLeft className="size-5" />
+1 -1
View File
@@ -130,7 +130,7 @@ export default function VendorDetailPage() {
return (
<div className="flex flex-col gap-6">
<div className="flex items-center justify-between">
<div className="flex flex-col gap-3 sm:flex-row sm:items-center sm:justify-between">
<div className="flex items-center gap-3">
<Link href="/dashboard/vendors" className={cn(buttonVariants({ variant: "ghost", size: "icon-lg" }))}>
<ArrowLeft className="size-5" />
+5 -5
View File
@@ -127,7 +127,7 @@ export default function VendorsPage() {
return (
<div className="flex flex-col gap-6">
<div className="flex items-center justify-between">
<div className="flex flex-col gap-3 sm:flex-row sm:items-center sm:justify-between">
<div>
<h1 className="text-2xl font-bold text-foreground">Vendors</h1>
<p className="text-base text-muted-foreground">Supplier master data code, terms, tax registration, currency (FR-MD-06).</p>
@@ -172,11 +172,11 @@ export default function VendorsPage() {
<FieldError errors={[errors.currency ? { message: errors.currency } : undefined]} />
</Field>
</FieldGroup>
<div className="flex justify-center gap-3 pt-2">
<Button variant="outline" className="min-w-36" onClick={() => setOpen(false)} disabled={submitting}>
<div className="flex flex-col-reverse gap-3 pt-2 sm:flex-row sm:justify-center">
<Button variant="outline" className="w-full sm:w-auto sm:min-w-36" onClick={() => setOpen(false)} disabled={submitting}>
Cancel
</Button>
<Button className="min-w-36" onClick={handleCreate} disabled={submitting}>
<Button className="w-full sm:w-auto sm:min-w-36" onClick={handleCreate} disabled={submitting}>
{submitting ? "Creating…" : "Create"}
</Button>
</div>
@@ -303,7 +303,7 @@ export default function VendorsPage() {
</div>
</div>
<div className="flex justify-center pt-2">
<DialogClose render={<Button variant="outline" className="min-w-36" />}>Close</DialogClose>
<DialogClose render={<Button variant="outline" className="w-full sm:w-auto sm:min-w-36" />}>Close</DialogClose>
</div>
</DialogContent>
</Dialog>
@@ -88,7 +88,7 @@ export default function WarehouseDetailPage() {
return (
<div className="flex flex-col gap-6">
<div className="flex items-center justify-between">
<div className="flex flex-col gap-3 sm:flex-row sm:items-center sm:justify-between">
<div className="flex items-center gap-3">
<Link href="/dashboard/warehouse" className={cn(buttonVariants({ variant: "ghost", size: "icon-lg" }))}>
<ArrowLeft className="size-5" />
@@ -124,11 +124,11 @@ export default function WarehouseDetailPage() {
<Input id="bin-type" value={binType} onChange={(e) => setBinType(e.target.value)} placeholder="Shelf, Pallet, …" />
</Field>
</FieldGroup>
<div className="flex justify-center gap-3 pt-2">
<Button variant="outline" className="min-w-36" onClick={() => setOpen(false)} disabled={submitting}>
<div className="flex flex-col-reverse gap-3 pt-2 sm:flex-row sm:justify-center">
<Button variant="outline" className="w-full sm:w-auto sm:min-w-36" onClick={() => setOpen(false)} disabled={submitting}>
Cancel
</Button>
<Button className="min-w-36" onClick={handleCreate} disabled={submitting}>
<Button className="w-full sm:w-auto sm:min-w-36" onClick={handleCreate} disabled={submitting}>
{submitting ? "Creating…" : "Create"}
</Button>
</div>
@@ -98,7 +98,7 @@ export default function WarehousesPage() {
return (
<div className="flex flex-col gap-6">
<div className="flex items-center justify-between">
<div className="flex flex-col gap-3 sm:flex-row sm:items-center sm:justify-between">
<div className="flex items-center gap-3">
<Link href="/dashboard" className={cn(buttonVariants({ variant: "ghost", size: "icon-lg" }))}>
<ArrowLeft className="size-5" />
@@ -134,11 +134,11 @@ export default function WarehousesPage() {
<Input id="wh-code" value={generatedCode} readOnly disabled placeholder="Enter a name to generate a code" className="text-muted-foreground" />
</Field>
</FieldGroup>
<div className="flex justify-center gap-3 pt-2">
<Button variant="outline" className="min-w-36" onClick={() => setOpen(false)} disabled={submitting}>
<div className="flex flex-col-reverse gap-3 pt-2 sm:flex-row sm:justify-center">
<Button variant="outline" className="w-full sm:w-auto sm:min-w-36" onClick={() => setOpen(false)} disabled={submitting}>
Cancel
</Button>
<Button className="min-w-36" onClick={handleCreate} disabled={submitting}>
<Button className="w-full sm:w-auto sm:min-w-36" onClick={handleCreate} disabled={submitting}>
{submitting ? "Creating…" : "Create"}
</Button>
</div>