{branding.name}
Find, book & manage your appointments with ease.
import { Scissors } from "lucide-react"; import Link from "next/link"; import { redirect } from "next/navigation"; import { auth } from "@/auth"; import { Button } from "@/components/ui/button"; import { getBranding } from "@/lib/business/branding"; import { getPrimaryBusiness } from "@/lib/business/get-primary-business"; import { hasPermission, isSuperAdmin } from "@/lib/auth/permissions"; import { Permission } from "@/generated/prisma/enums"; import { prisma } from "@/lib/db/prisma"; import { WelcomeInstallCard } from "@/features/pwa/components/welcome-install-card"; /** * The unauthenticated entry point — always shown at `/` before * authentication, per the brief's "Welcome routing" requirements. * Authenticated visitors never see it: they're routed straight to their * role's calendar (barber → /staff, owner/super admin → /owner/calendar) * or customer home below. This is also where a bare sign-in with no * `callbackUrl` ends up — see safeRedirectPath's fallback in * sign-in-form.tsx — so it's the one place that has to get every role * right, not just staffProfile holders. Unreachable at all before * installation completes — src/proxy.ts redirects every non-exempt route * (including this one) to /install until ApplicationInstallation flips * to INSTALLED. */ export default async function WelcomePage() { const session = await auth(); if (session?.user) { const staffProfile = await prisma.staffProfile.findUnique({ where: { userId: session.user.id } }); if (staffProfile) { const canManageStaff = await hasPermission(session.user.id, Permission.MANAGE_STAFF); redirect(canManageStaff ? "/owner" : "/staff"); } // A Super Administrator has no StaffProfile by design (see // isSuperAdmin) — without this check they'd fall through to the // customer /home below instead of the staff shell + Calendar tab // their nav role (see lib/navigation/nav-config.ts) actually gives // them once they land somewhere in it. if (await isSuperAdmin(session.user.id)) redirect("/owner/calendar"); redirect("/home"); } const [branding, business] = await Promise.all([getBranding(), getPrimaryBusiness()]); const guestBookingEnabled = business.bookingRule?.allowGuestBooking ?? false; // The hero card's photo — the welcome-specific background the owner // uploaded for this exact screen takes priority (it was purpose-built for // it, see BrandingInfo.welcomeBackgroundMobileUrl/DesktopUrl); the // general-purpose cover shot is only a fallback for a business that // configured a cover image but never set a dedicated welcome background. // Desktop and mobile keep their own independent images, same as before. const heroImageMobileUrl = branding.welcomeBackgroundMobileUrl ?? branding.welcomeBackgroundDesktopUrl ?? branding.coverImageUrl; const heroImageDesktopUrl = branding.welcomeBackgroundDesktopUrl ?? branding.welcomeBackgroundMobileUrl ?? branding.coverImageUrl; const hasHeroImage = !!(heroImageMobileUrl || heroImageDesktopUrl); return (
Find, book & manage your appointments with ease.