mirror of
https://github.com/fosrl/pangolin.git
synced 2026-08-12 07:20:43 +02:00
match the budget picker to the rules picker
This commit is contained in:
+161
-209
@@ -1,13 +1,10 @@
|
|||||||
"use client";
|
"use client";
|
||||||
|
|
||||||
import {
|
import {
|
||||||
SettingsFormCell,
|
|
||||||
SettingsFormGrid,
|
|
||||||
SettingsSection,
|
SettingsSection,
|
||||||
SettingsSectionBody,
|
SettingsSectionBody,
|
||||||
SettingsSectionDescription,
|
SettingsSectionDescription,
|
||||||
SettingsSectionFooter,
|
SettingsSectionFooter,
|
||||||
SettingsSectionForm,
|
|
||||||
SettingsSectionHeader,
|
SettingsSectionHeader,
|
||||||
SettingsSectionTitle
|
SettingsSectionTitle
|
||||||
} from "@app/components/Settings";
|
} from "@app/components/Settings";
|
||||||
@@ -281,217 +278,172 @@ export function BudgetsEditor({
|
|||||||
</SettingsSectionHeader>
|
</SettingsSectionHeader>
|
||||||
|
|
||||||
<SettingsSectionBody>
|
<SettingsSectionBody>
|
||||||
<SettingsSectionForm>
|
<div className="space-y-4">
|
||||||
<SettingsFormGrid>
|
<Table>
|
||||||
<SettingsFormCell span="half">
|
<TableHeader>
|
||||||
<div className="space-y-4">
|
<TableRow>
|
||||||
<Table>
|
<TableHead>{t("aiBudgetAmount")}</TableHead>
|
||||||
<TableHeader>
|
<TableHead>{t("aiBudgetUnit")}</TableHead>
|
||||||
<TableRow>
|
<TableHead>{t("aiBudgetPeriod")}</TableHead>
|
||||||
<TableHead>
|
<TableHead></TableHead>
|
||||||
{t("aiBudgetUnit")}
|
</TableRow>
|
||||||
</TableHead>
|
</TableHeader>
|
||||||
<TableHead>
|
<TableBody>
|
||||||
{t("aiBudgetPeriod")}
|
{rows.length === 0 ? (
|
||||||
</TableHead>
|
<DataTableEmptyState
|
||||||
<TableHead>
|
colSpan={4}
|
||||||
{t("aiBudgetAmount")}
|
message={t("aiBudgetEmpty")}
|
||||||
</TableHead>
|
action={addRowButton}
|
||||||
<TableHead></TableHead>
|
compact
|
||||||
</TableRow>
|
/>
|
||||||
</TableHeader>
|
) : (
|
||||||
<TableBody>
|
rows.map((row) => {
|
||||||
{rows.length === 0 ? (
|
const showConflict = conflictingKeys.has(
|
||||||
<DataTableEmptyState
|
row.key
|
||||||
colSpan={4}
|
);
|
||||||
message={t("aiBudgetEmpty")}
|
const showInvalidAmount =
|
||||||
action={addRowButton}
|
attemptedSave &&
|
||||||
compact
|
invalidAmountKeys.has(row.key);
|
||||||
/>
|
return (
|
||||||
) : (
|
<TableRow key={row.key}>
|
||||||
rows.map((row) => {
|
<TableCell>
|
||||||
const showConflict =
|
<Input
|
||||||
conflictingKeys.has(
|
type="number"
|
||||||
row.key
|
min="0"
|
||||||
);
|
step="any"
|
||||||
const showInvalidAmount =
|
placeholder={t(
|
||||||
attemptedSave &&
|
"aiBudgetAmountPlaceholder"
|
||||||
invalidAmountKeys.has(
|
)}
|
||||||
row.key
|
value={row.amount}
|
||||||
);
|
aria-invalid={
|
||||||
return (
|
showInvalidAmount
|
||||||
<TableRow key={row.key}>
|
}
|
||||||
<TableCell>
|
disabled={
|
||||||
<Select
|
saveLoading ||
|
||||||
value={row.unit}
|
budgetsQuery.isLoading
|
||||||
onValueChange={(
|
}
|
||||||
value
|
onChange={(e) =>
|
||||||
) =>
|
updateRow(row.key, {
|
||||||
updateRow(
|
amount: e.target
|
||||||
row.key,
|
.value
|
||||||
{
|
})
|
||||||
unit: value as AiBudgetUnit
|
}
|
||||||
}
|
className="w-full min-w-0"
|
||||||
)
|
/>
|
||||||
}
|
</TableCell>
|
||||||
disabled={
|
<TableCell>
|
||||||
saveLoading ||
|
<Select
|
||||||
budgetsQuery.isLoading
|
value={row.unit}
|
||||||
}
|
onValueChange={(value) =>
|
||||||
>
|
updateRow(row.key, {
|
||||||
<SelectTrigger
|
unit: value as AiBudgetUnit
|
||||||
className="w-full min-w-0"
|
})
|
||||||
aria-invalid={
|
}
|
||||||
showConflict
|
disabled={
|
||||||
}
|
saveLoading ||
|
||||||
|
budgetsQuery.isLoading
|
||||||
|
}
|
||||||
|
>
|
||||||
|
<SelectTrigger
|
||||||
|
className="w-full min-w-0"
|
||||||
|
aria-invalid={
|
||||||
|
showConflict
|
||||||
|
}
|
||||||
|
>
|
||||||
|
<SelectValue />
|
||||||
|
</SelectTrigger>
|
||||||
|
<SelectContent>
|
||||||
|
{AI_BUDGET_UNITS.map(
|
||||||
|
(unit) => (
|
||||||
|
<SelectItem
|
||||||
|
key={unit}
|
||||||
|
value={unit}
|
||||||
>
|
>
|
||||||
<SelectValue />
|
{
|
||||||
</SelectTrigger>
|
unitLabels[
|
||||||
<SelectContent>
|
|
||||||
{AI_BUDGET_UNITS.map(
|
|
||||||
(
|
|
||||||
unit
|
unit
|
||||||
) => (
|
]
|
||||||
<SelectItem
|
}
|
||||||
key={
|
</SelectItem>
|
||||||
unit
|
)
|
||||||
}
|
)}
|
||||||
value={
|
</SelectContent>
|
||||||
unit
|
</Select>
|
||||||
}
|
</TableCell>
|
||||||
>
|
<TableCell>
|
||||||
{
|
<Select
|
||||||
unitLabels[
|
value={row.period}
|
||||||
unit
|
onValueChange={(value) =>
|
||||||
]
|
updateRow(row.key, {
|
||||||
}
|
period: value as AiBudgetPeriod
|
||||||
</SelectItem>
|
})
|
||||||
)
|
}
|
||||||
)}
|
disabled={
|
||||||
</SelectContent>
|
saveLoading ||
|
||||||
</Select>
|
budgetsQuery.isLoading
|
||||||
</TableCell>
|
}
|
||||||
<TableCell>
|
>
|
||||||
<Select
|
<SelectTrigger
|
||||||
value={
|
className="w-full min-w-0"
|
||||||
row.period
|
aria-invalid={
|
||||||
}
|
showConflict
|
||||||
onValueChange={(
|
}
|
||||||
value
|
>
|
||||||
) =>
|
<SelectValue />
|
||||||
updateRow(
|
</SelectTrigger>
|
||||||
row.key,
|
<SelectContent>
|
||||||
{
|
{AI_BUDGET_PERIODS.map(
|
||||||
period: value as AiBudgetPeriod
|
(period) => (
|
||||||
}
|
<SelectItem
|
||||||
)
|
key={period}
|
||||||
}
|
value={
|
||||||
disabled={
|
period
|
||||||
saveLoading ||
|
|
||||||
budgetsQuery.isLoading
|
|
||||||
}
|
|
||||||
>
|
|
||||||
<SelectTrigger
|
|
||||||
className="w-full min-w-0"
|
|
||||||
aria-invalid={
|
|
||||||
showConflict
|
|
||||||
}
|
}
|
||||||
>
|
>
|
||||||
<SelectValue />
|
{
|
||||||
</SelectTrigger>
|
periodLabels[
|
||||||
<SelectContent>
|
|
||||||
{AI_BUDGET_PERIODS.map(
|
|
||||||
(
|
|
||||||
period
|
period
|
||||||
) => (
|
]
|
||||||
<SelectItem
|
}
|
||||||
key={
|
</SelectItem>
|
||||||
period
|
)
|
||||||
}
|
)}
|
||||||
value={
|
</SelectContent>
|
||||||
period
|
</Select>
|
||||||
}
|
</TableCell>
|
||||||
>
|
<TableCell>
|
||||||
{
|
<div className="flex items-center justify-end space-x-2">
|
||||||
periodLabels[
|
<Button
|
||||||
period
|
type="button"
|
||||||
]
|
variant="outline"
|
||||||
}
|
disabled={
|
||||||
</SelectItem>
|
saveLoading ||
|
||||||
)
|
budgetsQuery.isLoading
|
||||||
)}
|
}
|
||||||
</SelectContent>
|
onClick={() =>
|
||||||
</Select>
|
removeRow(row.key)
|
||||||
</TableCell>
|
}
|
||||||
<TableCell>
|
>
|
||||||
<Input
|
Delete
|
||||||
type="number"
|
</Button>
|
||||||
min="0"
|
</div>
|
||||||
step="any"
|
</TableCell>
|
||||||
placeholder={t(
|
</TableRow>
|
||||||
"aiBudgetAmountPlaceholder"
|
);
|
||||||
)}
|
})
|
||||||
value={
|
)}
|
||||||
row.amount
|
</TableBody>
|
||||||
}
|
</Table>
|
||||||
aria-invalid={
|
{(conflictingKeys.size > 0 ||
|
||||||
showInvalidAmount
|
(attemptedSave && invalidAmountKeys.size > 0)) && (
|
||||||
}
|
<p className="text-xs text-destructive">
|
||||||
disabled={
|
{conflictingKeys.size > 0
|
||||||
saveLoading ||
|
? t("aiBudgetConflictError")
|
||||||
budgetsQuery.isLoading
|
: t("aiBudgetInvalidAmountError")}
|
||||||
}
|
</p>
|
||||||
onChange={(e) =>
|
)}
|
||||||
updateRow(
|
{rows.length > 0 && addRowButton}
|
||||||
row.key,
|
</div>
|
||||||
{
|
|
||||||
amount: e
|
|
||||||
.target
|
|
||||||
.value
|
|
||||||
}
|
|
||||||
)
|
|
||||||
}
|
|
||||||
className="w-full min-w-0"
|
|
||||||
/>
|
|
||||||
</TableCell>
|
|
||||||
<TableCell>
|
|
||||||
<Button
|
|
||||||
type="button"
|
|
||||||
variant="ghost"
|
|
||||||
size="icon"
|
|
||||||
disabled={
|
|
||||||
saveLoading ||
|
|
||||||
budgetsQuery.isLoading
|
|
||||||
}
|
|
||||||
onClick={() =>
|
|
||||||
removeRow(
|
|
||||||
row.key
|
|
||||||
)
|
|
||||||
}
|
|
||||||
>
|
|
||||||
<Trash2 className="h-4 w-4 text-destructive" />
|
|
||||||
</Button>
|
|
||||||
</TableCell>
|
|
||||||
</TableRow>
|
|
||||||
);
|
|
||||||
})
|
|
||||||
)}
|
|
||||||
</TableBody>
|
|
||||||
</Table>
|
|
||||||
{(conflictingKeys.size > 0 ||
|
|
||||||
(attemptedSave &&
|
|
||||||
invalidAmountKeys.size > 0)) && (
|
|
||||||
<p className="text-xs text-destructive">
|
|
||||||
{conflictingKeys.size > 0
|
|
||||||
? t("aiBudgetConflictError")
|
|
||||||
: t("aiBudgetInvalidAmountError")}
|
|
||||||
</p>
|
|
||||||
)}
|
|
||||||
{rows.length > 0 && addRowButton}
|
|
||||||
</div>
|
|
||||||
</SettingsFormCell>
|
|
||||||
</SettingsFormGrid>
|
|
||||||
</SettingsSectionForm>
|
|
||||||
</SettingsSectionBody>
|
</SettingsSectionBody>
|
||||||
|
|
||||||
<SettingsSectionFooter>
|
<SettingsSectionFooter>
|
||||||
|
|||||||
Reference in New Issue
Block a user