feat: add Login navigation and beautiful staff authentication page (fully translated sv/en/hi/ur, mobile-optimized form with Askim/Backaplan dropdown, premium theme graphics, placeholder 'backend under construction' message)

This commit is contained in:
Zeeshan Khan
2026-06-02 19:03:49 +02:00
parent 5eddef80e6
commit 380f7bc9a6
3 changed files with 378 additions and 1 deletions
+279
View File
@@ -0,0 +1,279 @@
'use client';
import Navbar from "@/components/Navbar";
import Footer from "@/components/Footer";
import { useLanguage } from "@/lib/language-context";
import { getTranslation } from "@/lib/translations";
import { useState } from 'react';
import { motion, AnimatePresence } from "framer-motion";
import { User, Lock, MapPin, LogIn, Phone, MessageCircle } from "lucide-react";
/**
* =============================================================================
* STAFF LOGIN / AUTHENTICATION PAGE
* =============================================================================
*
* Beautiful, theme-matched placeholder login experience.
* - Fully language compatible (sv default + en/hi/ur)
* - No real backend yet — always shows friendly "under construction" message
* - Mobile-first: large tap targets, excellent spacing, easy form on phones
* - Desktop: elegant split layout with dark luxury graphic panel + form
* - Uses existing design tokens (gold accents, cream bg, rounded cards, serif titles)
*
* Future: when real auth is added, this will become the entry to a protected staff area
* (per-site menus, orders, inventory etc. for Askim vs Backaplan).
*/
export default function LoginPage() {
const { language } = useLanguage();
const t = getTranslation(language);
const [formData, setFormData] = useState({
username: '',
password: '',
site: '',
});
const [isSubmitted, setIsSubmitted] = useState(false);
const handleChange = (e: React.ChangeEvent<HTMLInputElement | HTMLSelectElement>) => {
const { name, value } = e.target;
setFormData((prev) => ({ ...prev, [name]: value }));
};
const handleSubmit = (e: React.FormEvent<HTMLFormElement>) => {
e.preventDefault();
// Placeholder behaviour: always show the construction notice.
// No validation beyond native required fields — real auth coming later.
setIsSubmitted(true);
};
const resetForm = () => {
setFormData({ username: '', password: '', site: '' });
setIsSubmitted(false);
};
return (
<div className="min-h-screen bg-[#F8F5F0] text-[#2C2A26]">
<Navbar />
<main className="pt-16 pb-20">
{/* Elegant header */}
<div className="max-w-5xl mx-auto px-6 pt-8 text-center">
<div className="inline-flex items-center gap-2 rounded-full bg-[#B38B4D]/10 px-4 py-1 text-[#B38B4D] text-[10px] tracking-[3.5px] font-medium mb-4">
STAFF PORTAL
</div>
<h1 className="font-serif text-5xl md:text-6xl tracking-[-2.2px] leading-none mb-4">
{t.auth.title}
</h1>
<p className="mx-auto max-w-md text-lg text-[#6B665F]">
{t.auth.subtitle}
</p>
</div>
{/* Content area — beautiful split layout on desktop, clean single column on mobile */}
<div className="mx-auto max-w-5xl px-6 mt-10">
<div className="grid items-start gap-8 md:grid-cols-5">
{/* LEFT: Premium dark graphic panel (desktop only). Matches royal theme with gold details. */}
<div className="hidden md:col-span-2 md:block">
<div className="sticky top-24 flex h-[520px] flex-col justify-between overflow-hidden rounded-3xl border border-[#c99a2e]/20 bg-gradient-to-br from-[#101724] via-[#1a1816] to-[#2C2A26] p-10 text-white shadow-2xl">
{/* Subtle gold frame lines */}
<div className="absolute inset-x-0 top-0 h-px bg-gradient-to-r from-transparent via-[#c99a2e] to-transparent" />
<div className="absolute inset-x-0 bottom-0 h-px bg-gradient-to-r from-transparent via-[#c99a2e]/50 to-transparent" />
<div>
<div className="mb-8 inline-flex h-16 w-16 items-center justify-center rounded-2xl border border-[#c99a2e]/30 bg-white/5 p-3 backdrop-blur">
<img
src="/images/logo/logo1.png"
alt="Shahi Kitchen"
className="h-full w-full object-contain"
/>
</div>
<div className="font-serif text-[42px] leading-[0.95] tracking-[-1.8px]">
Shahi<br />Kitchen
</div>
<div className="mt-1 text-sm font-medium tracking-[2.5px] text-[#c99a2e]">
STAFF ACCESS
</div>
</div>
<div>
<div className="my-6 h-px w-10 bg-[#c99a2e]/40" />
<p className="max-w-[220px] text-sm leading-relaxed text-white/70">
Two locations serving royal Indian &amp; Pakistani hospitality in Gothenburg since 2016.
</p>
<div className="mt-5 text-[10px] uppercase tracking-[2.5px] text-[#c99a2e]/60">
ASKIM BACKAPLAN
</div>
</div>
</div>
</div>
{/* RIGHT / MOBILE: The actual elegant login card */}
<div className="md:col-span-3">
<div className="rounded-3xl border border-[#EDE6D9] bg-white p-8 shadow-xl md:p-10">
{/* Mobile-only logo accent for visual continuity */}
<div className="mb-6 flex justify-center md:hidden">
<div className="flex h-14 w-14 items-center justify-center rounded-2xl border border-[#c99a2e]/30 bg-[#F8F5F0] p-2.5">
<img src="/images/logo/logo1.png" alt="Shahi Kitchen" className="h-full w-full object-contain" />
</div>
</div>
<AnimatePresence mode="wait">
{!isSubmitted ? (
<motion.div
key="login-form"
initial={{ opacity: 0, y: 8 }}
animate={{ opacity: 1, y: 0 }}
exit={{ opacity: 0, y: -8 }}
transition={{ duration: 0.2 }}
>
<form onSubmit={handleSubmit} className="space-y-6">
{/* Username */}
<div>
<label htmlFor="username" className="mb-2 block text-sm font-semibold tracking-wide text-[#6B665F]">
{t.auth.usernameLabel}
</label>
<div className="relative">
<User className="absolute left-4 top-4 h-5 w-5 text-[#B38B4D]" />
<input
id="username"
name="username"
type="text"
value={formData.username}
onChange={handleChange}
placeholder={t.auth.usernamePlaceholder}
required
className="w-full rounded-2xl border border-[#EDE6D9] bg-[#F8F5F0] py-4 pl-12 pr-4 text-[17px] placeholder:text-[#8A8478] transition-all outline-none focus:border-[#B38B4D] focus:bg-white focus:ring-1 focus:ring-[#B38B4D]/20"
/>
</div>
</div>
{/* Password */}
<div>
<label htmlFor="password" className="mb-2 block text-sm font-semibold tracking-wide text-[#6B665F]">
{t.auth.passwordLabel}
</label>
<div className="relative">
<Lock className="absolute left-4 top-4 h-5 w-5 text-[#B38B4D]" />
<input
id="password"
name="password"
type="password"
value={formData.password}
onChange={handleChange}
placeholder={t.auth.passwordPlaceholder}
required
className="w-full rounded-2xl border border-[#EDE6D9] bg-[#F8F5F0] py-4 pl-12 pr-4 text-[17px] placeholder:text-[#8A8478] transition-all outline-none focus:border-[#B38B4D] focus:bg-white focus:ring-1 focus:ring-[#B38B4D]/20"
/>
</div>
</div>
{/* Site / Location dropdown — Askim or Backaplan */}
<div>
<label htmlFor="site" className="mb-2 block text-sm font-semibold tracking-wide text-[#6B665F]">
{t.auth.siteLabel}
</label>
<div className="relative">
<MapPin className="pointer-events-none absolute left-4 top-4 z-10 h-5 w-5 text-[#B38B4D]" />
<select
id="site"
name="site"
value={formData.site}
onChange={handleChange}
required
className="w-full cursor-pointer appearance-none rounded-2xl border border-[#EDE6D9] bg-[#F8F5F0] py-4 pl-12 pr-10 text-[17px] transition-all outline-none focus:border-[#B38B4D] focus:bg-white focus:ring-1 focus:ring-[#B38B4D]/20"
>
<option value="">{t.auth.sitePlaceholder}</option>
<option value="askim">{t.auth.askim}</option>
<option value="backaplan">{t.auth.backaplan}</option>
</select>
{/* Custom dropdown arrow for polish */}
<div className="pointer-events-none absolute right-4 top-4 text-[#B38B4D]"></div>
</div>
<p className="mt-1.5 text-[11px] text-[#8A8478]">Select the location you are working at today.</p>
</div>
{/* Primary gold action button — large & mobile friendly */}
<button
type="submit"
className="btn-primary mt-2 flex w-full items-center justify-center gap-3 rounded-2xl py-4 text-base font-semibold tracking-[0.5px] active:scale-[0.985] transition"
>
<LogIn className="h-5 w-5" />
{t.auth.submit}
</button>
</form>
<p className="mt-8 text-center text-[11px] tracking-wide text-[#8A8478]">
{t.auth.footerNote}
</p>
</motion.div>
) : (
/* Beautiful result state — always shows the construction notice */
<motion.div
key="construction-result"
initial={{ opacity: 0, y: 10 }}
animate={{ opacity: 1, y: 0 }}
className="text-center"
>
<div className="mx-auto mb-6 flex h-16 w-16 items-center justify-center rounded-full bg-[#B38B4D]/10">
<LogIn className="h-8 w-8 text-[#B38B4D]" />
</div>
<h2 className="mb-3 font-serif text-3xl tracking-[-1px]">
{t.auth.construction.title}
</h2>
<p className="mx-auto max-w-md text-[15px] leading-relaxed text-[#6B665F]">
{t.auth.construction.message}
</p>
{/* Helpful contact actions (real numbers from the site) */}
<div className="mt-8 space-y-3">
<a
href="tel:031288910"
className="flex w-full items-center justify-center gap-2 rounded-2xl border border-[#EDE6D9] py-3.5 text-sm font-medium transition active:bg-[#F8F5F0] hover:bg-[#F8F5F0]"
>
<Phone className="h-4 w-4" />
{t.auth.construction.contact} 031-28 89 10
</a>
<a
href="https://wa.me/46739381089"
target="_blank"
rel="noopener noreferrer"
className="flex w-full items-center justify-center gap-2 rounded-2xl border border-[#EDE6D9] py-3.5 text-sm font-medium transition active:bg-[#F8F5F0] hover:bg-[#F8F5F0]"
>
<MessageCircle className="h-4 w-4" />
WhatsApp +46 73 938 10 89
</a>
<button
onClick={resetForm}
className="mt-2 w-full rounded-2xl bg-[#101724] py-3.5 text-sm font-semibold text-white active:bg-black transition"
>
{t.auth.construction.tryAgain}
</button>
</div>
<p className="mt-6 text-[10px] text-[#8A8478]">
We appreciate your patience while we build a seamless experience.
</p>
</motion.div>
)}
</AnimatePresence>
</div>
{/* Small trust line */}
<p className="mt-5 text-center text-[10px] text-[#8A8478] tracking-[1px]">
SHAHI KITCHEN GOTHENBURG EST 2016
</p>
</div>
</div>
</div>
</main>
<Footer />
</div>
);
}
+3 -1
View File
@@ -3,7 +3,7 @@
import { useState, useEffect } from "react";
import Link from "next/link";
import { useCart } from "./CartContext";
import { ShoppingBag, ArrowRight, Home, UtensilsCrossed, MapPin, Star, Phone, X } from "lucide-react";
import { ShoppingBag, ArrowRight, Home, UtensilsCrossed, MapPin, Star, Phone, X, LogIn } from "lucide-react";
import LanguageSwitcher from "./LanguageSwitcher";
import { useLanguage } from "@/lib/language-context";
import { getTranslation } from "@/lib/translations";
@@ -39,6 +39,7 @@ export default function Navbar({ variant = "default" }: NavbarProps) {
{ href: "/", label: t.nav.home },
{ href: "/menu", label: t.nav.menu },
{ href: "/locations", label: t.nav.locations },
{ href: "/login", label: t.nav.login },
{ href: "/#experience", label: t.nav.experience },
{ href: "/#contact", label: t.nav.contact },
];
@@ -232,6 +233,7 @@ export default function Navbar({ variant = "default" }: NavbarProps) {
link.href === '/' ? Home :
link.href === '/menu' ? UtensilsCrossed :
link.href === '/locations' ? MapPin :
link.href === '/login' ? LogIn :
link.href.includes('experience') ? Star : Phone;
return (
+96
View File
@@ -14,6 +14,7 @@ export const translations = {
home: 'Home',
menu: 'Menu',
locations: 'Locations',
login: 'Login',
experience: 'Experience',
contact: 'Contact',
},
@@ -172,6 +173,29 @@ export const translations = {
messageThanks: 'Thank you!',
},
// Authentication / Staff Login Page (fully translated, placeholder only)
auth: {
title: 'Staff Login',
subtitle: 'Secure access for Shahi Kitchen team members at our locations',
usernameLabel: 'Username',
usernamePlaceholder: 'Enter your username',
passwordLabel: 'Password',
passwordPlaceholder: 'Enter your password',
siteLabel: 'Select Site',
sitePlaceholder: 'Choose your branch',
askim: 'Askim (Sisjön)',
backaplan: 'Backaplan',
submit: 'Sign In',
submitting: 'Signing in...',
construction: {
title: 'Authentication Under Construction',
message: 'Our staff login system is currently under development. The backend authentication service is not yet available. Please try again later. For immediate assistance with orders or reservations, please contact the restaurant directly via phone or WhatsApp.',
contact: 'Contact Restaurant',
tryAgain: 'Close & Try Later',
},
footerNote: 'This portal is for authorized Shahi Kitchen staff only.',
},
// Full Menu Page
menu: {
title: 'Our Menu',
@@ -191,6 +215,7 @@ export const translations = {
home: 'Hem',
menu: 'Meny',
locations: 'Platser',
login: 'Logga in',
experience: 'Upplevelse',
contact: 'Kontakt',
},
@@ -343,6 +368,29 @@ export const translations = {
messageThanks: 'Tack!',
},
// Authentication / Staff Login Page (fully translated, placeholder only)
auth: {
title: 'Personalloggning',
subtitle: 'Säker åtkomst för Shahi Kitchen teammedlemmar vid våra platser',
usernameLabel: 'Användarnamn',
usernamePlaceholder: 'Ange ditt användarnamn',
passwordLabel: 'Lösenord',
passwordPlaceholder: 'Ange ditt lösenord',
siteLabel: 'Välj plats',
sitePlaceholder: 'Välj din restaurang',
askim: 'Askim (Sisjön)',
backaplan: 'Backaplan',
submit: 'Logga in',
submitting: 'Loggar in...',
construction: {
title: 'Autentisering under uppbyggnad',
message: 'Vårt personallogginssystem är för närvarande under utveckling. Backend-autentiseringstjänsten är inte tillgänglig ännu. Vänligen försök igen senare. För omedelbar hjälp med beställningar eller bokningar, kontakta restaurangen direkt via telefon eller WhatsApp.',
contact: 'Kontakta restaurangen',
tryAgain: 'Stäng & försök senare',
},
footerNote: 'Denna portal är endast för auktoriserad Shahi Kitchen-personal.',
},
// Full Menu Page
menu: {
title: 'Vår Meny',
@@ -362,6 +410,7 @@ export const translations = {
home: 'होम',
menu: 'मेन्यू',
locations: 'स्थान',
login: 'लॉगिन',
experience: 'अनुभव',
contact: 'संपर्क',
},
@@ -523,6 +572,29 @@ export const translations = {
messageTotal: 'कुल',
messageThanks: 'धन्यवाद!',
},
// Authentication / Staff Login Page (fully translated, placeholder only)
auth: {
title: 'स्टाफ लॉगिन',
subtitle: 'शाही किचन टीम सदस्यों के लिए सुरक्षित पहुंच',
usernameLabel: 'उपयोगकर्ता नाम',
usernamePlaceholder: 'अपना उपयोगकर्ता नाम दर्ज करें',
passwordLabel: 'पासवर्ड',
passwordPlaceholder: 'अपना पासवर्ड दर्ज करें',
siteLabel: 'साइट चुनें',
sitePlaceholder: 'अपनी शाखा चुनें',
askim: 'Askim (Sisjön)',
backaplan: 'Backaplan',
submit: 'साइन इन करें',
submitting: 'साइन इन हो रहा है...',
construction: {
title: 'प्रमाणीकरण निर्माणाधीन',
message: 'हमारा स्टाफ लॉगिन सिस्टम वर्तमान में विकास के अधीन है। बैकएंड प्रमाणीकरण सेवा अभी उपलब्ध नहीं है। कृपया बाद में पुनः प्रयास करें। तत्काल सहायता के लिए, कृपया रेस्तरां से सीधे फोन या व्हाट्सएप के माध्यम से संपर्क करें।',
contact: 'रेस्तरां से संपर्क करें',
tryAgain: 'बंद करें और बाद में प्रयास करें',
},
footerNote: 'यह पोर्टल केवल अधिकृत शाही किचन स्टाफ के लिए है।',
},
},
ur: {
@@ -530,6 +602,7 @@ export const translations = {
home: 'ہوم',
menu: 'مینو',
locations: 'مقامات',
login: 'لاگ ان',
experience: 'تجربہ',
contact: 'رابطہ',
},
@@ -691,6 +764,29 @@ export const translations = {
messageTotal: 'کل',
messageThanks: 'شکریہ!',
},
// Authentication / Staff Login Page (fully translated, placeholder only)
auth: {
title: 'اسٹاف لاگ ان',
subtitle: 'شاہی کچن ٹیم کے ممبران کے لیے محفوظ رسائی',
usernameLabel: 'صارف نام',
usernamePlaceholder: 'اپنا صارف نام درج کریں',
passwordLabel: 'پاس ورڈ',
passwordPlaceholder: 'اپنا پاس ورڈ درج کریں',
siteLabel: 'سائٹ منتخب کریں',
sitePlaceholder: 'اپنی برانچ منتخب کریں',
askim: 'Askim (Sisjön)',
backaplan: 'Backaplan',
submit: 'سائن ان کریں',
submitting: 'سائن ان ہو رہا ہے...',
construction: {
title: 'تصدیق زیر تعمیر',
message: 'ہمارا اسٹاف لاگ ان سسٹم فی الحال ترقی کے مراحل میں ہے۔ بیک اینڈ تصدیقی سروس ابھی دستیاب نہیں ہے۔ براہ کرم بعد میں دوبارہ کوشش کریں۔ فوری مدد کے لیے، براہ کرم براہ راست فون یا واٹس ایپ کے ذریعے ریستوراں سے رابطہ کریں۔',
contact: 'ریستوراں سے رابطہ کریں',
tryAgain: 'بند کریں اور بعد میں کوشش کریں',
},
footerNote: 'یہ پورٹل صرف مجاز شاہی کچن اسٹاف کے لیے ہے۔',
},
},
} as const;