Base app architecture:

    Route groups for customer, staff and owner.
* Reusable design system with around 20 UI components.
* Complete Prisma schema.
* Authentication with email/password and Google.
* Role and permission model.
* Protected routes.
* Clean separation between features, services, components and shared utilities.
This commit is contained in:
Stefan Lazic committed 2026-08-02 17:47:23 +01:00
1 parent 468d163299
commit 090646fdfd
201 files changed
+31984

No files matched your search

+380
View File
@@ -0,0 +1,380 @@
<html lang="en">
<head>
<script>
window.FontAwesomeConfig = {
autoReplaceSvg: 'nest'
};
</script>
<script
src="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/js/all.min.js"
crossorigin="anonymous" referrerpolicy="no-referrer"></script>
<meta charset="utf-8">
<meta name="viewport"
content="width=device-width, initial-scale=1, viewport-fit=cover">
<title>Home</title>
<script src="https://cdn.tailwindcss.com"></script>
<link rel="stylesheet"
href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css">
<script>
tailwind.config = {
theme:
{
extend:
{
colors:
{
ink: '#111b15',
stone: '#f4f6f4',
surface: '#ffffff',
muted: '#6c7870',
line: '#e1e7e2',
accent: '#10b981'
},
fontFamily:
{
sans: ['Inter', 'sans-serif']
},
borderRadius:
{
jumbo: '1rem',
tile: '0.75rem'
}
}
}
}
</script>
<style>
.no-scrollbar::-webkit-scrollbar
{
display: none;
}
.nav-blur
{
backdrop-filter: blur(20px);
-webkit-backdrop-filter: blur(20px);
}
</style>
</head>
<body class="bg-stone text-ink overflow-x-hidden pb-32">
<!-- Top Hero Section -->
<meta charset="utf-8">
<meta name="viewport"
content="width=device-width, initial-scale=1, viewport-fit=cover">
<title>The Cut &amp; Shave Co. — TrimTime</title>
<link rel="stylesheet"
href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css">
<section class="relative">
<div class="h-72 w-full overflow-hidden"><img
src="https://storage.googleapis.com/uxpilot-auth.appspot.com/gen_6f41884203_51631d7a07f0b3a6.png"
alt="exterior and interior of a premium heritage barbershop, dark wood, classic signage, atmospheric ligh"
class="w-full h-full object-cover"></div>
<!-- Header Overlay Buttons -->
<!-- Photos Overlay --><button
class="absolute bottom-6 right-6 bg-white/90 backdrop-blur-sm px-4 py-2 rounded-lg text-[10px] font-bold uppercase tracking-widest shadow-sm">
Show all photos
</button>
</section><!-- Gallery Preview -->
<div class="flex gap-1 overflow-x-auto no-scrollbar py-1 bg-stone"><img
src="https://storage.googleapis.com/uxpilot-auth.appspot.com/gen_e586b8a854_62ba2a631fca3c08.png"
alt="men's sharp fade haircut, side profile, barbershop background"
class="w-24 h-20 object-cover"><img
src="https://storage.googleapis.com/uxpilot-auth.appspot.com/gen_782a439f88_fc2c5d9ed81f2686.png"
alt="barber grooming a beard with precision, warm lighting"
class="w-24 h-20 object-cover"><img
src="https://storage.googleapis.com/uxpilot-auth.appspot.com/gen_e188dc18b7_604cc720c67b47cc.png"
alt="classic pompadour hairstyle, professional studio lighting"
class="w-24 h-20 object-cover"><img
src="https://storage.googleapis.com/uxpilot-auth.appspot.com/gen_312c057f78_b7165e53db4b5429.png"
alt="modern beard trim and shape up" class="w-24 h-20 object-cover">
<div class="relative w-24 h-20 shrink-0"><img
src="https://storage.googleapis.com/uxpilot-auth.appspot.com/gen_2b32eca278_abfffae3ac340230.png"
alt="barbershop interior wide shot"
class="w-full h-full object-cover brightness-50"><span
class="absolute inset-0 flex items-center justify-center text-white font-bold text-sm">+29</span>
</div>
</div>
<main class="bg-white">
<!-- Shop Info -->
<section class="px-6 py-6">
<h1 class="text-2xl font-bold tracking-tight mb-1">Blake Heritage
Barbershop</h1>
<p class="text-xs text-muted mb-3">79 Joel Street, HA6 1LW, Northwood,
Northwood</p>
<div class="flex items-center gap-3 text-sm mb-4">
<div class="flex items-center gap-1 text-amber-500"><i
class="fa-solid fa-star"></i><i class="fa-solid fa-star"></i><i
class="fa-solid fa-star"></i><i class="fa-solid fa-star"></i><i
class="fa-solid fa-star"></i></div><span
class="font-bold">5.0</span><a href="#"
class="text-blue-600 underline">1,142 reviews</a>
</div>
<p class="text-[10px] font-bold uppercase tracking-widest text-muted">
Entrepreneur</p>
</section><!-- Policy Link -->
<section class="px-6 py-4 border-t border-line"><button
class="w-full flex items-center justify-between group">
<div class="flex items-center gap-3">
<div
class="w-8 h-8 rounded-lg bg-green-50 flex items-center justify-center text-green-600">
<i class="fa-solid fa-shield-halved"></i></div><span
class="text-sm font-medium">Review policies and safety</span>
</div><i
class="fa-solid fa-chevron-right text-muted group-hover:translate-x-1 transition-transform"></i>
</button></section><!-- Tabbed Menu -->
<section
class="sticky top-0 z-40 bg-white border-b border-line overflow-x-auto no-scrollbar">
<div class="flex px-6"><button onclick="switchTab('services')"
id="tab-services"
class="tab-btn px-4 py-4 text-[10px] font-bold uppercase tracking-[0.15em] border-b-2 border-ink whitespace-nowrap">Services</button><button
onclick="switchTab('portfolio')" id="tab-portfolio"
class="tab-btn px-4 py-4 text-[10px] font-bold uppercase tracking-[0.15em] border-b-2 border-transparent text-muted whitespace-nowrap">Portfolio</button><button
onclick="switchTab('details')" id="tab-details"
class="tab-btn px-4 py-4 text-[10px] font-bold uppercase tracking-[0.15em] border-b-2 border-transparent text-muted whitespace-nowrap">Details</button>
</div>
</section><!-- Tab Contents -->
<div id="content-services" class="tab-content block">
<!-- Search -->
<div class="px-6 py-4">
<div class="relative"><i
class="fa-solid fa-magnifying-glass absolute left-4 top-1/2 -translate-y-1/2 text-muted"></i><input
type="text" placeholder="Search for service"
class="w-full bg-stone/50 border border-line rounded-xl pl-12 pr-4 py-4 focus:ring-2 focus:ring-ink outline-none text-sm transition-all">
</div>
</div><!-- Categories -->
<div class="px-6 flex gap-2 overflow-x-auto no-scrollbar mb-6"><button
class="px-4 py-2 rounded-full border border-ink bg-ink text-white text-[10px] font-bold whitespace-nowrap">Hair
&amp; Beard Services Senior B...</button><button
class="px-4 py-2 rounded-full border border-line bg-stone text-ink text-[10px] font-bold whitespace-nowrap">(Junior
Barber)</button></div><!-- Service List -->
<div class="px-6 space-y-6 pb-12">
<div>
<h3 class="text-sm font-bold mb-4 flex items-center gap-2">👍 Hair
&amp; Beard Services Senior Barber</h3>
<div class="space-y-6">
<div class="flex justify-between items-start gap-4">
<div class="flex-1">
<h4 class="text-sm font-medium mb-1">Haircut &amp; Style (Skin
fade/Taper not included)</h4>
<p class="text-xs text-muted">30m</p>
</div>
<div class="text-right">
<p class="font-bold mb-2">£22.00</p><button
onclick="location.href='Schedule__mobile.html'"
class="bg-blue-500 text-white px-6 py-2 rounded-lg text-xs font-bold uppercase tracking-widest hover:bg-blue-600 transition-colors">Book</button>
</div>
</div>
<div
class="flex justify-between items-start gap-4 pt-6 border-t border-stone">
<div class="flex-1">
<h4 class="text-sm font-medium mb-1">Skinfade / Taper &amp;
Style (Beard not included)</h4>
<p class="text-xs text-muted">30m</p>
</div>
<div class="text-right">
<p class="font-bold mb-2">£25.00</p><button
onclick="location.href='Schedule__mobile.html'"
class="bg-blue-500 text-white px-6 py-2 rounded-lg text-xs font-bold uppercase tracking-widest hover:bg-blue-600 transition-colors">Book</button>
</div>
</div>
<div
class="flex justify-between items-start gap-4 pt-6 border-t border-stone">
<div class="flex-1">
<h4 class="text-sm font-medium mb-1">Haircut &amp; Beard
(Skinfade not included)</h4>
<p class="text-xs text-muted">40m</p>
</div>
<div class="text-right">
<p class="font-bold mb-2">£30.00</p><button
onclick="location.href='Schedule__mobile.html'"
class="bg-blue-500 text-white px-6 py-2 rounded-lg text-xs font-bold uppercase tracking-widest hover:bg-blue-600 transition-colors">Book</button>
</div>
</div>
</div>
</div>
<div class="pt-8">
<h3 class="text-sm font-bold mb-4">Oap Haircut</h3>
<div class="flex justify-between items-start gap-4">
<div class="flex-1">
<h4 class="text-sm font-medium mb-1">Standard OAP Cut</h4>
<p class="text-xs text-muted">20m</p>
</div>
<div class="text-right">
<p class="font-bold mb-2">£15.00+</p><button
onclick="location.href='Schedule__mobile.html'"
class="bg-blue-500 text-white px-6 py-2 rounded-lg text-xs font-bold uppercase tracking-widest hover:bg-blue-600 transition-colors">Book</button>
</div>
</div>
</div>
</div>
</div>
<div id="content-reviews" class="tab-content hidden p-6">
<h3 class="text-lg font-bold mb-4">Reviews</h3>
<p class="text-sm text-muted">Review content goes here...</p>
</div>
<div id="content-portfolio" class="tab-content hidden">
<div class="px-6 py-4 flex gap-2 overflow-x-auto no-scrollbar"><button
class="px-4 py-2 rounded-full bg-ink text-white text-[10px] font-bold">All</button><button
class="px-4 py-2 rounded-full bg-stone text-ink text-[10px] font-bold">Fades</button><button
class="px-4 py-2 rounded-full bg-stone text-ink text-[10px] font-bold">Beards</button><button
class="px-4 py-2 rounded-full bg-stone text-ink text-[10px] font-bold">Long
Hair</button></div>
<div class="grid grid-cols-2 gap-1 bg-stone p-1"><img
src="https://storage.googleapis.com/uxpilot-auth.appspot.com/gen_da55042625_823a14a0d2abd502.png"
alt="sharp skin fade haircut detailed work"
class="w-full aspect-square object-cover"><img
src="https://storage.googleapis.com/uxpilot-auth.appspot.com/gen_15370a1287_f764d58e3bd92072.png"
alt="professional beard line up and trim"
class="w-full aspect-square object-cover"><img
src="https://storage.googleapis.com/uxpilot-auth.appspot.com/gen_465184396a_408d980cf6a78b99.png"
alt="classic pompadour styling"
class="w-full aspect-square object-cover"><img
src="https://storage.googleapis.com/uxpilot-auth.appspot.com/gen_b8c3765997_e56374cb93dd94a8.png"
alt="textured crop haircut for men"
class="w-full aspect-square object-cover"><img
src="https://storage.googleapis.com/uxpilot-auth.appspot.com/gen_8bee30dac8_9efb939a95f39e70.png"
alt="clean tapered haircut profile"
class="w-full aspect-square object-cover"><img
src="https://storage.googleapis.com/uxpilot-auth.appspot.com/gen_73a26d2bf3_6c12eeca17949780.png"
alt="master barber at work with clippers"
class="w-full aspect-square object-cover"></div>
</div>
<div id="content-packages" class="tab-content hidden p-6">
<h3 class="text-lg font-bold mb-4">Packages</h3>
<p class="text-sm text-muted">Packages content goes here...</p>
</div>
<div id="content-details" class="tab-content hidden">
<!-- Map Section -->
<div class="relative h-48 bg-stone"><img
src="https://storage.googleapis.com/uxpilot-auth.appspot.com/gen_48ef4fd311_eab8ed092996a6b5.png"
alt="simplified stylized street map of Northwood London area with a pin icon"
class="w-full h-full object-cover">
<div
class="absolute inset-x-6 bottom-4 bg-white p-4 rounded-xl shadow-lg border border-line flex items-center justify-between">
<div>
<h4 class="text-xs font-bold mb-1">Blake Heritage Barbershop</h4>
<p class="text-[10px] text-muted">79 Joel Street, HA6 1LW</p>
</div><button
class="w-10 h-10 rounded-full bg-stone flex items-center justify-center"><i
class="fa-solid fa-location-arrow text-blue-600"></i></button>
</div>
</div><!-- About -->
<section class="px-6 py-8">
<h3
class="text-[10px] font-bold uppercase tracking-widest text-muted mb-4">
About Us</h3>
<p class="text-sm leading-relaxed text-gray-700">
Blake Heritage has come to Northwood! Check our Instagram
@Blake.Heritage.Barbershop for more info..
</p>
</section><!-- Staff -->
<section class="px-6 pb-8">
<h3
class="text-[10px] font-bold uppercase tracking-widest text-muted mb-6">
Staffers</h3>
<div class="flex gap-6 overflow-x-auto no-scrollbar">
<div class="w-20 shrink-0 text-center"><img
src="https://storage.googleapis.com/uxpilot-auth.appspot.com/avatars/avatar-2.jpg"
alt="Jay"
class="w-20 h-20 rounded-full object-cover mb-2 border border-line">
<p class="text-xs font-medium">Jay The Bar...</p>
</div>
<div class="w-20 shrink-0 text-center"><img
src="https://storage.googleapis.com/uxpilot-auth.appspot.com/avatars/avatar-3.jpg"
alt="Issa"
class="w-20 h-20 rounded-full object-cover mb-2 border border-line">
<p class="text-xs font-medium">Barber Issa</p>
</div>
<div class="w-20 shrink-0 text-center"><img
src="https://storage.googleapis.com/uxpilot-auth.appspot.com/avatars/avatar-4.jpg"
alt="Alfie"
class="w-20 h-20 rounded-full object-cover mb-2 border border-line">
<p class="text-xs font-medium">Alfie (Junior...</p>
</div>
</div>
</section><!-- Hours -->
<section class="px-6 pb-8">
<h3
class="text-[10px] font-bold uppercase tracking-widest text-muted mb-6">
Contact &amp; Business Hours</h3>
<div class="space-y-4">
<div class="flex justify-between items-center text-sm"><span
class="text-gray-600">Monday</span><span
class="font-medium text-muted">Closed</span></div>
<div class="flex justify-between items-center text-sm"><span
class="text-gray-600">Tuesday</span><span
class="font-bold">10:00 - 19:00</span></div>
<div class="flex justify-between items-center text-sm"><span
class="text-gray-600">Wednesday</span><span
class="font-bold">10:00 - 19:00</span></div>
<div class="flex justify-between items-center text-sm"><span
class="text-gray-600">Thursday</span><span
class="font-bold">10:00 - 19:30</span></div>
<div class="flex justify-between items-center text-sm"><span
class="text-gray-600">Friday</span><span class="font-bold">10:00
- 19:00</span></div>
</div>
</section><!-- Amenities -->
<section class="px-6 pb-12">
<h3
class="text-[10px] font-bold uppercase tracking-widest text-muted mb-4">
Venue Amenities</h3>
<div class="grid grid-cols-2 gap-4">
<div class="flex items-center gap-3 text-sm"><i
class="fa-solid fa-car text-muted"></i><span>Free Parking</span>
</div>
<div class="flex items-center gap-3 text-sm"><i
class="fa-solid fa-wifi text-muted"></i><span>Guest WiFi</span>
</div>
</div>
</section>
</div>
</main>
<script>
function switchTab(tabId)
{
// Hide all content
document.querySelectorAll('.tab-content').forEach(content =>
{
content.classList.add('hidden');
content.classList.remove('block');
});
// Show selected content
const activeContent = document.getElementById('content-' + tabId);
activeContent.classList.remove('hidden');
activeContent.classList.add('block');
// Reset tab styles
document.querySelectorAll('.tab-btn').forEach(btn =>
{
btn.classList.remove('border-ink');
btn.classList.add('border-transparent', 'text-muted');
});
// Highlight active tab
const activeTab = document.getElementById('tab-' + tabId);
activeTab.classList.add('border-ink');
activeTab.classList.remove('border-transparent', 'text-muted');
}
</script>
<!-- Bottom Navigation -->
<nav class="fixed bottom-0 left-0 right-0 z-50 bg-white border-t border-line py-4 px-10 flex justify-between items-center">
<a href="Home__mobile.html" class="flex flex-col items-center gap-1 text-ink">
<i class="fa-solid fa-house text-xl"></i>
<span class="text-[10px] font-bold uppercase tracking-widest">Home</span>
</a>
<a href="Appointments__mobile.html" class="flex flex-col items-center gap-1 text-muted hover:text-ink transition-colors">
<i class="fa-solid fa-calendar-check text-xl"></i>
<span class="text-[10px] font-bold uppercase tracking-widest">Bookings</span>
</a>
<a href="Settings__mobile.html" class="flex flex-col items-center gap-1 text-muted hover:text-ink transition-colors">
<i class="fa-solid fa-user text-xl"></i>
<span class="text-[10px] font-bold uppercase tracking-widest">Settings</span>
</a>
</nav>
</body>
</html>