forked from git.gladyson/openmonetis
feat: adição de novos ícones SVG e configuração do ambiente
- Adicionados ícones SVG para ChatGPT, Claude, Gemini e OpenRouter - Implementados ícones para modos claro e escuro do ChatGPT - Criado script de inicialização para PostgreSQL com extensão pgcrypto - Adicionado script de configuração de ambiente que faz backup do .env - Configurado tsconfig.json para TypeScript com opções de compilação
This commit is contained in:
214
components/cartoes/card-form-fields.tsx
Normal file
214
components/cartoes/card-form-fields.tsx
Normal file
@@ -0,0 +1,214 @@
|
||||
"use client";
|
||||
|
||||
import { CurrencyInput } from "@/components/ui/currency-input";
|
||||
import { Input } from "@/components/ui/input";
|
||||
import { Label } from "@/components/ui/label";
|
||||
import {
|
||||
Select,
|
||||
SelectContent,
|
||||
SelectItem,
|
||||
SelectTrigger,
|
||||
SelectValue,
|
||||
} from "@/components/ui/select";
|
||||
import { Textarea } from "@/components/ui/textarea";
|
||||
import {
|
||||
DAYS_IN_MONTH,
|
||||
DEFAULT_CARD_BRANDS,
|
||||
DEFAULT_CARD_STATUS,
|
||||
} from "./constants";
|
||||
import type { CardFormValues } from "./types";
|
||||
import {
|
||||
BrandSelectContent,
|
||||
StatusSelectContent,
|
||||
AccountSelectContent,
|
||||
} from "./card-select-items";
|
||||
|
||||
interface AccountOption {
|
||||
id: string;
|
||||
name: string;
|
||||
logo: string | null;
|
||||
}
|
||||
|
||||
interface CardFormFieldsProps {
|
||||
values: CardFormValues;
|
||||
accountOptions: AccountOption[];
|
||||
onChange: (field: keyof CardFormValues, value: string) => void;
|
||||
}
|
||||
|
||||
const ensureOption = (options: string[], value: string) => {
|
||||
if (!value) {
|
||||
return options;
|
||||
}
|
||||
return options.includes(value) ? options : [value, ...options];
|
||||
};
|
||||
|
||||
export function CardFormFields({
|
||||
values,
|
||||
accountOptions,
|
||||
onChange,
|
||||
}: CardFormFieldsProps) {
|
||||
const brands = ensureOption(
|
||||
DEFAULT_CARD_BRANDS as unknown as string[],
|
||||
values.brand
|
||||
);
|
||||
const statuses = ensureOption(
|
||||
DEFAULT_CARD_STATUS as unknown as string[],
|
||||
values.status
|
||||
);
|
||||
|
||||
return (
|
||||
<div className="grid grid-cols-1 gap-4 sm:grid-cols-2">
|
||||
<div className="flex flex-col gap-2">
|
||||
<Label htmlFor="card-name">Nome do cartão</Label>
|
||||
<Input
|
||||
id="card-name"
|
||||
value={values.name}
|
||||
onChange={(event) => onChange("name", event.target.value)}
|
||||
placeholder="Ex.: Nubank Platinum"
|
||||
required
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div className="flex flex-col gap-2">
|
||||
<Label htmlFor="card-brand">Bandeira</Label>
|
||||
<Select
|
||||
value={values.brand}
|
||||
onValueChange={(value) => onChange("brand", value)}
|
||||
>
|
||||
<SelectTrigger id="card-brand" className="w-full">
|
||||
<SelectValue placeholder="Selecione a bandeira">
|
||||
{values.brand && <BrandSelectContent label={values.brand} />}
|
||||
</SelectValue>
|
||||
</SelectTrigger>
|
||||
<SelectContent>
|
||||
{brands.map((brand) => (
|
||||
<SelectItem key={brand} value={brand}>
|
||||
<BrandSelectContent label={brand} />
|
||||
</SelectItem>
|
||||
))}
|
||||
</SelectContent>
|
||||
</Select>
|
||||
</div>
|
||||
|
||||
<div className="flex flex-col gap-2">
|
||||
<Label htmlFor="card-status">Status</Label>
|
||||
<Select
|
||||
value={values.status}
|
||||
onValueChange={(value) => onChange("status", value)}
|
||||
>
|
||||
<SelectTrigger id="card-status" className="w-full">
|
||||
<SelectValue placeholder="Selecione o status">
|
||||
{values.status && <StatusSelectContent label={values.status} />}
|
||||
</SelectValue>
|
||||
</SelectTrigger>
|
||||
<SelectContent>
|
||||
{statuses.map((status) => (
|
||||
<SelectItem key={status} value={status}>
|
||||
<StatusSelectContent label={status} />
|
||||
</SelectItem>
|
||||
))}
|
||||
</SelectContent>
|
||||
</Select>
|
||||
</div>
|
||||
|
||||
<div className="flex flex-col gap-2">
|
||||
<Label htmlFor="card-limit">Limite (R$)</Label>
|
||||
<CurrencyInput
|
||||
id="card-limit"
|
||||
value={values.limit}
|
||||
onValueChange={(value) => onChange("limit", value)}
|
||||
placeholder="R$ 0,00"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div className="flex flex-col gap-2">
|
||||
<Label htmlFor="card-closing-day">Dia de fechamento</Label>
|
||||
<Select
|
||||
value={values.closingDay}
|
||||
onValueChange={(value) => onChange("closingDay", value)}
|
||||
>
|
||||
<SelectTrigger id="card-closing-day" className="w-full">
|
||||
<SelectValue placeholder="Dia de fechamento" />
|
||||
</SelectTrigger>
|
||||
<SelectContent>
|
||||
{DAYS_IN_MONTH.map((day) => (
|
||||
<SelectItem key={day} value={day}>
|
||||
Dia {day}
|
||||
</SelectItem>
|
||||
))}
|
||||
</SelectContent>
|
||||
</Select>
|
||||
</div>
|
||||
|
||||
<div className="flex flex-col gap-2">
|
||||
<Label htmlFor="card-due-day">Dia de vencimento</Label>
|
||||
<Select
|
||||
value={values.dueDay}
|
||||
onValueChange={(value) => onChange("dueDay", value)}
|
||||
>
|
||||
<SelectTrigger id="card-due-day" className="w-full">
|
||||
<SelectValue placeholder="Dia de vencimento" />
|
||||
</SelectTrigger>
|
||||
<SelectContent>
|
||||
{DAYS_IN_MONTH.map((day) => (
|
||||
<SelectItem key={day} value={day}>
|
||||
Dia {day}
|
||||
</SelectItem>
|
||||
))}
|
||||
</SelectContent>
|
||||
</Select>
|
||||
</div>
|
||||
|
||||
<div className="flex flex-col gap-2 sm:col-span-2">
|
||||
<Label htmlFor="card-account">Conta vinculada</Label>
|
||||
<Select
|
||||
value={values.contaId}
|
||||
onValueChange={(value) => onChange("contaId", value)}
|
||||
disabled={accountOptions.length === 0}
|
||||
>
|
||||
<SelectTrigger id="card-account" className="w-full">
|
||||
<SelectValue
|
||||
placeholder={
|
||||
accountOptions.length === 0
|
||||
? "Cadastre uma conta primeiro"
|
||||
: "Selecione a conta"
|
||||
}
|
||||
>
|
||||
{values.contaId && (() => {
|
||||
const selectedAccount = accountOptions.find(
|
||||
(acc) => acc.id === values.contaId
|
||||
);
|
||||
return selectedAccount ? (
|
||||
<AccountSelectContent
|
||||
label={selectedAccount.name}
|
||||
logo={selectedAccount.logo}
|
||||
/>
|
||||
) : null;
|
||||
})()}
|
||||
</SelectValue>
|
||||
</SelectTrigger>
|
||||
<SelectContent>
|
||||
{accountOptions.map((account) => (
|
||||
<SelectItem key={account.id} value={account.id}>
|
||||
<AccountSelectContent
|
||||
label={account.name}
|
||||
logo={account.logo}
|
||||
/>
|
||||
</SelectItem>
|
||||
))}
|
||||
</SelectContent>
|
||||
</Select>
|
||||
</div>
|
||||
|
||||
<div className="flex flex-col gap-2 sm:col-span-2">
|
||||
<Label htmlFor="card-note">Anotação</Label>
|
||||
<Textarea
|
||||
id="card-note"
|
||||
value={values.note}
|
||||
onChange={(event) => onChange("note", event.target.value)}
|
||||
placeholder="Observações sobre este cartão"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user