style: padroniza layout do formulário de criação de empresas com o de vagas
This commit is contained in:
parent
a754b4eba8
commit
007a708ffe
1 changed files with 217 additions and 162 deletions
|
|
@ -6,11 +6,11 @@ import { Button } from "@/components/ui/button"
|
||||||
import { Input } from "@/components/ui/input"
|
import { Input } from "@/components/ui/input"
|
||||||
import { Textarea } from "@/components/ui/textarea"
|
import { Textarea } from "@/components/ui/textarea"
|
||||||
import { Label } from "@/components/ui/label"
|
import { Label } from "@/components/ui/label"
|
||||||
import { Loader2, Eye, EyeOff, ArrowLeft } from "lucide-react"
|
import { Loader2, Eye, EyeOff, ArrowLeft, Building2 } from "lucide-react"
|
||||||
import { adminCompaniesApi } from "@/lib/api"
|
import { adminCompaniesApi } from "@/lib/api"
|
||||||
import { toast } from "sonner"
|
import { toast } from "sonner"
|
||||||
import { useTranslation } from "@/lib/i18n"
|
import { useTranslation } from "@/lib/i18n"
|
||||||
import { Card, CardContent } from "@/components/ui/card"
|
import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "@/components/ui/card"
|
||||||
import Link from "next/link"
|
import Link from "next/link"
|
||||||
|
|
||||||
const formatCNPJ = (value: string) => {
|
const formatCNPJ = (value: string) => {
|
||||||
|
|
@ -85,185 +85,240 @@ export default function NewCompanyPage() {
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="space-y-8 max-w-3xl mx-auto">
|
<div className="container max-w-4xl py-10">
|
||||||
<div className="flex items-center gap-4">
|
<div className="mb-8">
|
||||||
<Button variant="ghost" size="icon" asChild>
|
<Button variant="ghost" size="sm" asChild className="mb-4">
|
||||||
<Link href="/dashboard/companies">
|
<Link href="/dashboard/companies" className="flex items-center gap-2">
|
||||||
<ArrowLeft className="h-5 w-5" />
|
<ArrowLeft className="h-4 w-4" />
|
||||||
|
{t('admin.companies.create.backToList', { defaultValue: 'Voltar para lista' })}
|
||||||
</Link>
|
</Link>
|
||||||
</Button>
|
</Button>
|
||||||
<div>
|
|
||||||
<h1 className="text-3xl font-bold text-foreground">{t('admin.companies.create.title')}</h1>
|
|
||||||
<p className="text-muted-foreground mt-1">{t('admin.companies.create.subtitle')}</p>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<Card>
|
<Card className="border-0 shadow-lg">
|
||||||
<CardContent className="pt-6">
|
<CardHeader className="bg-muted/50 pb-8 pt-8">
|
||||||
<div className="grid gap-6">
|
<div className="flex items-center gap-4">
|
||||||
<div className="grid gap-2">
|
<div className="bg-primary/10 p-3 rounded-xl">
|
||||||
<Label htmlFor="name">{t('admin.companies.create.name')}</Label>
|
<Building2 className="h-8 w-8 text-primary" />
|
||||||
<Input
|
|
||||||
id="name"
|
|
||||||
value={formData.name}
|
|
||||||
onChange={(e) =>
|
|
||||||
setFormData({
|
|
||||||
...formData,
|
|
||||||
name: e.target.value,
|
|
||||||
slug: generateSlug(e.target.value),
|
|
||||||
})
|
|
||||||
}
|
|
||||||
placeholder={t('admin.companies.create.namePlaceholder')}
|
|
||||||
/>
|
|
||||||
</div>
|
</div>
|
||||||
<div className="grid gap-2">
|
<div>
|
||||||
<Label htmlFor="slug">{t('admin.companies.create.slug')}</Label>
|
<CardTitle className="text-2xl font-bold">{t('admin.companies.create.title')}</CardTitle>
|
||||||
<Input
|
<CardDescription className="text-base mt-1">
|
||||||
id="slug"
|
{t('admin.companies.create.subtitle')}
|
||||||
value={formData.slug}
|
</CardDescription>
|
||||||
onChange={(e) => setFormData({ ...formData, slug: e.target.value })}
|
|
||||||
placeholder={t('admin.companies.create.slugPlaceholder')}
|
|
||||||
/>
|
|
||||||
</div>
|
</div>
|
||||||
<div className="grid gap-2">
|
</div>
|
||||||
<Label htmlFor="document">{t('admin.companies.fields.document')}</Label>
|
</CardHeader>
|
||||||
<Input
|
<CardContent className="pt-8">
|
||||||
id="document"
|
<div className="grid gap-8">
|
||||||
maxLength={18}
|
{/* Seção: Informações Básicas */}
|
||||||
value={formData.document}
|
<div className="grid gap-4">
|
||||||
onChange={(e) => setFormData({ ...formData, document: formatCNPJ(e.target.value) })}
|
<h3 className="text-lg font-semibold border-b pb-2 flex items-center gap-2">
|
||||||
placeholder="CNPJ / Document"
|
<span className="bg-primary w-1 h-5 rounded-full"></span>
|
||||||
/>
|
{t('admin.companies.sections.basicInfo', { defaultValue: 'Informações Básicas' })}
|
||||||
</div>
|
</h3>
|
||||||
<div className="grid gap-2">
|
<div className="grid grid-cols-1 md:grid-cols-2 gap-4">
|
||||||
<Label htmlFor="email">{t('admin.companies.create.email')}</Label>
|
<div className="grid gap-2">
|
||||||
<Input
|
<Label htmlFor="name">{t('admin.companies.create.name')}</Label>
|
||||||
id="email"
|
|
||||||
type="email"
|
|
||||||
value={formData.email}
|
|
||||||
onChange={(e) => setFormData({ ...formData, email: e.target.value })}
|
|
||||||
placeholder={t('admin.companies.create.emailPlaceholder')}
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
<div className="grid grid-cols-1 md:grid-cols-2 gap-4">
|
|
||||||
<div className="grid gap-2">
|
|
||||||
<Label htmlFor="password">{t('admin.companies.fields.password')}</Label>
|
|
||||||
<div className="relative">
|
|
||||||
<Input
|
<Input
|
||||||
id="password"
|
id="name"
|
||||||
type={showPassword ? "text" : "password"}
|
value={formData.name}
|
||||||
value={formData.password}
|
onChange={(e) =>
|
||||||
onChange={(e) => setFormData({ ...formData, password: e.target.value })}
|
setFormData({
|
||||||
placeholder="******"
|
...formData,
|
||||||
|
name: e.target.value,
|
||||||
|
slug: generateSlug(e.target.value),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
placeholder={t('admin.companies.create.namePlaceholder')}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div className="grid gap-2">
|
||||||
|
<Label htmlFor="slug">{t('admin.companies.create.slug')}</Label>
|
||||||
|
<Input
|
||||||
|
id="slug"
|
||||||
|
value={formData.slug}
|
||||||
|
onChange={(e) => setFormData({ ...formData, slug: e.target.value })}
|
||||||
|
placeholder={t('admin.companies.create.slugPlaceholder')}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div className="grid grid-cols-1 md:grid-cols-2 gap-4">
|
||||||
|
<div className="grid gap-2">
|
||||||
|
<Label htmlFor="document">{t('admin.companies.fields.document')}</Label>
|
||||||
|
<Input
|
||||||
|
id="document"
|
||||||
|
maxLength={18}
|
||||||
|
value={formData.document}
|
||||||
|
onChange={(e) => setFormData({ ...formData, document: formatCNPJ(e.target.value) })}
|
||||||
|
placeholder="CNPJ / Document"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div className="grid gap-2">
|
||||||
|
<Label htmlFor="email">{t('admin.companies.create.email')}</Label>
|
||||||
|
<Input
|
||||||
|
id="email"
|
||||||
|
type="email"
|
||||||
|
value={formData.email}
|
||||||
|
onChange={(e) => setFormData({ ...formData, email: e.target.value })}
|
||||||
|
placeholder={t('admin.companies.create.emailPlaceholder')}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{/* Seção: Segurança */}
|
||||||
|
<div className="grid gap-4">
|
||||||
|
<h3 className="text-lg font-semibold border-b pb-2 flex items-center gap-2">
|
||||||
|
<span className="bg-primary w-1 h-5 rounded-full"></span>
|
||||||
|
{t('admin.companies.sections.security', { defaultValue: 'Segurança' })}
|
||||||
|
</h3>
|
||||||
|
<div className="grid grid-cols-1 md:grid-cols-2 gap-4">
|
||||||
|
<div className="grid gap-2">
|
||||||
|
<Label htmlFor="password">{t('admin.companies.fields.password')}</Label>
|
||||||
|
<div className="relative">
|
||||||
|
<Input
|
||||||
|
id="password"
|
||||||
|
type={showPassword ? "text" : "password"}
|
||||||
|
value={formData.password}
|
||||||
|
onChange={(e) => setFormData({ ...formData, password: e.target.value })}
|
||||||
|
placeholder="******"
|
||||||
|
/>
|
||||||
|
<Button
|
||||||
|
type="button"
|
||||||
|
variant="ghost"
|
||||||
|
size="sm"
|
||||||
|
className="absolute right-0 top-0 h-full px-3 py-2 hover:bg-transparent"
|
||||||
|
onClick={() => setShowPassword(!showPassword)}
|
||||||
|
>
|
||||||
|
{showPassword ? (
|
||||||
|
<EyeOff className="h-4 w-4 text-muted-foreground" />
|
||||||
|
) : (
|
||||||
|
<Eye className="h-4 w-4 text-muted-foreground" />
|
||||||
|
)}
|
||||||
|
</Button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div className="grid gap-2">
|
||||||
|
<Label htmlFor="confirmPassword">{t('admin.companies.fields.confirmPassword')}</Label>
|
||||||
|
<div className="relative">
|
||||||
|
<Input
|
||||||
|
id="confirmPassword"
|
||||||
|
type={showConfirmPassword ? "text" : "password"}
|
||||||
|
value={formData.confirmPassword}
|
||||||
|
onChange={(e) => setFormData({ ...formData, confirmPassword: e.target.value })}
|
||||||
|
placeholder="******"
|
||||||
|
/>
|
||||||
|
<Button
|
||||||
|
type="button"
|
||||||
|
variant="ghost"
|
||||||
|
size="sm"
|
||||||
|
className="absolute right-0 top-0 h-full px-3 py-2 hover:bg-transparent"
|
||||||
|
onClick={() => setShowConfirmPassword(!showConfirmPassword)}
|
||||||
|
>
|
||||||
|
{showConfirmPassword ? (
|
||||||
|
<EyeOff className="h-4 w-4 text-muted-foreground" />
|
||||||
|
) : (
|
||||||
|
<Eye className="h-4 w-4 text-muted-foreground" />
|
||||||
|
)}
|
||||||
|
</Button>
|
||||||
|
</div>
|
||||||
|
{formData.password !== formData.confirmPassword && formData.confirmPassword && (
|
||||||
|
<p className="text-xs text-red-500">{t('admin.companies.fields.passwordsDoNotMatch')}</p>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{/* Seção: Contato e Localização */}
|
||||||
|
<div className="grid gap-4">
|
||||||
|
<h3 className="text-lg font-semibold border-b pb-2 flex items-center gap-2">
|
||||||
|
<span className="bg-primary w-1 h-5 rounded-full"></span>
|
||||||
|
{t('admin.companies.sections.contact', { defaultValue: 'Contato e Localização' })}
|
||||||
|
</h3>
|
||||||
|
<div className="grid grid-cols-1 md:grid-cols-2 gap-4">
|
||||||
|
<div className="grid gap-2">
|
||||||
|
<Label htmlFor="phone">{t('admin.companies.fields.phone')}</Label>
|
||||||
|
<Input
|
||||||
|
id="phone"
|
||||||
|
maxLength={15}
|
||||||
|
value={formData.phone}
|
||||||
|
onChange={(e) => setFormData({ ...formData, phone: formatPhone(e.target.value) })}
|
||||||
|
placeholder="(99) 99999-9999"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div className="grid gap-2">
|
||||||
|
<Label htmlFor="website">{t('admin.companies.fields.website')}</Label>
|
||||||
|
<Input
|
||||||
|
id="website"
|
||||||
|
value={formData.website}
|
||||||
|
onChange={(e) => setFormData({ ...formData, website: e.target.value })}
|
||||||
|
placeholder="https://example.com"
|
||||||
/>
|
/>
|
||||||
<Button
|
|
||||||
type="button"
|
|
||||||
variant="ghost"
|
|
||||||
size="sm"
|
|
||||||
className="absolute right-0 top-0 h-full px-3 py-2 hover:bg-transparent"
|
|
||||||
onClick={() => setShowPassword(!showPassword)}
|
|
||||||
>
|
|
||||||
{showPassword ? (
|
|
||||||
<EyeOff className="h-4 w-4 text-muted-foreground" />
|
|
||||||
) : (
|
|
||||||
<Eye className="h-4 w-4 text-muted-foreground" />
|
|
||||||
)}
|
|
||||||
</Button>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div className="grid gap-2">
|
<div className="grid gap-2">
|
||||||
<Label htmlFor="confirmPassword">{t('admin.companies.fields.confirmPassword')}</Label>
|
<Label htmlFor="address">{t('admin.companies.fields.address')}</Label>
|
||||||
<div className="relative">
|
<Input
|
||||||
<Input
|
id="address"
|
||||||
id="confirmPassword"
|
value={formData.address}
|
||||||
type={showConfirmPassword ? "text" : "password"}
|
onChange={(e) => setFormData({ ...formData, address: e.target.value })}
|
||||||
value={formData.confirmPassword}
|
placeholder="Endereço completo"
|
||||||
onChange={(e) => setFormData({ ...formData, confirmPassword: e.target.value })}
|
/>
|
||||||
placeholder="******"
|
|
||||||
/>
|
|
||||||
<Button
|
|
||||||
type="button"
|
|
||||||
variant="ghost"
|
|
||||||
size="sm"
|
|
||||||
className="absolute right-0 top-0 h-full px-3 py-2 hover:bg-transparent"
|
|
||||||
onClick={() => setShowConfirmPassword(!showConfirmPassword)}
|
|
||||||
>
|
|
||||||
{showConfirmPassword ? (
|
|
||||||
<EyeOff className="h-4 w-4 text-muted-foreground" />
|
|
||||||
) : (
|
|
||||||
<Eye className="h-4 w-4 text-muted-foreground" />
|
|
||||||
)}
|
|
||||||
</Button>
|
|
||||||
</div>
|
|
||||||
{formData.password !== formData.confirmPassword && formData.confirmPassword && (
|
|
||||||
<p className="text-xs text-red-500">{t('admin.companies.fields.passwordsDoNotMatch')}</p>
|
|
||||||
)}
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div className="grid gap-2">
|
|
||||||
<Label htmlFor="phone">{t('admin.companies.fields.phone')}</Label>
|
{/* Seção: Detalhes da Empresa */}
|
||||||
<Input
|
<div className="grid gap-4">
|
||||||
id="phone"
|
<h3 className="text-lg font-semibold border-b pb-2 flex items-center gap-2">
|
||||||
maxLength={15}
|
<span className="bg-primary w-1 h-5 rounded-full"></span>
|
||||||
value={formData.phone}
|
{t('admin.companies.sections.details', { defaultValue: 'Detalhes Adicionais' })}
|
||||||
onChange={(e) => setFormData({ ...formData, phone: formatPhone(e.target.value) })}
|
</h3>
|
||||||
placeholder="+55 11 99999-9999"
|
<div className="grid gap-2">
|
||||||
/>
|
<Label htmlFor="description">{t('admin.companies.fields.description')}</Label>
|
||||||
|
<Textarea
|
||||||
|
id="description"
|
||||||
|
value={formData.description}
|
||||||
|
onChange={(e) => setFormData({ ...formData, description: e.target.value })}
|
||||||
|
placeholder="Conte um pouco sobre a empresa..."
|
||||||
|
className="min-h-[120px] resize-none"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div className="grid grid-cols-1 md:grid-cols-2 gap-4">
|
||||||
|
<div className="grid gap-2">
|
||||||
|
<Label htmlFor="logoUrl">Logo URL</Label>
|
||||||
|
<Input
|
||||||
|
id="logoUrl"
|
||||||
|
value={formData.logoUrl}
|
||||||
|
onChange={(e) => setFormData({ ...formData, logoUrl: e.target.value })}
|
||||||
|
placeholder="https://example.com/logo.png"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div className="grid gap-2">
|
||||||
|
<Label htmlFor="yearsInMarket">Anos no mercado</Label>
|
||||||
|
<Input
|
||||||
|
id="yearsInMarket"
|
||||||
|
type="number"
|
||||||
|
value={formData.yearsInMarket}
|
||||||
|
onChange={(e) => setFormData({ ...formData, yearsInMarket: e.target.value })}
|
||||||
|
placeholder="Ex: 10"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div className="grid gap-2">
|
|
||||||
<Label htmlFor="website">{t('admin.companies.fields.website')}</Label>
|
<div className="flex justify-end gap-4 pt-6 mt-4 border-t">
|
||||||
<Input
|
|
||||||
id="website"
|
|
||||||
value={formData.website}
|
|
||||||
onChange={(e) => setFormData({ ...formData, website: e.target.value })}
|
|
||||||
placeholder="https://..."
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
<div className="grid gap-2">
|
|
||||||
<Label htmlFor="address">{t('admin.companies.fields.address')}</Label>
|
|
||||||
<Input
|
|
||||||
id="address"
|
|
||||||
value={formData.address}
|
|
||||||
onChange={(e) => setFormData({ ...formData, address: e.target.value })}
|
|
||||||
placeholder="Address..."
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
<div className="grid gap-2">
|
|
||||||
<Label htmlFor="description">{t('admin.companies.fields.description')}</Label>
|
|
||||||
<Textarea
|
|
||||||
id="description"
|
|
||||||
value={formData.description}
|
|
||||||
onChange={(e) => setFormData({ ...formData, description: e.target.value })}
|
|
||||||
placeholder="Company description..."
|
|
||||||
className="min-h-[120px]"
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
<div className="grid gap-2">
|
|
||||||
<Label htmlFor="logoUrl">Logo URL</Label>
|
|
||||||
<Input
|
|
||||||
id="logoUrl"
|
|
||||||
value={formData.logoUrl}
|
|
||||||
onChange={(e) => setFormData({ ...formData, logoUrl: e.target.value })}
|
|
||||||
placeholder="https://example.com/logo.png"
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
<div className="grid gap-2">
|
|
||||||
<Label htmlFor="yearsInMarket">Anos no mercado</Label>
|
|
||||||
<Input
|
|
||||||
id="yearsInMarket"
|
|
||||||
value={formData.yearsInMarket}
|
|
||||||
onChange={(e) => setFormData({ ...formData, yearsInMarket: e.target.value })}
|
|
||||||
placeholder="Ex: 10"
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
<div className="flex justify-end gap-4 pt-4 border-t">
|
|
||||||
<Button variant="outline" asChild>
|
<Button variant="outline" asChild>
|
||||||
<Link href="/dashboard/companies">
|
<Link href="/dashboard/companies">
|
||||||
{t('admin.companies.create.cancel')}
|
{t('admin.companies.create.cancel')}
|
||||||
</Link>
|
</Link>
|
||||||
</Button>
|
</Button>
|
||||||
<Button onClick={handleCreate} disabled={creating}>
|
<Button onClick={handleCreate} disabled={creating} className="min-w-[140px]">
|
||||||
{creating && <Loader2 className="h-4 w-4 mr-2 animate-spin" />}
|
{creating ? (
|
||||||
|
<Loader2 className="h-4 w-4 mr-2 animate-spin" />
|
||||||
|
) : (
|
||||||
|
<Building2 className="h-4 w-4 mr-2" />
|
||||||
|
)}
|
||||||
{t('admin.companies.create.submit')}
|
{t('admin.companies.create.submit')}
|
||||||
</Button>
|
</Button>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue