feat(i18n): Complete localization of marketing frontend with react-i18next, prefixed URLs, JSON migrations, and automation

This commit is contained in:
Codex Agent
2025-10-03 13:05:13 +02:00
parent 1845d83583
commit 60f8de9162
46 changed files with 3454 additions and 590 deletions

View File

@@ -0,0 +1,45 @@
import React from 'react';
import { useForm } from '@inertiajs/react';
import { Button } from '@/components/ui/button';
import { Input } from '@/components/ui/input';
import { Label } from '@/components/ui/label';
import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card';
const ProfileAccount = () => {
const { data, setData, post, processing, errors } = useForm({
name: '',
email: '',
});
const handleSubmit = (e: React.FormEvent) => {
e.preventDefault();
post('/profile/account');
};
return (
<div className="container mx-auto py-8">
<Card>
<CardHeader>
<CardTitle>Account bearbeiten</CardTitle>
</CardHeader>
<CardContent>
<form onSubmit={handleSubmit} className="space-y-4">
<div>
<Label htmlFor="name">Name</Label>
<Input id="name" value={data.name} onChange={(e) => setData('name', e.target.value)} />
{errors.name && <p className="text-red-500 text-sm">{errors.name}</p>}
</div>
<div>
<Label htmlFor="email">Email</Label>
<Input id="email" type="email" value={data.email} onChange={(e) => setData('email', e.target.value)} />
{errors.email && <p className="text-red-500 text-sm">{errors.email}</p>}
</div>
<Button type="submit" disabled={processing}>Speichern</Button>
</form>
</CardContent>
</Card>
</div>
);
};
export default ProfileAccount;

View File

@@ -0,0 +1,38 @@
import React from 'react';
import { usePage } from '@inertiajs/react';
import { Tabs, TabsContent, TabsList, TabsTrigger } from '@/components/ui/tabs';
import Account from './Account';
import Orders from './Orders';
import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card';
const ProfileIndex = () => {
const { user } = usePage().props as any;
return (
<div className="container mx-auto py-8 space-y-6">
<Card>
<CardHeader>
<CardTitle>Mein Profil</CardTitle>
</CardHeader>
<CardContent>
<p>Hallo, {user.name}!</p>
<p>Email: {user.email}</p>
</CardContent>
</Card>
<Tabs defaultValue="account" className="w-full">
<TabsList className="grid w-full grid-cols-2">
<TabsTrigger value="account">Account</TabsTrigger>
<TabsTrigger value="orders">Bestellungen</TabsTrigger>
</TabsList>
<TabsContent value="account">
<Account />
</TabsContent>
<TabsContent value="orders">
<Orders />
</TabsContent>
</Tabs>
</div>
);
};
export default ProfileIndex;

View File

@@ -0,0 +1,61 @@
import React from 'react';
import { usePage } from '@inertiajs/react';
import { Table, TableBody, TableCell, TableHead, TableHeader, TableRow } from '@/components/ui/table';
import { Badge } from '@/components/ui/badge';
import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card';
import { format } from 'date-fns';
interface Purchase {
id: number;
created_at: string;
package: {
name: string;
price: number;
};
status: string;
}
const ProfileOrders = () => {
const { purchases } = usePage().props as any;
return (
<div className="container mx-auto py-8">
<Card>
<CardHeader>
<CardTitle>Bestellungen</CardTitle>
</CardHeader>
<CardContent>
<Table>
<TableHeader>
<TableRow>
<TableHead>Paket</TableHead>
<TableHead>Preis</TableHead>
<TableHead>Datum</TableHead>
<TableHead>Status</TableHead>
</TableRow>
</TableHeader>
<TableBody>
{purchases.map((purchase) => (
<TableRow key={purchase.id}>
<TableCell>{purchase.package.name}</TableCell>
<TableCell>{purchase.package.price} </TableCell>
<TableCell>{format(new Date(purchase.created_at), 'dd.MM.yyyy')}</TableCell>
<TableCell>
<Badge variant={purchase.status === 'completed' ? 'default' : 'secondary'}>
{purchase.status}
</Badge>
</TableCell>
</TableRow>
))}
</TableBody>
</Table>
{purchases.length === 0 && (
<p className="text-center text-muted-foreground py-8">Keine Bestellungen gefunden.</p>
)}
</CardContent>
</Card>
</div>
);
};
export default ProfileOrders;