feat: reworked registration/sign-in, auth is now on homescreen and includes an explanation text. Reworked onboarding to only include a participation checkbox for the raffle.
This commit is contained in:
@@ -17,7 +17,7 @@ export default async function DatasetEntryPage({ params }: DatasetEntryPageProps
|
|||||||
const result = await requireAdmin();
|
const result = await requireAdmin();
|
||||||
|
|
||||||
if (!result.authenticated) {
|
if (!result.authenticated) {
|
||||||
redirect("/user/sign-in");
|
redirect("/");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!result.admin) {
|
if (!result.admin) {
|
||||||
|
|||||||
@@ -22,7 +22,7 @@ export default async function DatasetPage({ params }: DatasetPageProps) {
|
|||||||
const result = await requireAdmin();
|
const result = await requireAdmin();
|
||||||
|
|
||||||
if (!result.authenticated) {
|
if (!result.authenticated) {
|
||||||
redirect("/user/sign-in");
|
redirect("/");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!result.admin) {
|
if (!result.admin) {
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ export default async function DatasetsAdminPage() {
|
|||||||
const result = await requireAdmin();
|
const result = await requireAdmin();
|
||||||
|
|
||||||
if (!result.authenticated) {
|
if (!result.authenticated) {
|
||||||
redirect("/user/sign-in");
|
redirect("/");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!result.admin) {
|
if (!result.admin) {
|
||||||
|
|||||||
@@ -22,7 +22,7 @@ export default async function ExperimentPage({ params }: ExperimentPageProps) {
|
|||||||
const result = await requireAdmin();
|
const result = await requireAdmin();
|
||||||
|
|
||||||
if (!result.authenticated) {
|
if (!result.authenticated) {
|
||||||
redirect("/user/sign-in");
|
redirect("/");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!result.admin) {
|
if (!result.admin) {
|
||||||
|
|||||||
@@ -18,7 +18,7 @@ export default async function ParticipantPage({ params }: ParticipantDetailPageP
|
|||||||
const result = await requireAdmin();
|
const result = await requireAdmin();
|
||||||
|
|
||||||
if (!result.authenticated) {
|
if (!result.authenticated) {
|
||||||
redirect("/user/sign-in");
|
redirect("/");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!result.admin) {
|
if (!result.admin) {
|
||||||
|
|||||||
@@ -17,7 +17,7 @@ export default async function ParticipantsPage({ params }: ParticipantsPageProps
|
|||||||
const result = await requireAdmin();
|
const result = await requireAdmin();
|
||||||
|
|
||||||
if (!result.authenticated) {
|
if (!result.authenticated) {
|
||||||
redirect("/user/sign-in");
|
redirect("/");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!result.admin) {
|
if (!result.admin) {
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ export default async function ExperimentsAdminPage() {
|
|||||||
const result = await requireAdmin();
|
const result = await requireAdmin();
|
||||||
|
|
||||||
if (!result.authenticated) {
|
if (!result.authenticated) {
|
||||||
redirect("/user/sign-in");
|
redirect("/");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!result.admin) {
|
if (!result.admin) {
|
||||||
|
|||||||
@@ -10,7 +10,7 @@ export default async function AdminPage() {
|
|||||||
const result = await requireAdmin();
|
const result = await requireAdmin();
|
||||||
|
|
||||||
if (!result.authenticated) {
|
if (!result.authenticated) {
|
||||||
redirect("/user/sign-in");
|
redirect("/");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!result.admin) {
|
if (!result.admin) {
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ export default async function UsersPage() {
|
|||||||
const result = await requireAdmin();
|
const result = await requireAdmin();
|
||||||
|
|
||||||
if (!result.authenticated) {
|
if (!result.authenticated) {
|
||||||
redirect("/user/sign-in");
|
redirect("/");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!result.admin) {
|
if (!result.admin) {
|
||||||
|
|||||||
@@ -16,7 +16,7 @@ interface Props {
|
|||||||
|
|
||||||
export default async function AnnotatePage({ params }: Props) {
|
export default async function AnnotatePage({ params }: Props) {
|
||||||
const session = await auth.api.getSession({ headers: await headers() });
|
const session = await auth.api.getSession({ headers: await headers() });
|
||||||
if (!session) redirect('/user/sign-in');
|
if (!session) redirect("/");
|
||||||
|
|
||||||
const { experimentId: experimentIdStr } = await params;
|
const { experimentId: experimentIdStr } = await params;
|
||||||
const experimentId = parseInt(experimentIdStr, 10);
|
const experimentId = parseInt(experimentIdStr, 10);
|
||||||
|
|||||||
@@ -2,25 +2,18 @@ import Link from 'next/link';
|
|||||||
import { headers } from 'next/headers';
|
import { headers } from 'next/headers';
|
||||||
import { auth } from '@/lib/auth';
|
import { auth } from '@/lib/auth';
|
||||||
import { getAllExperiments, getAnnotationProgress } from '@/app/actions/annotations';
|
import { getAllExperiments, getAnnotationProgress } from '@/app/actions/annotations';
|
||||||
|
import { AuthForm } from '@/components/AuthForm';
|
||||||
|
|
||||||
export default async function HomePage() {
|
export default async function HomePage() {
|
||||||
const session = await auth.api.getSession({ headers: await headers() });
|
const session = await auth.api.getSession({ headers: await headers() });
|
||||||
|
|
||||||
if (!session) {
|
if (!session) {
|
||||||
return (
|
return (
|
||||||
<div className="max-w-xl mx-auto text-center py-20">
|
<div className="max-w-xl mx-auto text-center px-4 mt-4">
|
||||||
<h1 className="text-3xl font-bold text-gray-800 mb-4">
|
<p className="text-gray-600 mb-4">
|
||||||
Willkommen zur Dialektannotation
|
Für die Teilnahme an Annotationsstudien benötigst du ein Benutzerkonto. Mit diesem Konto speichern wir deinen Fortschritt, damit du jederzeit unterbrechen und später fortsetzen kannst. Deine Daten werden vertraulich behandelt und ausschließlich für die Zwecke dieser Studien verwendet. Wir werden dir niemals E-Mails ohne deine ausdrückliche Zustimmung senden.
|
||||||
</h1>
|
|
||||||
<p className="text-gray-600 mb-8">
|
|
||||||
Bitte melden Sie sich an, um mit der Annotation zu beginnen.
|
|
||||||
</p>
|
</p>
|
||||||
<Link
|
<AuthForm />
|
||||||
href="/user/sign-in"
|
|
||||||
className="px-6 py-3 bg-blue-600 hover:bg-blue-700 text-white font-semibold rounded-lg transition-colors"
|
|
||||||
>
|
|
||||||
Anmelden
|
|
||||||
</Link>
|
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +0,0 @@
|
|||||||
import { AuthForm } from '@/components/AuthForm';
|
|
||||||
|
|
||||||
export default function SignInPage() {
|
|
||||||
return <AuthForm />;
|
|
||||||
}
|
|
||||||
@@ -57,13 +57,10 @@ export function AuthForm() {
|
|||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="flex items-center justify-center py-8 px-4">
|
<div className="flex items-center justify-center">
|
||||||
<div className="w-full max-w-md">
|
<div className="w-full">
|
||||||
{/* Card */}
|
{/* Card */}
|
||||||
<div className="bg-white rounded-lg shadow-lg overflow-hidden border border-gray-200">
|
<div className="bg-white rounded-lg shadow-lg overflow-hidden border border-gray-200">
|
||||||
{/* Header */}
|
|
||||||
<div className="bg-gradient-to-r from-blue-600 to-blue-700 px-6 py-8">
|
|
||||||
</div>
|
|
||||||
|
|
||||||
{/* Tabs */}
|
{/* Tabs */}
|
||||||
<div className="flex border-b border-gray-200">
|
<div className="flex border-b border-gray-200">
|
||||||
@@ -200,7 +197,7 @@ export function AuthForm() {
|
|||||||
<p className="text-center text-sm text-gray-600 mt-6">
|
<p className="text-center text-sm text-gray-600 mt-6">
|
||||||
{mode === 'signin' ? (
|
{mode === 'signin' ? (
|
||||||
<>
|
<>
|
||||||
Sie haben noch kein Konto?{' '}
|
Du hast noch kein Konto?{' '}
|
||||||
<button
|
<button
|
||||||
type="button"
|
type="button"
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
@@ -214,7 +211,7 @@ export function AuthForm() {
|
|||||||
</>
|
</>
|
||||||
) : (
|
) : (
|
||||||
<>
|
<>
|
||||||
Sie haben bereits ein Konto?{' '}
|
Du hast bereits ein Konto?{' '}
|
||||||
<button
|
<button
|
||||||
type="button"
|
type="button"
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
|
|||||||
@@ -25,68 +25,65 @@ export function Header() {
|
|||||||
<div className="flex justify-between items-center py-5">
|
<div className="flex justify-between items-center py-5">
|
||||||
{/* Logo */}
|
{/* Logo */}
|
||||||
<Link href="/" className="font-bold hover:text-blue-100 transition-colors text-lg sm:text-2xl">
|
<Link href="/" className="font-bold hover:text-blue-100 transition-colors text-lg sm:text-2xl">
|
||||||
<span className="hidden sm:inline">TTS Dialektannotations-Plattform</span>
|
<span className="hidden sm:inline">TTS Dialektannotation</span>
|
||||||
<span className="sm:hidden">Dialektannotation</span>
|
<span className="sm:hidden">TTS Dialektannotation</span>
|
||||||
</Link>
|
</Link>
|
||||||
|
|
||||||
{/* Desktop Navigation */}
|
{/* Desktop Navigation */}
|
||||||
<nav className="hidden md:flex items-center gap-6">
|
{(loading || session) && (
|
||||||
{loading ? (
|
<nav className="hidden md:flex items-center gap-6">
|
||||||
<span className="text-sm text-blue-100">Laden...</span>
|
{loading ? (
|
||||||
) : session ? (
|
<span className="text-sm text-blue-100">Laden...</span>
|
||||||
<div className="flex items-center gap-6">
|
) : session && (
|
||||||
<div className="text-right">
|
<div className="flex items-center gap-6">
|
||||||
<p className="text-xs text-blue-100 uppercase tracking-wide">Willkommen zurück</p>
|
<div className="text-right">
|
||||||
<p className="text-sm font-semibold">{session.user?.email}</p>
|
<p className="text-xs text-blue-100 uppercase tracking-wide">Willkommen zurück</p>
|
||||||
</div>
|
<p className="text-sm font-semibold">{session.user?.email}</p>
|
||||||
{(session.user as any)?.admin && (
|
</div>
|
||||||
<Link
|
{(session.user as any)?.admin && (
|
||||||
href="/admin"
|
<Link
|
||||||
className="px-4 py-2 bg-yellow-500 hover:bg-yellow-600 active:bg-yellow-700 text-white font-semibold rounded-lg transition-all duration-200 transform hover:scale-105"
|
href="/admin"
|
||||||
|
className="px-4 py-2 bg-yellow-500 hover:bg-yellow-600 active:bg-yellow-700 text-white font-semibold rounded-lg transition-all duration-200 transform hover:scale-105"
|
||||||
|
>
|
||||||
|
Admin
|
||||||
|
</Link>
|
||||||
|
)}
|
||||||
|
<button
|
||||||
|
onClick={handleSignOut}
|
||||||
|
className="px-4 py-2 bg-red-600 hover:bg-red-700 active:bg-red-800 text-white font-semibold rounded-lg transition-all duration-200 transform hover:scale-105"
|
||||||
>
|
>
|
||||||
Admin
|
Abmelden
|
||||||
</Link>
|
</button>
|
||||||
)}
|
</div>
|
||||||
<button
|
)}
|
||||||
onClick={handleSignOut}
|
</nav>
|
||||||
className="px-4 py-2 bg-red-600 hover:bg-red-700 active:bg-red-800 text-white font-semibold rounded-lg transition-all duration-200 transform hover:scale-105"
|
)}
|
||||||
>
|
|
||||||
Abmelden
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
) : (
|
|
||||||
<Link
|
|
||||||
href="/user/sign-in"
|
|
||||||
className="px-5 py-2 bg-green-500 hover:bg-green-600 active:bg-green-700 text-white font-semibold rounded-lg transition-all duration-200 transform hover:scale-105"
|
|
||||||
>
|
|
||||||
Anmelden
|
|
||||||
</Link>
|
|
||||||
)}
|
|
||||||
</nav>
|
|
||||||
|
|
||||||
{/* Mobile Menu Button */}
|
{/* Mobile Menu Button */}
|
||||||
<button
|
{(loading || session) && (
|
||||||
onClick={() => setMobileMenuOpen(!mobileMenuOpen)}
|
<button
|
||||||
className="md:hidden p-2"
|
onClick={() => setMobileMenuOpen(!mobileMenuOpen)}
|
||||||
title={mobileMenuOpen ? 'Menü schließen' : 'Menü öffnen'}
|
className="md:hidden p-2"
|
||||||
>
|
title={mobileMenuOpen ? 'Menü schließen' : 'Menü öffnen'}
|
||||||
<svg className="w-6 h-6" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
>
|
||||||
{mobileMenuOpen ? (
|
<svg className="w-6 h-6" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||||
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M6 18L18 6M6 6l12 12" />
|
{mobileMenuOpen ? (
|
||||||
) : (
|
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M6 18L18 6M6 6l12 12" />
|
||||||
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M4 6h16M4 12h16M4 18h16" />
|
) : (
|
||||||
)}
|
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M4 6h16M4 12h16M4 18h16" />
|
||||||
</svg>
|
)}
|
||||||
</button>
|
</svg>
|
||||||
|
</button>
|
||||||
|
)}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{/* Mobile Fullscreen Menu */}
|
{/* Mobile Fullscreen Menu */}
|
||||||
{mobileMenuOpen && (
|
{mobileMenuOpen && session && (
|
||||||
<div className="md:hidden fixed inset-0 top-16 bg-blue-700 z-40 flex flex-col p-4 space-y-4">
|
<div className="md:hidden fixed inset-0 top-16 bg-blue-700 z-40 flex flex-col p-4 space-y-4">
|
||||||
{loading ? (
|
{loading ? (
|
||||||
<span className="text-sm text-blue-100">Laden...</span>
|
<span className="text-sm text-blue-100">Laden...</span>
|
||||||
) : session ? (
|
) : (
|
||||||
<>
|
<>
|
||||||
<div className="text-center py-4 border-b border-blue-600">
|
<div className="text-center py-4 border-b border-blue-600">
|
||||||
<p className="text-xs text-blue-100 uppercase tracking-wide">Willkommen zurück</p>
|
<p className="text-xs text-blue-100 uppercase tracking-wide">Willkommen zurück</p>
|
||||||
@@ -111,14 +108,6 @@ export function Header() {
|
|||||||
Abmelden
|
Abmelden
|
||||||
</button>
|
</button>
|
||||||
</>
|
</>
|
||||||
) : (
|
|
||||||
<Link
|
|
||||||
href="/user/sign-in"
|
|
||||||
onClick={() => setMobileMenuOpen(false)}
|
|
||||||
className="px-4 py-3 bg-green-500 hover:bg-green-600 text-white font-semibold rounded-lg transition-colors text-center"
|
|
||||||
>
|
|
||||||
Anmelden
|
|
||||||
</Link>
|
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
|
|||||||
@@ -8,6 +8,7 @@ import { DIALECT_LABELS_WITHOUT_DE } from '@/lib/dialects';
|
|||||||
interface OnboardingFormViewProps {
|
interface OnboardingFormViewProps {
|
||||||
experimentId: number;
|
experimentId: number;
|
||||||
onBack: () => void;
|
onBack: () => void;
|
||||||
|
userEmail: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
interface ResidenceEntry {
|
interface ResidenceEntry {
|
||||||
@@ -17,7 +18,7 @@ interface ResidenceEntry {
|
|||||||
|
|
||||||
interface FormData {
|
interface FormData {
|
||||||
age?: string;
|
age?: string;
|
||||||
email?: string;
|
participateInRaffle?: boolean;
|
||||||
residences?: ResidenceEntry[];
|
residences?: ResidenceEntry[];
|
||||||
dialectQualities?: Record<string, string>;
|
dialectQualities?: Record<string, string>;
|
||||||
listeningExperience?: string;
|
listeningExperience?: string;
|
||||||
@@ -26,7 +27,7 @@ interface FormData {
|
|||||||
|
|
||||||
type Step = 1 | 2 | 3;
|
type Step = 1 | 2 | 3;
|
||||||
|
|
||||||
export default function OnboardingFormView({ experimentId, onBack }: OnboardingFormViewProps) {
|
export default function OnboardingFormView({ experimentId, onBack, userEmail }: OnboardingFormViewProps) {
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
const [isPending, startTransition] = useTransition();
|
const [isPending, startTransition] = useTransition();
|
||||||
const [currentStep, setCurrentStep] = useState<Step>(1);
|
const [currentStep, setCurrentStep] = useState<Step>(1);
|
||||||
@@ -37,7 +38,7 @@ export default function OnboardingFormView({ experimentId, onBack }: OnboardingF
|
|||||||
|
|
||||||
const [formData, setFormData] = useState<FormData>({
|
const [formData, setFormData] = useState<FormData>({
|
||||||
age: '',
|
age: '',
|
||||||
email: '',
|
participateInRaffle: false,
|
||||||
residences: [{ region: '', years: '' }],
|
residences: [{ region: '', years: '' }],
|
||||||
dialectQualities: initializeDialectQualities()
|
dialectQualities: initializeDialectQualities()
|
||||||
});
|
});
|
||||||
@@ -50,7 +51,7 @@ export default function OnboardingFormView({ experimentId, onBack }: OnboardingF
|
|||||||
});
|
});
|
||||||
}, [currentStep]);
|
}, [currentStep]);
|
||||||
|
|
||||||
const handleChange = (field: keyof FormData, value: string) => {
|
const handleChange = (field: keyof FormData, value: string | boolean) => {
|
||||||
setFormData((prev) => ({
|
setFormData((prev) => ({
|
||||||
...prev,
|
...prev,
|
||||||
[field]: value,
|
[field]: value,
|
||||||
@@ -223,18 +224,23 @@ export default function OnboardingFormView({ experimentId, onBack }: OnboardingF
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="border-t border-gray-200 pt-6">
|
<div className="border-t border-gray-200 pt-6">
|
||||||
<label htmlFor="email" className="block text-s font-medium text-gray-900 mb-1">
|
<div className="flex items-start gap-3">
|
||||||
E-Mail-Adresse (optional)
|
<input
|
||||||
</label>
|
type="checkbox"
|
||||||
<p className="text-sm text-gray-500 mb-2">Wird nur für die Gutschein-Verlosung verwendet.</p>
|
id="participateInRaffle"
|
||||||
<input
|
checked={formData.participateInRaffle ?? false}
|
||||||
type="email"
|
onChange={(e) => handleChange('participateInRaffle', e.target.checked ? true : false)}
|
||||||
id="email"
|
className="mt-1 w-5 h-5 cursor-pointer accent-blue-600"
|
||||||
value={formData.email}
|
/>
|
||||||
onChange={(e) => handleChange('email', e.target.value)}
|
<div className="flex-1">
|
||||||
placeholder="beispiel@email.ch"
|
<label htmlFor="participateInRaffle" className="block text-s font-medium text-gray-900 mb-2 cursor-pointer">
|
||||||
className="w-full px-4 py-2 border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-transparent"
|
Ich möchte an der Gutscheinverlosung teilnehmen
|
||||||
/>
|
</label>
|
||||||
|
<p className="text-sm text-gray-600 mb-2">
|
||||||
|
Wir werden deine E-Mail-Adresse<strong>{userEmail && ` (${userEmail})`}</strong> verwenden, um dich im Falle eines Gewinns zu kontaktieren.
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ import { useEffect, useState } from 'react';
|
|||||||
import { getOnboardingAnswers } from '@/app/actions/onboarding';
|
import { getOnboardingAnswers } from '@/app/actions/onboarding';
|
||||||
import OnboardingInfoView from './OnboardingInfoView';
|
import OnboardingInfoView from './OnboardingInfoView';
|
||||||
import OnboardingFormView from './OnboardingFormView';
|
import OnboardingFormView from './OnboardingFormView';
|
||||||
|
import { authClient } from '@/lib/auth-client';
|
||||||
|
|
||||||
const scrollToTop = () => {
|
const scrollToTop = () => {
|
||||||
window.scrollTo({
|
window.scrollTo({
|
||||||
@@ -21,6 +22,9 @@ export default function OnboardingPhase({ experimentId }: OnboardingPhaseProps)
|
|||||||
const [hasExistingAnswers, setHasExistingAnswers] = useState(false);
|
const [hasExistingAnswers, setHasExistingAnswers] = useState(false);
|
||||||
const [isLoading, setIsLoading] = useState(true);
|
const [isLoading, setIsLoading] = useState(true);
|
||||||
|
|
||||||
|
const [userEmail, setUserEmail] = useState<string>('');
|
||||||
|
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const load = async () => {
|
const load = async () => {
|
||||||
try {
|
try {
|
||||||
@@ -32,6 +36,11 @@ export default function OnboardingPhase({ experimentId }: OnboardingPhaseProps)
|
|||||||
setHasExistingAnswers(true);
|
setHasExistingAnswers(true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
// Get user email for raffle participation
|
||||||
|
const session = await authClient.getSession();
|
||||||
|
if (session && session.data && session.data.user && session.data.user.email) {
|
||||||
|
setUserEmail(session.data.user.email);
|
||||||
|
}
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
console.error(err);
|
console.error(err);
|
||||||
} finally {
|
} finally {
|
||||||
@@ -69,5 +78,5 @@ export default function OnboardingPhase({ experimentId }: OnboardingPhaseProps)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
return <OnboardingFormView experimentId={experimentId} onBack={() => { scrollToTop(); setShowInfoPage(true); }} />;
|
return <OnboardingFormView experimentId={experimentId} userEmail={userEmail} onBack={() => { scrollToTop(); setShowInfoPage(true); }} />;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -41,4 +41,16 @@ export async function requireAdmin() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return { authenticated: true, admin: session.user.admin, session };
|
return { authenticated: true, admin: session.user.admin, session };
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function requireAuthentication() {
|
||||||
|
const session = await auth.api.getSession({
|
||||||
|
headers: await headers()
|
||||||
|
});
|
||||||
|
|
||||||
|
if (!session) {
|
||||||
|
return { authenticated: false, session: null };
|
||||||
|
}
|
||||||
|
|
||||||
|
return { authenticated: true, session };
|
||||||
}
|
}
|
||||||
Reference in New Issue
Block a user