Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 21 additions & 0 deletions messages/ja/dashboard.json
Original file line number Diff line number Diff line change
Expand Up @@ -512,6 +512,27 @@
"placeholder": "空白の場合は無制限",
"description": "5時間以内の最大消費金額"
},
"limitDailyUsd": {
"label": "1日の消費上限 (USD)",
"placeholder": "空白の場合は無制限",
"description": "1日あたりの最大消費金額"
},
"dailyResetMode": {
"label": "毎日リセットモード",
"options": {
"fixed": "固定時間リセット",
"rolling": "ローリングウィンドウ (24時間)"
},
"desc": {
"fixed": "毎日指定された時間にクォータをリセット",
"rolling": "最初のリクエストから24時間のローリングウィンドウ"
}
},
"dailyResetTime": {
"label": "毎日リセット時間",
"placeholder": "HH:mm",
"description": "1日の制限がリセットされる時間 (システムタイムゾーンを使用)"
},
"limitWeeklyUsd": {
"label": "週間消費上限 (USD)",
"placeholder": "空白の場合は無制限",
Expand Down
21 changes: 21 additions & 0 deletions messages/ru/dashboard.json
Original file line number Diff line number Diff line change
Expand Up @@ -511,6 +511,27 @@
"placeholder": "Оставьте пустым для неограниченного",
"description": "Максимальный расход в течение 5 часов"
},
"limitDailyUsd": {
"label": "Дневной лимит расходов (USD)",
"placeholder": "Оставьте пустым для неограниченного",
"description": "Максимальный расход в день"
},
"dailyResetMode": {
"label": "Режим ежедневного сброса",
"options": {
"fixed": "Сброс в фиксированное время",
"rolling": "Скользящее окно (24 часа)"
},
"desc": {
"fixed": "Сброс квоты в определенное время каждый день",
"rolling": "24-часовое скользящее окно от первого запроса"
}
},
"dailyResetTime": {
"label": "Время ежедневного сброса",
"placeholder": "HH:mm",
"description": "Когда сбрасывается дневной лимит (использует системный часовой пояс)"
},
"limitWeeklyUsd": {
"label": "Недельный лимит расходов (USD)",
"placeholder": "Оставьте пустым для неограниченного",
Expand Down
21 changes: 21 additions & 0 deletions messages/zh-TW/dashboard.json
Original file line number Diff line number Diff line change
Expand Up @@ -513,6 +513,27 @@
"placeholder": "留空表示無限制",
"description": "5小時內最大消費金額"
},
"limitDailyUsd": {
"label": "每日消費上限 (USD)",
"placeholder": "留空表示無限制",
"description": "每日最大消費金額"
},
"dailyResetMode": {
"label": "每日重設模式",
"options": {
"fixed": "固定時間重設",
"rolling": "滾動視窗(24小時)"
},
"desc": {
"fixed": "每天在指定時間重設額度",
"rolling": "從首次請求開始計算24小時滾動視窗"
}
},
"dailyResetTime": {
"label": "每日重設時間",
"placeholder": "HH:mm",
"description": "每日限額的重設時間(使用系統時區)"
},
"limitWeeklyUsd": {
"label": "週消費上限 (USD)",
"placeholder": "留空表示無限制",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ export function AddUserDialog({
<ListPlus className="h-4 w-4" /> {t("addUser")}
</Button>
</DialogTrigger>
<DialogContent className="max-h-[85vh] flex flex-col">
<DialogContent className="max-h-[85vh] flex flex-col overflow-hidden">
<FormErrorBoundary>
<UserForm onSuccess={() => setOpen(false)} currentUser={currentUser} />
</FormErrorBoundary>
Expand Down
64 changes: 33 additions & 31 deletions src/app/[locale]/dashboard/_components/user/forms/add-key-form.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -155,38 +155,40 @@ export function AddKeyForm({ userId, user, onSuccess }: AddKeyFormProps) {
/>
</FormGrid>

<div className="space-y-2">
<Label htmlFor="daily-reset-mode">{t("dailyResetMode.label")}</Label>
<Select
value={form.values.dailyResetMode}
onValueChange={(value: "fixed" | "rolling") => form.setValue("dailyResetMode", value)}
disabled={isPending}
>
<SelectTrigger id="daily-reset-mode">
<SelectValue />
</SelectTrigger>
<SelectContent>
<SelectItem value="fixed">{t("dailyResetMode.options.fixed")}</SelectItem>
<SelectItem value="rolling">{t("dailyResetMode.options.rolling")}</SelectItem>
</SelectContent>
</Select>
<p className="text-xs text-muted-foreground">
{form.values.dailyResetMode === "fixed"
? t("dailyResetMode.desc.fixed")
: t("dailyResetMode.desc.rolling")}
</p>
</div>
<FormGrid columns={2}>
Copy link
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Medium: Empty column in 2-column grid when dailyResetMode is "rolling"

Why this is a problem: When the dailyResetMode is set to "rolling", the dailyResetTime field is not rendered, leaving the second column of the FormGrid empty. This creates an unbalanced layout with visible empty space on the right side.

Suggested fix:

<FormGrid columns={form.values.dailyResetMode === "fixed" ? 2 : 1}>
  <div className="space-y-2">
    <Label htmlFor="daily-reset-mode">{t("dailyResetMode.label")}</Label>
    <Select
      value={form.values.dailyResetMode}
      onValueChange={(value: "fixed" | "rolling") => form.setValue("dailyResetMode", value)}
      disabled={isPending}
    >
      <SelectTrigger id="daily-reset-mode">
        <SelectValue />
      </SelectTrigger>
      <SelectContent>
        <SelectItem value="fixed">{t("dailyResetMode.options.fixed")}</SelectItem>
        <SelectItem value="rolling">{t("dailyResetMode.options.rolling")}</SelectItem>
      </SelectContent>
    </Select>
    <p className="text-xs text-muted-foreground">
      {form.values.dailyResetMode === "fixed"
        ? t("dailyResetMode.desc.fixed")
        : t("dailyResetMode.desc.rolling")}
    </p>
  </div>

  {form.values.dailyResetMode === "fixed" && (
    <TextField
      label={t("dailyResetTime.label")}
      placeholder={t("dailyResetTime.placeholder")}
      description={t("dailyResetTime.description")}
      type="time"
      step={60}
      {...form.getFieldProps("dailyResetTime")}
    />
  )}
</FormGrid>

<div className="space-y-2">
<Label htmlFor="daily-reset-mode">{t("dailyResetMode.label")}</Label>
<Select
value={form.values.dailyResetMode}
onValueChange={(value: "fixed" | "rolling") => form.setValue("dailyResetMode", value)}
disabled={isPending}
>
<SelectTrigger id="daily-reset-mode">
<SelectValue />
</SelectTrigger>
<SelectContent>
<SelectItem value="fixed">{t("dailyResetMode.options.fixed")}</SelectItem>
<SelectItem value="rolling">{t("dailyResetMode.options.rolling")}</SelectItem>
</SelectContent>
</Select>
<p className="text-xs text-muted-foreground">
{form.values.dailyResetMode === "fixed"
? t("dailyResetMode.desc.fixed")
: t("dailyResetMode.desc.rolling")}
</p>
</div>

{form.values.dailyResetMode === "fixed" && (
<TextField
label={t("dailyResetTime.label")}
placeholder={t("dailyResetTime.placeholder")}
description={t("dailyResetTime.description")}
type="time"
step={60}
{...form.getFieldProps("dailyResetTime")}
/>
)}
{form.values.dailyResetMode === "fixed" && (
<TextField
label={t("dailyResetTime.label")}
placeholder={t("dailyResetTime.placeholder")}
description={t("dailyResetTime.description")}
type="time"
step={60}
{...form.getFieldProps("dailyResetTime")}
/>
)}
</FormGrid>

<FormGrid columns={2}>
<NumberField
Expand Down
64 changes: 33 additions & 31 deletions src/app/[locale]/dashboard/_components/user/forms/edit-key-form.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -166,38 +166,40 @@ export function EditKeyForm({ keyData, user, onSuccess }: EditKeyFormProps) {
/>
</FormGrid>

<div className="space-y-2">
<Label htmlFor="daily-reset-mode">{t("dailyResetMode.label")}</Label>
<Select
value={form.values.dailyResetMode}
onValueChange={(value: "fixed" | "rolling") => form.setValue("dailyResetMode", value)}
disabled={isPending}
>
<SelectTrigger id="daily-reset-mode">
<SelectValue />
</SelectTrigger>
<SelectContent>
<SelectItem value="fixed">{t("dailyResetMode.options.fixed")}</SelectItem>
<SelectItem value="rolling">{t("dailyResetMode.options.rolling")}</SelectItem>
</SelectContent>
</Select>
<p className="text-xs text-muted-foreground">
{form.values.dailyResetMode === "fixed"
? t("dailyResetMode.desc.fixed")
: t("dailyResetMode.desc.rolling")}
</p>
</div>
<FormGrid columns={2}>
Copy link
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Medium: Empty column in 2-column grid when dailyResetMode is "rolling"

Why this is a problem: Same issue as in add-key-form.tsx - when dailyResetMode is "rolling", the second column is empty, creating an unbalanced layout.

Suggested fix:

<FormGrid columns={form.values.dailyResetMode === "fixed" ? 2 : 1}>

Dynamically set the number of columns based on whether the time field will be shown.

<div className="space-y-2">
<Label htmlFor="daily-reset-mode">{t("dailyResetMode.label")}</Label>
<Select
value={form.values.dailyResetMode}
onValueChange={(value: "fixed" | "rolling") => form.setValue("dailyResetMode", value)}
disabled={isPending}
>
<SelectTrigger id="daily-reset-mode">
<SelectValue />
</SelectTrigger>
<SelectContent>
<SelectItem value="fixed">{t("dailyResetMode.options.fixed")}</SelectItem>
<SelectItem value="rolling">{t("dailyResetMode.options.rolling")}</SelectItem>
</SelectContent>
</Select>
<p className="text-xs text-muted-foreground">
{form.values.dailyResetMode === "fixed"
? t("dailyResetMode.desc.fixed")
: t("dailyResetMode.desc.rolling")}
</p>
</div>

{form.values.dailyResetMode === "fixed" && (
<TextField
label={t("dailyResetTime.label")}
placeholder={t("dailyResetTime.placeholder")}
description={t("dailyResetTime.description")}
type="time"
step={60}
{...form.getFieldProps("dailyResetTime")}
/>
)}
{form.values.dailyResetMode === "fixed" && (
<TextField
label={t("dailyResetTime.label")}
placeholder={t("dailyResetTime.placeholder")}
description={t("dailyResetTime.description")}
type="time"
step={60}
{...form.getFieldProps("dailyResetTime")}
/>
)}
</FormGrid>

<FormGrid columns={2}>
<NumberField
Expand Down
4 changes: 2 additions & 2 deletions src/app/[locale]/dashboard/_components/user/key-actions.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ export function KeyActions({
<SquarePen className="h-4 w-4" />
</button>
</DialogTrigger>
<DialogContent>
<DialogContent className="max-h-[80vh] flex flex-col overflow-hidden">
<FormErrorBoundary>
<EditKeyForm
keyData={keyData}
Expand All @@ -75,7 +75,7 @@ export function KeyActions({
<Trash2 className="h-4 w-4" />
</button>
</DialogTrigger>
<DialogContent>
<DialogContent className="max-h-[80vh] flex flex-col overflow-hidden">
<FormErrorBoundary>
<DeleteKeyConfirm keyData={keyData} onSuccess={() => setOpenDelete(false)} />
</FormErrorBoundary>
Expand Down
24 changes: 13 additions & 11 deletions src/app/[locale]/dashboard/_components/user/user-list.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -70,17 +70,19 @@ export function UserList({ users, activeUserId, onUserSelect, currentUser }: Use
: undefined
}
>
<div className="space-y-2">
{listItems.map((item) => (
<ListItem
key={item.id}
data={item}
isActive={item.id === activeUserId}
onClick={() => onUserSelect(item.id as number)}
compact
/>
))}
</div>
{users.length > 0 ? (
<div className="space-y-2">
{listItems.map((item) => (
<ListItem
key={item.id}
data={item}
isActive={item.id === activeUserId}
onClick={() => onUserSelect(item.id as number)}
compact
/>
))}
</div>
) : null}
</ListContainer>
</div>
);
Expand Down
Loading