added registriation of manager and business

This commit is contained in:
Rajpreet0 2025-11-23 17:33:16 +01:00
parent 47cc3466a0
commit 08ff89702d
7 changed files with 706 additions and 55 deletions

View file

@ -1,16 +1,24 @@
import { LogoutButton } from "@/src/components/layout/LogoutButton";
import { requireAuthWithData } from "@/src/lib/auth/getUser";
import { requireAuthWithData, isManager, isUser } from "@/src/lib/auth/getUser";
export default async function DashboardPage() {
const userData = await requireAuthWithData();
// Get display name based on user type
const displayName = isManager(userData)
? `${userData.firstName} ${userData.lastName}`
: userData.name || userData.email;
return (
<div className="space-y-6">
<div className="bg-white rounded-lg shadow p-6">
<h1 className="text-3xl font-bold text-gray-900 mb-4">Willkommen zurück!</h1>
<p className="text-gray-600">
Schön, dich wiederzusehen, {userData?.name || userData.email}
</p>
<p className="text-gray-600">Schön, dich wiederzusehen, {displayName}</p>
{isManager(userData) && (
<span className="inline-block mt-2 px-3 py-1 bg-blue-100 text-blue-800 text-sm font-medium rounded-full">
Manager
</span>
)}
</div>
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-6">
@ -19,10 +27,20 @@ export default async function DashboardPage() {
<p className="text-gray-600 text-sm">Verwalte deine persönlichen Daten</p>
</div>
<div className="bg-white rounded-lg shadow p-6">
<h2 className="text-lg font-semibold mb-2">Trainings</h2>
<p className="text-gray-600 text-sm">Deine gebuchten Trainingseinheiten</p>
</div>
{isManager(userData) ? (
<div className="bg-white rounded-lg shadow p-6">
<h2 className="text-lg font-semibold mb-2">Meine Businesses</h2>
<p className="text-gray-600 text-sm">
{userData.businesses.length}{" "}
{userData.businesses.length === 1 ? "Business" : "Businesses"}
</p>
</div>
) : (
<div className="bg-white rounded-lg shadow p-6">
<h2 className="text-lg font-semibold mb-2">Trainings</h2>
<p className="text-gray-600 text-sm">Deine gebuchten Trainingseinheiten</p>
</div>
)}
<div className="bg-white rounded-lg shadow p-6">
<h2 className="text-lg font-semibold mb-2">Einstellungen</h2>
@ -30,41 +48,93 @@ export default async function DashboardPage() {
</div>
</div>
<div className="bg-white rounded-lg shadow p-6">
<h2 className="text-xl font-semibold mb-4">Benutzerdaten</h2>
<dl className="grid grid-cols-1 md:grid-cols-2 gap-4">
<div>
<dt className="text-sm font-medium text-gray-500">Name</dt>
<dd className="mt-1 text-sm text-gray-900">{userData?.name || "—"}</dd>
{isUser(userData) && (
<div className="bg-white rounded-lg shadow p-6">
<h2 className="text-xl font-semibold mb-4">Benutzerdaten</h2>
<dl className="grid grid-cols-1 md:grid-cols-2 gap-4">
<div>
<dt className="text-sm font-medium text-gray-500">Name</dt>
<dd className="mt-1 text-sm text-gray-900">{userData.name || "—"}</dd>
</div>
<div>
<dt className="text-sm font-medium text-gray-500">E-Mail</dt>
<dd className="mt-1 text-sm text-gray-900">{userData.email}</dd>
</div>
<div>
<dt className="text-sm font-medium text-gray-500">Geburtsdatum</dt>
<dd className="mt-1 text-sm text-gray-900">
{userData.birthday ? new Date(userData.birthday).toLocaleDateString("de-DE") : "—"}
</dd>
</div>
<div>
<dt className="text-sm font-medium text-gray-500">Wohnort</dt>
<dd className="mt-1 text-sm text-gray-900">
{userData.plz && userData.city ? `${userData.plz} ${userData.city}` : "—"}
</dd>
</div>
<div>
<dt className="text-sm font-medium text-gray-500">Geschlecht</dt>
<dd className="mt-1 text-sm text-gray-900">{userData.gender || "—"}</dd>
</div>
<div>
<dt className="text-sm font-medium text-gray-500">Registriert seit</dt>
<dd className="mt-1 text-sm text-gray-900">
{userData.createdAt
? new Date(userData.createdAt).toLocaleDateString("de-DE")
: "—"}
</dd>
</div>
</dl>
</div>
)}
{isManager(userData) && (
<div className="bg-white rounded-lg shadow p-6">
<h2 className="text-xl font-semibold mb-4">Manager-Daten</h2>
<dl className="grid grid-cols-1 md:grid-cols-2 gap-4">
<div>
<dt className="text-sm font-medium text-gray-500">Vorname</dt>
<dd className="mt-1 text-sm text-gray-900">{userData.firstName}</dd>
</div>
<div>
<dt className="text-sm font-medium text-gray-500">Nachname</dt>
<dd className="mt-1 text-sm text-gray-900">{userData.lastName}</dd>
</div>
<div>
<dt className="text-sm font-medium text-gray-500">E-Mail</dt>
<dd className="mt-1 text-sm text-gray-900">{userData.email}</dd>
</div>
<div>
<dt className="text-sm font-medium text-gray-500">Telefon</dt>
<dd className="mt-1 text-sm text-gray-900">{userData.tel || "—"}</dd>
</div>
<div>
<dt className="text-sm font-medium text-gray-500">Registriert seit</dt>
<dd className="mt-1 text-sm text-gray-900">
{userData.createdAt
? new Date(userData.createdAt).toLocaleDateString("de-DE")
: "—"}
</dd>
</div>
</dl>
</div>
)}
{isManager(userData) && userData.businesses.length > 0 && (
<div className="bg-white rounded-lg shadow p-6">
<h2 className="text-xl font-semibold mb-4">Meine Businesses</h2>
<div className="space-y-4">
{userData.businesses.map((business) => (
<div key={business.id} className="border-l-4 border-blue-500 pl-4 py-2">
<h3 className="text-lg font-semibold text-gray-900">{business.name}</h3>
<p className="text-sm text-gray-600 mt-1">{business.address}</p>
<p className="text-sm text-gray-600">{business.email}</p>
</div>
))}
</div>
<div>
<dt className="text-sm font-medium text-gray-500">E-Mail</dt>
<dd className="mt-1 text-sm text-gray-900">{userData.email}</dd>
</div>
<div>
<dt className="text-sm font-medium text-gray-500">Geburtsdatum</dt>
<dd className="mt-1 text-sm text-gray-900">
{userData?.birthday ? new Date(userData.birthday).toLocaleDateString("de-DE") : "—"}
</dd>
</div>
<div>
<dt className="text-sm font-medium text-gray-500">Wohnort</dt>
<dd className="mt-1 text-sm text-gray-900">
{userData?.plz && userData?.city ? `${userData.plz} ${userData.city}` : "—"}
</dd>
</div>
<div>
<dt className="text-sm font-medium text-gray-500">Geschlecht</dt>
<dd className="mt-1 text-sm text-gray-900">{userData?.gender || "—"}</dd>
</div>
<div>
<dt className="text-sm font-medium text-gray-500">Registriert seit</dt>
<dd className="mt-1 text-sm text-gray-900">
{userData?.createdAt ? new Date(userData.createdAt).toLocaleDateString("de-DE") : "—"}
</dd>
</div>
</dl>
</div>
</div>
)}
<LogoutButton />
</div>
);

View file

@ -0,0 +1,109 @@
// app/api/auth/register/admin/route.ts
import { createClient } from "@/src/lib/supabase/server";
import { prisma } from "@/src/lib/prisma";
import { NextResponse } from "next/server";
export async function POST(request: Request) {
try {
const body = await request.json();
const {
email,
password,
firstName,
lastName,
tel,
plz,
city,
street,
companyName,
companyPlace,
companyPLZ,
companyStreet,
companyMail,
companyNumber,
} = body;
// Validate required fields
if (!email || !password || !firstName || !lastName || !companyName) {
return NextResponse.json({ error: "Pflichtfelder fehlen" }, { status: 400 });
}
const supabase = await createClient();
// Create Manager in Supabase Auth
const { data, error } = await supabase.auth.signUp({
email,
password,
options: {
emailRedirectTo: `${process.env.NEXT_PUBLIC_SITE_URL || "http://localhost:3000"}/login`,
data: {
firstName,
lastName,
role: "manager",
},
},
});
if (error) {
console.error("❌ Supabase Auth Error:", error.message);
return NextResponse.json({ error: error.message }, { status: 400 });
}
const supabaseUser = data.user;
if (!supabaseUser) {
return NextResponse.json({ error: "Manager konnte nicht erstellt werden" }, { status: 500 });
}
// Check if Manager already exists in DB
const existingManager = await prisma.manager.findUnique({
where: { email },
});
if (existingManager) {
return NextResponse.json({ manager: existingManager }, { status: 200 });
}
// Build business address
const businessAddress = `${companyStreet}, ${companyPLZ} ${companyPlace}`;
const managerAddress = plz && city && street ? `${street}, ${plz} ${city}` : "";
// Create Manager and Business in a transaction
const result = await prisma.$transaction(async (tx) => {
// Create Manager
const newManager = await tx.manager.create({
data: {
id: supabaseUser.id,
firstName,
lastName,
tel: tel || null,
email,
},
});
// Create Business
const newBusiness = await tx.business.create({
data: {
managerId: newManager.id,
name: companyName,
address: businessAddress,
email: companyMail || email, // Use manager email if company email is not provided
title: companyName, // Using company name as title
},
});
return { manager: newManager, business: newBusiness };
});
return NextResponse.json(
{
manager: result.manager,
business: result.business,
message: "Manager und Business erfolgreich erstellt",
},
{ status: 201 }
);
} catch (error) {
console.error("Error in /api/auth/register/admin:", error);
return NextResponse.json({ error: "Internal Server Error" }, { status: 500 });
}
}

View file

@ -8,7 +8,8 @@ import { userLoginSchema } from "../modules/auth/validation/userLoginSchema";
import { createClient } from "@/src/lib/supabase/client";
import { useAuthStore } from "@/src/store/authStore";
import { useRouter } from "next/navigation";
import { RegisterFormData } from "../types/auth";
import { RegisterFormData, AdminRegisterFormData } from "../types/auth";
import { adminRegisterSchema } from "../modules/auth/validation/adminRegisterSchema";
export const useAuth = () => {
const [loading, setLoading] = useState(false);
@ -112,10 +113,69 @@ export const useAuth = () => {
}
};
const registerAdmin = async (formData: AdminRegisterFormData) => {
setErrors({});
setLoading(true);
try {
adminRegisterSchema.parse(formData);
const [firstName, ...lastNameParts] = formData.fullName.split(" ");
const lastName = lastNameParts.join(" ") || firstName;
const res = await fetch("/api/auth/register/admin", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({
email: formData.email,
password: formData.password,
firstName,
lastName,
tel: formData.tel,
plz: formData.plz,
city: formData.place,
street: formData.street,
companyName: formData.companyName,
companyPlace: formData.companyPlace,
companyPLZ: formData.companyPLZ,
companyStreet: formData.companyStreet,
companyMail: formData.companyMail,
companyNumber: formData.companyNumber,
}),
});
const data = await res.json();
if (!res.ok) {
setErrors({ email: data.error || "Registrierung fehlgeschlagen" });
toast.error(data.error || "Registrierung fehlgeschlagen");
return false;
}
toast.success("Manager und Business erfolgreich registriert! Bitte bestätige deine E-Mail.");
return true;
} catch (err) {
if (err instanceof ZodError) {
const fieldErrors: Record<string, string> = {};
err.issues.forEach((issue) => {
const path = issue.path[0];
if (typeof path === "string") fieldErrors[path] = issue.message;
});
setErrors(fieldErrors);
return false;
}
toast.error("Ein unbekannter Fehler ist aufgetreten.");
return false;
} finally {
setLoading(false);
}
};
return {
loading,
errors,
registerUser,
registerAdmin,
loginUser,
setErrors,
};

View file

@ -2,7 +2,7 @@ import { createClient } from "@/src/lib/supabase/server";
import { prisma } from "@/src/lib/prisma";
import { cache } from "react";
// Define the user data type
// Define the user data types
export type UserData = {
id: string;
name: string | null;
@ -15,11 +15,31 @@ export type UserData = {
gender: string | null;
pbSrc: string | null;
createdAt: Date | null;
role: "user";
};
export type ManagerData = {
id: string;
firstName: string;
lastName: string;
email: string;
tel: string | null;
pbSrc: string | null;
createdAt: Date | null;
role: "manager";
businesses: Array<{
id: string;
name: string;
address: string;
email: string;
}>;
};
export type AuthUserData = UserData | ManagerData;
// Cache entry type
type CacheEntry = {
data: UserData;
data: AuthUserData;
timestamp: number;
};
@ -40,7 +60,7 @@ export const getUser = cache(async () => {
});
// Cache user data from database with time-based cache
export const getUserData = cache(async (): Promise<UserData | null> => {
export const getUserData = cache(async (): Promise<AuthUserData | null> => {
userDataCallCount++;
console.log(`📊 [DB] getUserData called (count: ${userDataCallCount})`);
@ -60,6 +80,7 @@ export const getUserData = cache(async (): Promise<UserData | null> => {
console.log("🗄️ [DB] Fetching user data from Prisma for:", user.email);
// Try to find in User table first
const userData = await prisma.user.findUnique({
where: { id: user.id },
select: {
@ -77,14 +98,47 @@ export const getUserData = cache(async (): Promise<UserData | null> => {
},
});
console.log("✅ [DB] User data fetched:", userData?.name);
// Store in cache
if (userData) {
userDataCache.set(user.id, { data: userData, timestamp: now });
console.log("✅ [DB] User data fetched:", userData.name);
const userWithRole: UserData = { ...userData, role: "user" };
userDataCache.set(user.id, { data: userWithRole, timestamp: now });
return userWithRole;
}
return userData;
// If not found in User table, try Manager table
const managerData = await prisma.manager.findUnique({
where: { id: user.id },
select: {
id: true,
firstName: true,
lastName: true,
email: true,
tel: true,
pbSrc: true,
createdAt: true,
businesses: {
select: {
id: true,
name: true,
address: true,
email: true,
},
},
},
});
if (managerData) {
console.log(
"✅ [DB] Manager data fetched:",
`${managerData.firstName} ${managerData.lastName}`
);
const managerWithRole: ManagerData = { ...managerData, role: "manager" };
userDataCache.set(user.id, { data: managerWithRole, timestamp: now });
return managerWithRole;
}
console.log("⚠️ [DB] No user or manager found for:", user.email);
return null;
});
export async function requireAuth() {
@ -95,7 +149,7 @@ export async function requireAuth() {
export async function requireAuthWithData() {
const userData = await getUserData();
if (!userData) {
throw new Error("User not found");
throw new Error("User or Manager not found");
}
return userData;
}
@ -107,3 +161,13 @@ export async function requireGuest() {
redirect("/dashboard");
}
}
// Helper function to check if user is a manager
export function isManager(userData: AuthUserData): userData is ManagerData {
return userData.role === "manager";
}
// Helper function to check if user is a regular user
export function isUser(userData: AuthUserData): userData is UserData {
return userData.role === "user";
}

View file

@ -1,7 +1,292 @@
"use client";
import { useState } from "react";
import AuthSidebarComponent from "../components/AuthSidebarComponent";
import InputComponent from "@/src/components/layout/InputComponent";
import { Button } from "@/src/components/ui/button";
import { useAuthFormStore } from "../../store/authFormState";
import { useAuth } from "@/src/hooks/useAuth";
import { ZodError } from "zod";
import {
adminRegisterStep1Schema,
adminRegisterStep2Schema,
adminRegisterStep3Schema,
} from "../../validation/adminRegisterSchema";
import { Spinner } from "@/src/components/ui/spinner";
import { useRouter } from "next/navigation";
const RegisterAdminView = () => {
return <div>Register Admin View</div>;
const RegisterAdmin = () => {
const [step, setStep] = useState(1);
const { registerAdmin, loading, errors, setErrors } = useAuth();
const router = useRouter();
const formData = useAuthFormStore();
const handleChange = (field: string, value: string) => {
formData.setField(field, value);
};
const handleNext = () => {
setErrors({});
try {
if (step === 1) {
adminRegisterStep1Schema.parse({
fullName: formData.fullName,
email: formData.email,
tel: formData.tel,
password: formData.password,
passwordConfirm: formData.passwordConfirm,
});
setStep(2);
} else if (step === 2) {
adminRegisterStep2Schema.parse({
plz: formData.plz,
place: formData.place,
street: formData.street,
});
setStep(3);
}
} catch (err) {
if (err instanceof ZodError) {
const fieldErrors: Record<string, string> = {};
err.issues.forEach((issue) => {
const path = issue.path[0];
if (typeof path === "string") {
fieldErrors[path] = issue.message;
}
});
setErrors(fieldErrors);
}
}
};
const handleRegister = async () => {
setErrors({});
try {
adminRegisterStep3Schema.parse({
companyName: formData.companyName,
companyPlace: formData.companyPlace,
companyPLZ: formData.companyPLZ,
companyStreet: formData.companyStreet,
companyMail: formData.companyMail,
companyNumber: formData.companyNumber,
});
const success = await registerAdmin({
fullName: formData.fullName,
email: formData.email,
tel: formData.tel,
password: formData.password,
passwordConfirm: formData.passwordConfirm,
plz: formData.plz,
place: formData.place,
street: formData.street,
companyName: formData.companyName,
companyPlace: formData.companyPlace,
companyPLZ: formData.companyPLZ,
companyStreet: formData.companyStreet,
companyMail: formData.companyMail,
companyNumber: formData.companyNumber,
});
if (success) {
formData.resetForm();
router.push("/login");
}
} catch (err) {
if (err instanceof ZodError) {
const fieldErrors: Record<string, string> = {};
err.issues.forEach((issue) => {
const path = issue.path[0];
if (typeof path === "string") {
fieldErrors[path] = issue.message;
}
});
setErrors(fieldErrors);
}
}
};
return (
<div className="flex min-h-screen">
<div className="hidden lg:flex lg:w-1/6 ">
<div className="fixed p-4 left-0 top-0 h-screen w-1/2 z-10">
<AuthSidebarComponent
title="Werde zur besten Version deiner selbst"
footer="info@since3.de"
isSteps
step={step}
totalSteps={3}
onStepChange={setStep}
/>
</div>
</div>
<div className="w-full lg:w-5/6 lg:ml-auto flex justify-center items-center min-h-screen px-4">
<div className="w-full max-w-lg flex flex-col gap-4 z-20">
<h1 className="text-2xl font-extrabold text-blue mb-8 mt-8 ">Sign up for free</h1>
{step === 1 && (
<>
<InputComponent
isLabel
label="Vor- und Nachname"
type="text"
id="register-admin-fullName"
value={formData.fullName}
onChange={(e) => handleChange("fullName", e.target.value)}
error={errors.fullName}
/>
<InputComponent
isLabel
label="E-Mail"
type="email"
id="register-admin-email"
value={formData.email}
onChange={(e) => handleChange("email", e.target.value)}
error={errors.email}
/>
<InputComponent
isLabel
label="Telefonnummer"
type="text"
id="register-admin-tel"
value={formData.tel}
onChange={(e) => handleChange("tel", e.target.value)}
error={errors.tel}
/>
<InputComponent
isLabel
label="Passwort"
type="password"
id="register-admin-password"
value={formData.password}
onChange={(e) => handleChange("password", e.target.value)}
error={errors.password}
/>
<InputComponent
isLabel
label="Passwort bestätigen"
type="password"
id="register-admin-passwordConform"
value={formData.passwordConfirm}
onChange={(e) => handleChange("passwordConfirm", e.target.value)}
error={errors.passwordConfirm}
/>
<Button className="w-full mt-6" onClick={handleNext} disabled={loading}>
{loading ? <Spinner /> : "Weiter"}
</Button>
</>
)}
{step === 2 && (
<>
<InputComponent
isLabel
label="PLZ"
type="text"
id="register-admin-plz"
value={formData.plz}
onChange={(e) => handleChange("plz", e.target.value)}
error={errors.plz}
/>
<InputComponent
isLabel
label="Wohnort"
type="text"
id="register-admin-place"
value={formData.place}
onChange={(e) => handleChange("place", e.target.value)}
error={errors.place}
/>
<InputComponent
isLabel
label="Straße und Hausnummer"
type="text"
id="register-admin-street"
value={formData.street}
onChange={(e) => handleChange("street", e.target.value)}
error={errors.street}
/>
<Button className="w-full mt-6" onClick={handleNext} disabled={loading}>
{loading ? <Spinner /> : "Weiter"}
</Button>
</>
)}
{step === 3 && (
<>
<InputComponent
isLabel
label="Unternehmensname"
type="text"
id="register-admin-companyName"
value={formData.companyName}
onChange={(e) => handleChange("companyName", e.target.value)}
error={errors.companyName}
/>
<InputComponent
isLabel
label="Unternehmenssitz"
type="text"
id="register-admin-companyPlace"
value={formData.companyPlace}
onChange={(e) => handleChange("companyPlace", e.target.value)}
error={errors.companyPlace}
/>
<InputComponent
isLabel
label="PLZ"
type="text"
id="register-admin-companyPLZ"
value={formData.companyPLZ}
onChange={(e) => handleChange("companyPLZ", e.target.value)}
error={errors.companyPLZ}
/>
<InputComponent
isLabel
label="Straße und Hausnummer"
type="text"
id="register-admin-companyStreet"
value={formData.companyStreet}
onChange={(e) => handleChange("companyStreet", e.target.value)}
error={errors.companyStreet}
/>
<InputComponent
isLabel
label="Geschäftsmail (falls unterschiedlich)"
type="email"
id="register-admin-companyMail"
value={formData.companyMail}
onChange={(e) => handleChange("companyMail", e.target.value)}
error={errors.companyMail}
/>
<InputComponent
isLabel
label="Geschäftsnummer (falls unterschiedlich)"
type="text"
id="register-admin-companyNumber"
value={formData.companyNumber}
onChange={(e) => handleChange("companyNumber", e.target.value)}
error={errors.companyNumber}
/>
<Button className="w-full mt-6" onClick={handleRegister} disabled={loading}>
{loading ? <Spinner /> : "Anmelden"}
</Button>
</>
)}
<div className="flex flex-col sm:flex-row gap-2 items-center mt-8 text-sm">
<p>Ich habe schon einen Account</p>
<p className="text-yellow hover:underline cursor-pointer">Login</p>
</div>
</div>
</div>
</div>
);
};
export default RegisterAdminView;
export default RegisterAdmin;

View file

@ -0,0 +1,46 @@
import { z } from "zod";
// Step 1: Personal Info
export const adminRegisterStep1Schema = z
.object({
fullName: z.string().min(2, "Name muss mindestens 2 Zeichen lang sein"),
email: z.string().email("Bitte eine gültige E-Mail-Adresse eingeben"),
tel: z.string().min(5, "Telefonnummer muss mindestens 5 Zeichen lang sein"),
password: z.string().min(8, "Passwort muss mindestens 8 Zeichen lang sein"),
passwordConfirm: z.string(),
})
.refine((data) => data.password === data.passwordConfirm, {
message: "Passwürter müssen übereinstimmen",
path: ["passwordConfirm"],
});
// Step 2: Address Info
export const adminRegisterStep2Schema = z.object({
plz: z.string().min(5, "PLZ muss 5 Zeichen lang sein").max(5, "PLZ muss 5 Zeichen lang sein"),
place: z.string().min(2, "Wohnort muss mindestens 2 Zeichen lang sein"),
street: z.string().min(3, "Straße und Hausnummer müssen mindestens 3 Zeichen lang sein"),
});
// Step 3: Business Info
export const adminRegisterStep3Schema = z.object({
companyName: z.string().min(2, "Unternehmensname muss mindestens 2 Zeichen lang sein"),
companyPlace: z.string().min(2, "Unternehmenssitz muss mindestens 2 Zeichen lang sein"),
companyPLZ: z
.string()
.min(5, "PLZ muss 5 Zeichen lang sein")
.max(5, "PLZ muss 5 Zeichen lang sein"),
companyStreet: z.string().min(3, "Straße und Hausnummer müssen mindestens 3 Zeichen lang sein"),
companyMail: z
.string()
.email("Bitte eine gültige E-Mail-Adresse eingeben")
.optional()
.or(z.literal("")),
companyNumber: z.string().optional().or(z.literal("")),
});
// Full schema for complete validation
export const adminRegisterSchema = adminRegisterStep1Schema
.merge(adminRegisterStep2Schema)
.merge(adminRegisterStep3Schema);
export type AdminRegisterFormData = z.infer<typeof adminRegisterSchema>;

View file

@ -10,6 +10,23 @@ export interface RegisterFormData {
gender: string;
}
export interface AdminRegisterFormData {
fullName: string;
email: string;
tel: string;
password: string;
passwordConfirm: string;
plz: string;
place: string;
street: string;
companyName: string;
companyPlace: string;
companyPLZ: string;
companyStreet: string;
companyMail: string;
companyNumber: string;
}
export interface LoginFormData {
email: string;
password: string;