feat: storage and token limiting

This commit is contained in:
Vasily Zubarev
2025-04-21 13:50:45 +02:00
parent 62bad46e58
commit 73e83221b8
25 changed files with 232 additions and 65 deletions

View File

@@ -17,7 +17,12 @@ export const FormSelectCurrency = ({
hideIfEmpty?: boolean
} & SelectProps) => {
const items = useMemo(
() => currencies.map((currency) => ({ code: currency.code, name: `${currency.code} - ${currency.name}` })),
() =>
currencies.map((currency) => ({
code: currency.code,
name: `${currency.code}`,
badge: currency.name,
})),
[currencies]
)
return (

View File

@@ -9,10 +9,10 @@ export const FormSelectType = ({
...props
}: { title: string; emptyValue?: string; placeholder?: string; hideIfEmpty?: boolean } & SelectProps) => {
const items = [
{ code: "expense", name: "Expense" },
{ code: "income", name: "Income" },
{ code: "pending", name: "Pending" },
{ code: "other", name: "Other" },
{ code: "expense", name: "Expense", badge: "↓" },
{ code: "income", name: "Income", badge: "↑" },
{ code: "pending", name: "Pending", badge: "⏲︎" },
{ code: "other", name: "Other", badge: "?" },
]
return (

View File

@@ -1,5 +1,6 @@
"use client"
import { Badge } from "@/components/ui/badge"
import { Button } from "@/components/ui/button"
import { Calendar } from "@/components/ui/calendar"
import { Input } from "@/components/ui/input"
@@ -57,7 +58,7 @@ export const FormSelect = ({
...props
}: {
title: string
items: Array<{ code: string; name: string; color?: string }>
items: Array<{ code: string; name: string; color?: string; badge?: string }>
emptyValue?: string
placeholder?: string
hideIfEmpty?: boolean
@@ -78,7 +79,10 @@ export const FormSelect = ({
{items.map((item) => (
<SelectItem key={item.code} value={item.code}>
<div className="flex items-center gap-2 text-base pr-2">
{item.color && <div className="w-2 h-2 rounded-full" style={{ backgroundColor: item.color }} />}
{item.badge && <Badge className="px-2">{item.badge}</Badge>}
{!item.badge && item.color && (
<div className="w-2 h-2 rounded-full" style={{ backgroundColor: item.color }} />
)}
{item.name}
</div>
</SelectItem>

View File

@@ -1,33 +0,0 @@
"use client"
import { saveProfileAction } from "@/app/(app)/settings/actions"
import { FormError } from "@/components/forms/error"
import { FormInput } from "@/components/forms/simple"
import { Button } from "@/components/ui/button"
import { User } from "@prisma/client"
import { CircleCheckBig } from "lucide-react"
import { useActionState } from "react"
export default function ProfileSettingsForm({ user }: { user: User }) {
const [saveState, saveAction, pending] = useActionState(saveProfileAction, null)
return (
<form action={saveAction} className="space-y-4">
<FormInput title="Your Name" name="name" defaultValue={user.name || ""} />
<div className="flex flex-row items-center gap-4">
<Button type="submit" disabled={pending}>
{pending ? "Saving..." : "Save"}
</Button>
{saveState?.success && (
<p className="text-green-500 flex flex-row items-center gap-2">
<CircleCheckBig />
Saved!
</p>
)}
</div>
{saveState?.error && <FormError>{saveState.error}</FormError>}
</form>
)
}

View File

@@ -0,0 +1,44 @@
"use client"
import { saveProfileAction } from "@/app/(app)/settings/actions"
import { FormError } from "@/components/forms/error"
import { FormInput } from "@/components/forms/simple"
import { Button } from "@/components/ui/button"
import { Card } from "@/components/ui/card"
import { formatBytes, formatNumber } from "@/lib/utils"
import { User } from "@prisma/client"
import { CircleCheckBig } from "lucide-react"
import { useActionState } from "react"
export default function ProfileSettingsForm({ user }: { user: User }) {
const [saveState, saveAction, pending] = useActionState(saveProfileAction, null)
return (
<div>
<form action={saveAction} className="space-y-4">
<FormInput title="Your Name" name="name" defaultValue={user.name || ""} />
<div className="flex flex-row items-center gap-4">
<Button type="submit" disabled={pending}>
{pending ? "Saving..." : "Save"}
</Button>
{saveState?.success && (
<p className="text-green-500 flex flex-row items-center gap-2">
<CircleCheckBig />
Saved!
</p>
)}
</div>
{saveState?.error && <FormError>{saveState.error}</FormError>}
</form>
<Card className="mt-4 p-4">
<p>
Storage: {user.storageUsed ? formatBytes(user.storageUsed) : "N/A"} /{" "}
{user.storageLimit && user.storageLimit > 0 ? formatBytes(user.storageLimit) : "Unlimited"}
</p>
<p>Tokens Balance: {user.tokenBalance ? formatNumber(user.tokenBalance) : "N/A"}</p>
</Card>
</div>
)
}

View File

@@ -106,7 +106,7 @@ export default function AnalyzeForm({
setAnalyzeError(results.error ? results.error : "Something went wrong...")
} else {
const nonEmptyFields = Object.fromEntries(
Object.entries(results.data || {}).filter(
Object.entries(results.data?.output || {}).filter(
([_, value]) => value !== null && value !== undefined && value !== ""
)
)