typescript-typenfehler behoben.. npm run lint läuft nun fehlerfrei durch.
This commit is contained in:
@@ -133,7 +133,7 @@ export default function ProfileIndex() {
|
||||
|
||||
try {
|
||||
return dateFormatter.format(new Date(userData.emailVerifiedAt));
|
||||
} catch (error) {
|
||||
} catch {
|
||||
return null;
|
||||
}
|
||||
}, [userData.emailVerifiedAt, dateFormatter]);
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import React, { useEffect, useMemo, useState } from "react";
|
||||
import React, { useEffect, useState } from "react";
|
||||
import { usePage } from "@inertiajs/react";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import toast from "react-hot-toast";
|
||||
@@ -31,8 +31,6 @@ type SharedPageProps = {
|
||||
|
||||
type FieldErrors = Record<string, string>;
|
||||
|
||||
const fallbackRoute = (locale: string) => `/${locale}/login`;
|
||||
|
||||
const csrfToken = () => (document.querySelector('meta[name="csrf-token"]') as HTMLMetaElement | null)?.content ?? "";
|
||||
|
||||
export default function LoginForm({ onSuccess, canResetPassword = true, locale }: LoginFormProps) {
|
||||
|
||||
@@ -6,10 +6,8 @@ import { LoaderCircle, User, Mail, Phone, Lock, MapPin } from 'lucide-react';
|
||||
import { Dialog, DialogContent, DialogTitle, DialogDescription } from '@/components/ui/dialog';
|
||||
import type { GoogleProfilePrefill } from '../marketing/checkout/types';
|
||||
|
||||
declare const route: (name: string, params?: Record<string, unknown>) => string;
|
||||
|
||||
export interface RegisterSuccessPayload {
|
||||
user: any | null;
|
||||
user: unknown | null;
|
||||
redirect?: string | null;
|
||||
pending_purchase?: boolean;
|
||||
}
|
||||
@@ -69,7 +67,7 @@ export default function RegisterForm({ packageId, onSuccess, privacyHtml, locale
|
||||
const [serverError, setServerError] = useState<string | null>(null);
|
||||
const [serverErrorType, setServerErrorType] = useState<'generic' | 'session-expired'>('generic');
|
||||
const { t } = useTranslation(['auth', 'common']);
|
||||
const page = usePage<{ errors: Record<string, string>; locale?: string; auth?: { user?: any | null } }>();
|
||||
const page = usePage<{ errors: Record<string, string>; locale?: string; auth?: { user?: unknown | null } }>();
|
||||
const resolvedLocale = locale ?? page.props.locale ?? 'de';
|
||||
|
||||
const { data, setData, errors, clearErrors, reset, setError } = useForm<RegisterFormFields>({
|
||||
@@ -245,7 +243,7 @@ export default function RegisterForm({ packageId, onSuccess, privacyHtml, locale
|
||||
try {
|
||||
const json = await response.clone().json();
|
||||
message = json?.message ?? null;
|
||||
} catch (error) {
|
||||
} catch {
|
||||
message = null;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import React, { useEffect, useState } from 'react';
|
||||
import { useForm } from '@inertiajs/react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { LoaderCircle, User, Mail, Phone, Lock, Home, MapPin } from 'lucide-react';
|
||||
import { LoaderCircle, User, Mail, Phone, Lock, MapPin } from 'lucide-react';
|
||||
import { Dialog, DialogContent, DialogTitle, DialogDescription } from '@/components/ui/dialog';
|
||||
|
||||
interface RegisterProps {
|
||||
|
||||
@@ -110,7 +110,10 @@ export default function Dashboard() {
|
||||
const page = usePage<SharedData & DashboardPageProps>();
|
||||
const { metrics, upcomingEvents, recentPurchases, latestPurchase, tenant, emailVerification, locale, onboarding } = page.props;
|
||||
const { auth, supportedLocales } = page.props;
|
||||
const translations = (page.props.translations?.dashboard ?? {}) as Record<string, unknown>;
|
||||
const translations = useMemo(
|
||||
() => (page.props.translations?.dashboard ?? {}) as Record<string, unknown>,
|
||||
[page.props.translations?.dashboard],
|
||||
);
|
||||
|
||||
const [verificationSent, setVerificationSent] = useState(false);
|
||||
const [sendingVerification, setSendingVerification] = useState(false);
|
||||
@@ -285,7 +288,7 @@ export default function Dashboard() {
|
||||
|
||||
try {
|
||||
return currencyFormatter.format(price);
|
||||
} catch (error) {
|
||||
} catch {
|
||||
return `${price.toFixed(2)} €`;
|
||||
}
|
||||
};
|
||||
@@ -669,4 +672,4 @@ export default function Dashboard() {
|
||||
);
|
||||
}
|
||||
|
||||
(Dashboard as any).layout = (page: ReactNode) => page;
|
||||
Object.assign(Dashboard, { layout: (page: ReactNode) => page });
|
||||
|
||||
@@ -50,7 +50,10 @@ const MarkdownPreview: React.FC<{ html?: string; fallback?: string; className?:
|
||||
const Blog: React.FC<Props> = ({ posts }) => {
|
||||
const { localizedPath } = useLocalizedRoutes();
|
||||
const { props } = usePage<{ supportedLocales?: string[] }>();
|
||||
const supportedLocales = props.supportedLocales && props.supportedLocales.length > 0 ? props.supportedLocales : ['de', 'en'];
|
||||
const supportedLocales = useMemo(
|
||||
() => (props.supportedLocales && props.supportedLocales.length > 0 ? props.supportedLocales : ['de', 'en']),
|
||||
[props.supportedLocales]
|
||||
);
|
||||
const { t, i18n } = useTranslation('marketing');
|
||||
const locale = i18n.language || 'de';
|
||||
const articles = posts?.data ?? [];
|
||||
@@ -116,7 +119,7 @@ const Blog: React.FC<Props> = ({ posts }) => {
|
||||
return localizedPath(raw);
|
||||
}
|
||||
},
|
||||
[localizedPath]
|
||||
[localizedPath, supportedLocales]
|
||||
);
|
||||
|
||||
const renderPagination = () => {
|
||||
|
||||
@@ -11,7 +11,7 @@ const Kontakt: React.FC = () => {
|
||||
message: '',
|
||||
});
|
||||
|
||||
const { flash } = usePage().props as any;
|
||||
const { flash } = usePage<{ flash?: { success?: string } }>().props;
|
||||
const { t } = useTranslation('marketing');
|
||||
const { localizedPath } = useLocalizedRoutes();
|
||||
|
||||
|
||||
@@ -1,22 +1,20 @@
|
||||
import React, { useState, useEffect, useMemo, useRef, useLayoutEffect } from 'react';
|
||||
import { Head, Link, usePage } from '@inertiajs/react';
|
||||
import { Link } from '@inertiajs/react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import type { TFunction } from 'i18next';
|
||||
import { Dialog, DialogContent, DialogHeader, DialogTitle } from '@/components/ui/dialog';
|
||||
import { Tabs, TabsContent, TabsList, TabsTrigger } from '@/components/ui/tabs';
|
||||
import { Table, TableBody, TableCell, TableHead, TableHeader, TableRow } from '@/components/ui/table';
|
||||
import { Badge } from '@/components/ui/badge';
|
||||
import { Button } from '@/components/ui/button';
|
||||
import { Accordion, AccordionContent, AccordionItem, AccordionTrigger } from '@/components/ui/accordion';
|
||||
import { Card, CardContent, CardDescription, CardFooter, CardHeader, CardTitle } from '@/components/ui/card';
|
||||
import { Sheet, SheetContent } from '@/components/ui/sheet';
|
||||
import { Separator } from '@/components/ui/separator';
|
||||
import { cn } from '@/lib/utils';
|
||||
import MarketingLayout from '@/layouts/mainWebsite';
|
||||
import { useAnalytics } from '@/hooks/useAnalytics';
|
||||
import { useCtaExperiment } from '@/hooks/useCtaExperiment';
|
||||
import { useLocalizedRoutes } from '@/hooks/useLocalizedRoutes';
|
||||
import { ArrowRight, ShoppingCart, Check, Users, Image, Shield, Star, Sparkles } from 'lucide-react';
|
||||
import { ArrowRight, Check, Shield, Star, Sparkles } from 'lucide-react';
|
||||
|
||||
interface Package {
|
||||
id: number;
|
||||
@@ -214,14 +212,11 @@ interface PackagesProps {
|
||||
const Packages: React.FC<PackagesProps> = ({ endcustomerPackages, resellerPackages }) => {
|
||||
const [open, setOpen] = useState(false);
|
||||
const [selectedPackage, setSelectedPackage] = useState<Package | null>(null);
|
||||
const [currentStep, setCurrentStep] = useState<'overview' | 'testimonials'>('overview');
|
||||
const [isMobile, setIsMobile] = useState(false);
|
||||
const dialogScrollRef = useRef<HTMLDivElement | null>(null);
|
||||
const dialogHeadingRef = useRef<HTMLDivElement | null>(null);
|
||||
const mobileEndcustomerRef = useRef<HTMLDivElement | null>(null);
|
||||
const mobileResellerRef = useRef<HTMLDivElement | null>(null);
|
||||
const { props } = usePage();
|
||||
const { auth } = props as any;
|
||||
const { localizedPath } = useLocalizedRoutes();
|
||||
const { t } = useTranslation('marketing');
|
||||
const { t: tCommon } = useTranslation('common');
|
||||
@@ -278,10 +273,18 @@ const Packages: React.FC<PackagesProps> = ({ endcustomerPackages, resellerPackag
|
||||
const media = window.matchMedia('(max-width: 768px)');
|
||||
const update = () => setIsMobile(media.matches);
|
||||
update();
|
||||
media.addEventListener ? media.addEventListener('change', update) : media.addListener(update);
|
||||
if (media.addEventListener) {
|
||||
media.addEventListener('change', update);
|
||||
} else {
|
||||
media.addListener(update);
|
||||
}
|
||||
|
||||
return () => {
|
||||
media.removeEventListener ? media.removeEventListener('change', update) : media.removeListener(update);
|
||||
if (media.removeEventListener) {
|
||||
media.removeEventListener('change', update);
|
||||
} else {
|
||||
media.removeListener(update);
|
||||
}
|
||||
};
|
||||
}, []);
|
||||
|
||||
@@ -403,7 +406,6 @@ function selectHighlightPackageId(packages: Package[]): number | null {
|
||||
value: pkg.price,
|
||||
});
|
||||
setSelectedPackage(pkg);
|
||||
setCurrentStep('overview');
|
||||
setOpen(true);
|
||||
};
|
||||
|
||||
@@ -418,20 +420,6 @@ function selectHighlightPackageId(packages: Package[]): number | null {
|
||||
|
||||
// nextStep entfernt, da Tabs nun parallel sind
|
||||
|
||||
const getFeatureIcon = (feature: string) => {
|
||||
switch (feature) {
|
||||
case 'basic_uploads': return <Image className="w-4 h-4" />;
|
||||
case 'unlimited_sharing': return <ArrowRight className="w-4 h-4" />;
|
||||
case 'no_watermark': return <Shield className="w-4 h-4" />;
|
||||
case 'custom_tasks': return <Check className="w-4 h-4" />;
|
||||
case 'advanced_analytics': return <Star className="w-4 h-4" />;
|
||||
case 'priority_support': return <Users className="w-4 h-4" />;
|
||||
case 'reseller_dashboard': return <ShoppingCart className="w-4 h-4" />;
|
||||
case 'custom_branding': return <Image className="w-4 h-4" />;
|
||||
default: return <Check className="w-4 h-4" />;
|
||||
}
|
||||
};
|
||||
|
||||
const getAccentTheme = (variant: 'endcustomer' | 'reseller') =>
|
||||
variant === 'reseller'
|
||||
? {
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
import React from 'react';
|
||||
import { usePage, router } from '@inertiajs/react';
|
||||
import { Head } from '@inertiajs/react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import MarketingLayout from '@/layouts/mainWebsite';
|
||||
import { Loader } from 'lucide-react';
|
||||
@@ -8,7 +7,7 @@ import { useLocalizedRoutes } from '@/hooks/useLocalizedRoutes';
|
||||
import { ADMIN_HOME_PATH } from '@/admin/constants';
|
||||
|
||||
const Success: React.FC = () => {
|
||||
const { auth } = usePage().props as any;
|
||||
const { auth } = usePage<{ auth: { user?: { email_verified_at?: string | null } } }>().props;
|
||||
const { t } = useTranslation('success');
|
||||
const { localizedPath } = useLocalizedRoutes();
|
||||
|
||||
|
||||
@@ -104,7 +104,10 @@ const WizardBody: React.FC<{
|
||||
[t]
|
||||
);
|
||||
|
||||
const currentIndex = useMemo(() => stepConfig.findIndex((step) => step.id === currentStep), [currentStep]);
|
||||
const currentIndex = useMemo(
|
||||
() => stepConfig.findIndex((step) => step.id === currentStep),
|
||||
[currentStep, stepConfig]
|
||||
);
|
||||
const progress = useMemo(() => {
|
||||
if (currentIndex < 0) {
|
||||
return 0;
|
||||
|
||||
@@ -5,7 +5,7 @@ interface CheckoutState {
|
||||
currentStep: CheckoutStepId;
|
||||
selectedPackage: CheckoutPackage | null;
|
||||
packageOptions: CheckoutPackage[];
|
||||
authUser: any;
|
||||
authUser: unknown;
|
||||
isAuthenticated: boolean;
|
||||
paymentIntent: string | null;
|
||||
loading: boolean;
|
||||
@@ -19,7 +19,7 @@ interface CheckoutWizardContextType {
|
||||
packageOptions: CheckoutPackage[];
|
||||
currentStep: CheckoutStepId;
|
||||
isAuthenticated: boolean;
|
||||
authUser: any;
|
||||
authUser: unknown;
|
||||
paddleConfig?: {
|
||||
environment?: string | null;
|
||||
client_token?: string | null;
|
||||
@@ -27,7 +27,7 @@ interface CheckoutWizardContextType {
|
||||
paymentCompleted: boolean;
|
||||
selectPackage: (pkg: CheckoutPackage) => void;
|
||||
setSelectedPackage: (pkg: CheckoutPackage) => void;
|
||||
setAuthUser: (user: any) => void;
|
||||
setAuthUser: (user: unknown) => void;
|
||||
nextStep: () => void;
|
||||
prevStep: () => void;
|
||||
previousStep: () => void;
|
||||
@@ -56,7 +56,7 @@ const initialState: CheckoutState = {
|
||||
|
||||
type CheckoutAction =
|
||||
| { type: 'SELECT_PACKAGE'; payload: CheckoutPackage }
|
||||
| { type: 'SET_AUTH_USER'; payload: any }
|
||||
| { type: 'SET_AUTH_USER'; payload: unknown }
|
||||
| { type: 'NEXT_STEP' }
|
||||
| { type: 'PREV_STEP' }
|
||||
| { type: 'GO_TO_STEP'; payload: CheckoutStepId }
|
||||
@@ -72,19 +72,23 @@ function checkoutReducer(state: CheckoutState, action: CheckoutAction): Checkout
|
||||
case 'SET_AUTH_USER':
|
||||
return { ...state, authUser: action.payload, isAuthenticated: Boolean(action.payload) };
|
||||
case 'NEXT_STEP':
|
||||
const steps: CheckoutStepId[] = ['package', 'auth', 'payment', 'confirmation'];
|
||||
const currentIndex = steps.indexOf(state.currentStep);
|
||||
if (currentIndex < steps.length - 1) {
|
||||
return { ...state, currentStep: steps[currentIndex + 1] };
|
||||
{
|
||||
const steps: CheckoutStepId[] = ['package', 'auth', 'payment', 'confirmation'];
|
||||
const currentIndex = steps.indexOf(state.currentStep);
|
||||
if (currentIndex < steps.length - 1) {
|
||||
return { ...state, currentStep: steps[currentIndex + 1] };
|
||||
}
|
||||
return state;
|
||||
}
|
||||
return state;
|
||||
case 'PREV_STEP':
|
||||
const prevSteps: CheckoutStepId[] = ['package', 'auth', 'payment', 'confirmation'];
|
||||
const prevIndex = prevSteps.indexOf(state.currentStep);
|
||||
if (prevIndex > 0) {
|
||||
return { ...state, currentStep: prevSteps[prevIndex - 1] };
|
||||
{
|
||||
const prevSteps: CheckoutStepId[] = ['package', 'auth', 'payment', 'confirmation'];
|
||||
const prevIndex = prevSteps.indexOf(state.currentStep);
|
||||
if (prevIndex > 0) {
|
||||
return { ...state, currentStep: prevSteps[prevIndex - 1] };
|
||||
}
|
||||
return state;
|
||||
}
|
||||
return state;
|
||||
case 'GO_TO_STEP':
|
||||
return { ...state, currentStep: action.payload };
|
||||
case 'UPDATE_PAYMENT_INTENT':
|
||||
@@ -105,7 +109,7 @@ interface CheckoutWizardProviderProps {
|
||||
initialPackage?: CheckoutPackage;
|
||||
packageOptions?: CheckoutPackage[];
|
||||
initialStep?: CheckoutStepId;
|
||||
initialAuthUser?: any;
|
||||
initialAuthUser?: unknown;
|
||||
initialIsAuthenticated?: boolean;
|
||||
paddle?: {
|
||||
environment?: string | null;
|
||||
@@ -173,7 +177,7 @@ export function CheckoutWizardProvider({
|
||||
dispatch({ type: 'SELECT_PACKAGE', payload: pkg });
|
||||
}, []);
|
||||
|
||||
const setAuthUser = useCallback((user: any) => {
|
||||
const setAuthUser = useCallback((user: unknown) => {
|
||||
dispatch({ type: 'SET_AUTH_USER', payload: user });
|
||||
}, []);
|
||||
|
||||
|
||||
@@ -39,7 +39,7 @@ export const AuthStep: React.FC<AuthStepProps> = ({ privacyHtml, googleProfile,
|
||||
const page = usePage<{ locale?: string }>();
|
||||
const locale = page.props.locale ?? "de";
|
||||
const googleAuth = useMemo<GoogleAuthFlash>(() => {
|
||||
const props = page.props as Record<string, any>;
|
||||
const props = page.props as { googleAuth?: GoogleAuthFlash };
|
||||
return props.googleAuth ?? {};
|
||||
}, [page.props]);
|
||||
const { isAuthenticated, authUser, setAuthUser, nextStep, selectedPackage } = useCheckoutWizard();
|
||||
|
||||
@@ -8,10 +8,9 @@ import { cn } from "@/lib/utils";
|
||||
|
||||
interface ConfirmationStepProps {
|
||||
onViewProfile?: () => void;
|
||||
onGoToAdmin?: () => void;
|
||||
}
|
||||
|
||||
export const ConfirmationStep: React.FC<ConfirmationStepProps> = ({ onViewProfile, onGoToAdmin }) => {
|
||||
export const ConfirmationStep: React.FC<ConfirmationStepProps> = ({ onViewProfile }) => {
|
||||
const { t } = useTranslation('marketing');
|
||||
const { selectedPackage } = useCheckoutWizard();
|
||||
const handleProfile = React.useCallback(() => {
|
||||
@@ -22,14 +21,6 @@ export const ConfirmationStep: React.FC<ConfirmationStepProps> = ({ onViewProfil
|
||||
window.location.href = '/settings/profile';
|
||||
}, [onViewProfile]);
|
||||
|
||||
const handleAdmin = React.useCallback(() => {
|
||||
if (typeof onGoToAdmin === 'function') {
|
||||
onGoToAdmin();
|
||||
return;
|
||||
}
|
||||
window.location.href = '/event-admin';
|
||||
}, [onGoToAdmin]);
|
||||
|
||||
const packageName = selectedPackage?.name ?? '';
|
||||
|
||||
const onboardingItems = [
|
||||
|
||||
@@ -149,17 +149,10 @@ export const PackageStep: React.FC = () => {
|
||||
const { t } = useTranslation('marketing');
|
||||
const { selectedPackage, packageOptions, setSelectedPackage, resetPaymentState } = useCheckoutWizard();
|
||||
|
||||
|
||||
// Early return if no package is selected
|
||||
if (!selectedPackage) {
|
||||
return (
|
||||
<div className="text-center py-8">
|
||||
<p className="text-muted-foreground">{t('checkout.package_step.no_package_selected')}</p>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
const comparablePackages = useMemo(() => {
|
||||
if (!selectedPackage) {
|
||||
return [];
|
||||
}
|
||||
// Filter by type and sort: free packages first, then by price ascending
|
||||
return packageOptions
|
||||
.filter((pkg: CheckoutPackage) => pkg.type === selectedPackage.type)
|
||||
@@ -180,6 +173,14 @@ export const PackageStep: React.FC = () => {
|
||||
resetPaymentState();
|
||||
};
|
||||
|
||||
if (!selectedPackage) {
|
||||
return (
|
||||
<div className="text-center py-8">
|
||||
<p className="text-muted-foreground">{t('checkout.package_step.no_package_selected')}</p>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="grid gap-8 lg:grid-cols-[2fr_1fr]">
|
||||
<div className="space-y-6">
|
||||
|
||||
@@ -139,7 +139,7 @@ export const PaymentStep: React.FC = () => {
|
||||
const [couponLoading, setCouponLoading] = useState(false);
|
||||
const paddleRef = useRef<typeof window.Paddle | null>(null);
|
||||
const checkoutContainerRef = useRef<HTMLDivElement | null>(null);
|
||||
const eventCallbackRef = useRef<(event: any) => void>();
|
||||
const eventCallbackRef = useRef<(event: Record<string, unknown>) => void>();
|
||||
const hasAutoAppliedCoupon = useRef(false);
|
||||
const checkoutContainerClass = 'paddle-checkout-container';
|
||||
|
||||
@@ -149,7 +149,6 @@ export const PaymentStep: React.FC = () => {
|
||||
}, [i18n.language]);
|
||||
|
||||
const isFree = useMemo(() => (selectedPackage ? Number(selectedPackage.price) <= 0 : false), [selectedPackage]);
|
||||
const hasCoupon = Boolean(couponPreview);
|
||||
|
||||
const applyCoupon = useCallback(async (code: string) => {
|
||||
if (!selectedPackage) {
|
||||
@@ -339,7 +338,7 @@ export const PaymentStep: React.FC = () => {
|
||||
console.info('[Checkout] Hosted checkout response', { status: response.status, rawBody });
|
||||
}
|
||||
|
||||
let data: any = null;
|
||||
let data: { checkout_url?: string; message?: string } | null = null;
|
||||
try {
|
||||
data = rawBody && rawBody.trim().startsWith('{') ? JSON.parse(rawBody) : null;
|
||||
} catch (parseError) {
|
||||
@@ -354,7 +353,7 @@ export const PaymentStep: React.FC = () => {
|
||||
if (/^https?:\/\//i.test(trimmed)) {
|
||||
checkoutUrl = trimmed;
|
||||
} else if (trimmed.startsWith('<')) {
|
||||
const match = trimmed.match(/https?:\/\/["'a-zA-Z0-9._~:\/?#\[\]@!$&'()*+,;=%-]+/);
|
||||
const match = trimmed.match(/https?:\/\/["'a-zA-Z0-9._~:/?#@!$&'()*+,;=%-]+/);
|
||||
if (match) {
|
||||
checkoutUrl = match[0];
|
||||
}
|
||||
@@ -444,7 +443,7 @@ export const PaymentStep: React.FC = () => {
|
||||
locale: paddleLocale,
|
||||
},
|
||||
},
|
||||
eventCallback: (event: any) => eventCallbackRef.current?.(event),
|
||||
eventCallback: (event: Record<string, unknown>) => eventCallbackRef.current?.(event),
|
||||
});
|
||||
|
||||
inlineReady = true;
|
||||
|
||||
@@ -43,6 +43,23 @@ export default function Profile({ mustVerifyEmail, status }: { mustVerifyEmail:
|
||||
>
|
||||
{({ processing, recentlySuccessful, errors }) => (
|
||||
<>
|
||||
<div className="grid gap-2">
|
||||
<Label htmlFor="name">{t('auth.settings.profile.name', 'Name')}</Label>
|
||||
|
||||
<Input
|
||||
id="name"
|
||||
type="text"
|
||||
className="mt-1 block w-full"
|
||||
defaultValue={auth.user.name ?? ''}
|
||||
name="name"
|
||||
required
|
||||
autoComplete="name"
|
||||
placeholder={t('auth.settings.profile.name_placeholder', 'Dein Name')}
|
||||
/>
|
||||
|
||||
<InputError className="mt-2" message={errors.name} />
|
||||
</div>
|
||||
|
||||
<div className="grid gap-2">
|
||||
<Label htmlFor="email">{t('auth.settings.profile.email', 'Email address')}</Label>
|
||||
|
||||
@@ -66,7 +83,7 @@ export default function Profile({ mustVerifyEmail, status }: { mustVerifyEmail:
|
||||
<Input
|
||||
id="username"
|
||||
className="mt-1 block w-full"
|
||||
defaultValue={(auth.user as any).username ?? ''}
|
||||
defaultValue={auth.user?.username ?? ''}
|
||||
name="username"
|
||||
autoComplete="username"
|
||||
placeholder={t('auth.settings.profile.username_placeholder')}
|
||||
@@ -81,7 +98,7 @@ export default function Profile({ mustVerifyEmail, status }: { mustVerifyEmail:
|
||||
<select
|
||||
id="preferred_locale"
|
||||
name="preferred_locale"
|
||||
defaultValue={(auth.user as any).preferred_locale ?? 'en'}
|
||||
defaultValue={auth.user?.preferred_locale ?? 'en'}
|
||||
className="mt-1 block w-full rounded-md border border-input bg-background px-3 py-2 text-sm ring-offset-background placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50"
|
||||
>
|
||||
{(supportedLocales ?? ['de', 'en']).map((l) => (
|
||||
|
||||
Reference in New Issue
Block a user