2 - Restyle settings panel as inline slide-out block
This commit is contained in:
parent
7d2e373ffd
commit
a9d74e3eee
2 changed files with 64 additions and 76 deletions
|
|
@ -1,9 +1,3 @@
|
||||||
import {
|
|
||||||
Sheet,
|
|
||||||
SheetContent,
|
|
||||||
SheetHeader,
|
|
||||||
SheetTitle,
|
|
||||||
} from '@/components/ui/sheet';
|
|
||||||
import { csrfToken } from '@/lib/utils';
|
import { csrfToken } from '@/lib/utils';
|
||||||
import { type SharedData } from '@/types';
|
import { type SharedData } from '@/types';
|
||||||
import { router, usePage } from '@inertiajs/react';
|
import { router, usePage } from '@inertiajs/react';
|
||||||
|
|
@ -21,13 +15,13 @@ interface DistributionOption {
|
||||||
const distributionOptions: DistributionOption[] = [
|
const distributionOptions: DistributionOption[] = [
|
||||||
{
|
{
|
||||||
value: 'even',
|
value: 'even',
|
||||||
label: 'Even Split',
|
label: 'EVEN SPLIT',
|
||||||
description:
|
description:
|
||||||
'Split evenly across buckets in each phase, respecting individual capacity',
|
'Split evenly across buckets in each phase, respecting individual capacity',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
value: 'priority',
|
value: 'priority',
|
||||||
label: 'Priority Order',
|
label: 'PRIORITY ORDER',
|
||||||
description: 'Fill highest-priority bucket first, then next',
|
description: 'Fill highest-priority bucket first, then next',
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
|
|
@ -38,7 +32,6 @@ interface SettingsPanelProps {
|
||||||
}
|
}
|
||||||
|
|
||||||
export default function SettingsPanel({
|
export default function SettingsPanel({
|
||||||
open,
|
|
||||||
onOpenChange,
|
onOpenChange,
|
||||||
}: SettingsPanelProps) {
|
}: SettingsPanelProps) {
|
||||||
const { scenario } = usePage<SharedData>().props;
|
const { scenario } = usePage<SharedData>().props;
|
||||||
|
|
@ -72,71 +65,61 @@ export default function SettingsPanel({
|
||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Sheet open={open} onOpenChange={onOpenChange}>
|
<div className="mb-8 border-4 border-red-500 bg-black p-6 glow-red">
|
||||||
<SheetContent side="top" className="px-6 pb-6">
|
<div className="flex items-center justify-between mb-4">
|
||||||
<SheetHeader>
|
<h2 className="text-lg font-mono font-bold tracking-wider uppercase text-red-500">
|
||||||
<SheetTitle>Settings</SheetTitle>
|
SETTINGS
|
||||||
</SheetHeader>
|
</h2>
|
||||||
|
<button
|
||||||
|
onClick={() => onOpenChange(false)}
|
||||||
|
className="text-red-500/60 hover:text-red-500 font-mono text-sm transition-colors"
|
||||||
|
>
|
||||||
|
CLOSE
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
|
||||||
<div className="mx-auto max-w-2xl">
|
<fieldset disabled={saveStatus === 'saving'}>
|
||||||
<fieldset disabled={saveStatus === 'saving'}>
|
<legend className="text-xs font-mono uppercase text-red-500/60">
|
||||||
<legend className="text-sm font-medium text-foreground">
|
DISTRIBUTION MODE
|
||||||
Distribution Mode
|
{saveStatus === 'success' && (
|
||||||
{saveStatus === 'success' && (
|
<span className="ml-2 text-green-500">SAVED</span>
|
||||||
<span className="ml-2 text-green-600">
|
)}
|
||||||
Saved
|
{saveStatus === 'error' && (
|
||||||
</span>
|
<span className="ml-2 text-red-500">FAILED</span>
|
||||||
)}
|
)}
|
||||||
{saveStatus === 'error' && (
|
</legend>
|
||||||
<span className="ml-2 text-red-600">
|
<div className="mt-3 space-y-2">
|
||||||
Failed to save
|
{distributionOptions.map((option) => (
|
||||||
</span>
|
<label
|
||||||
)}
|
key={option.value}
|
||||||
</legend>
|
className={`flex cursor-pointer items-start gap-3 border-2 p-3 transition-colors ${
|
||||||
<p className="mt-1 text-sm text-muted-foreground">
|
scenario.distribution_mode === option.value
|
||||||
How income is divided across buckets within each
|
? 'border-red-500 bg-red-500/10'
|
||||||
phase
|
: 'border-red-500/30 hover:border-red-500/60'
|
||||||
</p>
|
}`}
|
||||||
<div className="mt-3 space-y-2">
|
>
|
||||||
{distributionOptions.map((option) => (
|
<input
|
||||||
<label
|
type="radio"
|
||||||
key={option.value}
|
name="distribution_mode"
|
||||||
className={`flex cursor-pointer items-start gap-3 rounded-lg border p-3 transition-colors ${
|
value={option.value}
|
||||||
scenario.distribution_mode ===
|
checked={scenario.distribution_mode === option.value}
|
||||||
option.value
|
onChange={(e) =>
|
||||||
? 'border-primary bg-primary/5'
|
handleDistributionModeChange(e.target.value as DistributionMode)
|
||||||
: 'border-border hover:border-primary/50'
|
}
|
||||||
}`}
|
className="mt-0.5 accent-red-500"
|
||||||
>
|
/>
|
||||||
<input
|
<div>
|
||||||
type="radio"
|
<div className="text-sm font-mono font-bold text-red-500">
|
||||||
name="distribution_mode"
|
{option.label}
|
||||||
value={option.value}
|
</div>
|
||||||
checked={
|
<div className="text-xs font-mono text-red-500/60">
|
||||||
scenario.distribution_mode ===
|
{option.description}
|
||||||
option.value
|
</div>
|
||||||
}
|
</div>
|
||||||
onChange={(e) =>
|
</label>
|
||||||
handleDistributionModeChange(
|
))}
|
||||||
e.target.value as DistributionMode,
|
|
||||||
)
|
|
||||||
}
|
|
||||||
className="mt-0.5"
|
|
||||||
/>
|
|
||||||
<div>
|
|
||||||
<div className="text-sm font-medium">
|
|
||||||
{option.label}
|
|
||||||
</div>
|
|
||||||
<div className="text-sm text-muted-foreground">
|
|
||||||
{option.description}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</label>
|
|
||||||
))}
|
|
||||||
</div>
|
|
||||||
</fieldset>
|
|
||||||
</div>
|
</div>
|
||||||
</SheetContent>
|
</fieldset>
|
||||||
</Sheet>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -166,12 +166,12 @@ export default function Show({ scenario, buckets }: Props) {
|
||||||
<div className="min-h-screen bg-background p-8">
|
<div className="min-h-screen bg-background p-8">
|
||||||
<div className="mx-auto max-w-6xl">
|
<div className="mx-auto max-w-6xl">
|
||||||
{/* Header */}
|
{/* Header */}
|
||||||
<div className="mb-8 flex items-center justify-between">
|
<div className="mb-8 flex items-center justify-between border-b border-red-500/40 pb-4">
|
||||||
<h1 className="text-2xl font-bold font-mono uppercase tracking-wider text-red-500">
|
<h1 className="text-2xl font-bold font-mono uppercase tracking-wider text-red-500">
|
||||||
BUCKETS
|
BUCKETS
|
||||||
</h1>
|
</h1>
|
||||||
<button
|
<button
|
||||||
onClick={() => setIsSettingsOpen(true)}
|
onClick={() => setIsSettingsOpen(!isSettingsOpen)}
|
||||||
className="p-2 text-red-500/60 hover:text-red-500 transition-colors"
|
className="p-2 text-red-500/60 hover:text-red-500 transition-colors"
|
||||||
title="Settings"
|
title="Settings"
|
||||||
>
|
>
|
||||||
|
|
@ -179,7 +179,12 @@ export default function Show({ scenario, buckets }: Props) {
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<SettingsPanel open={isSettingsOpen} onOpenChange={setIsSettingsOpen} />
|
<div
|
||||||
|
className="overflow-hidden transition-all duration-300 ease-in-out"
|
||||||
|
style={{ maxHeight: isSettingsOpen ? '500px' : '0', opacity: isSettingsOpen ? 1 : 0 }}
|
||||||
|
>
|
||||||
|
<SettingsPanel open={isSettingsOpen} onOpenChange={setIsSettingsOpen} />
|
||||||
|
</div>
|
||||||
|
|
||||||
{/* Buckets */}
|
{/* Buckets */}
|
||||||
<div className="space-y-6">
|
<div className="space-y-6">
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue