feat(themes): add Amber Artisan 2-column bento gourmet dark theme
This commit is contained in:
@@ -155,20 +155,31 @@ export const restaurantsRoutes: FastifyPluginAsync = async (app) => {
|
|||||||
return reply.code(400).send({ message: "themeKey is required" });
|
return reply.code(400).send({ message: "themeKey is required" });
|
||||||
}
|
}
|
||||||
|
|
||||||
const { data: themeData } = await supabase
|
let themeId = themeData?.id;
|
||||||
|
if (!themeId) {
|
||||||
|
const { data: newTheme } = await supabase
|
||||||
.from("themes")
|
.from("themes")
|
||||||
|
.insert({
|
||||||
|
key: themeKey,
|
||||||
|
name: themeKey === "artisan" ? "Amber Artisan" : themeKey,
|
||||||
|
config: { primaryColor: "#E5A855", background: "#121316", productLayout: "card", categoryLayout: "tabs" },
|
||||||
|
})
|
||||||
.select("id")
|
.select("id")
|
||||||
.eq("key", themeKey)
|
|
||||||
.maybeSingle();
|
.maybeSingle();
|
||||||
|
|
||||||
if (!themeData) {
|
if (newTheme?.id) {
|
||||||
|
themeId = newTheme.id;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!themeId) {
|
||||||
return reply.code(404).send({ message: "Theme not found" });
|
return reply.code(404).send({ message: "Theme not found" });
|
||||||
}
|
}
|
||||||
|
|
||||||
const { error } = await supabase.from("restaurant_themes").upsert(
|
const { error } = await supabase.from("restaurant_themes").upsert(
|
||||||
{
|
{
|
||||||
restaurant_id: id,
|
restaurant_id: id,
|
||||||
theme_id: themeData.id,
|
theme_id: themeId,
|
||||||
},
|
},
|
||||||
{ onConflict: "restaurant_id" },
|
{ onConflict: "restaurant_id" },
|
||||||
);
|
);
|
||||||
|
|||||||
Binary file not shown.
@@ -31,6 +31,18 @@ export interface ThemeOption {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export const THEME_OPTIONS: ThemeOption[] = [
|
export const THEME_OPTIONS: ThemeOption[] = [
|
||||||
|
{
|
||||||
|
key: "artisan",
|
||||||
|
name: "Amber Artisan",
|
||||||
|
category: "Gurme & Organik / Koyu",
|
||||||
|
color: "#E5A855",
|
||||||
|
badgeBg: "#282B34",
|
||||||
|
badgeText: "#E5A855",
|
||||||
|
bgPreview: "#121316",
|
||||||
|
accent: "Amber Bal & Mat Oniks",
|
||||||
|
desc: "Koyu antrasit mat zemin, kehribar vurgular, modern bento ızgarası ve yuvarlak ürün kartları.",
|
||||||
|
suitableFor: "Gurme şarküteri, kuruyemiş & organik market, fıçı bira evleri, artisan kahveciler",
|
||||||
|
},
|
||||||
{
|
{
|
||||||
key: "elegant",
|
key: "elegant",
|
||||||
name: "Elegant Gold",
|
name: "Elegant Gold",
|
||||||
|
|||||||
@@ -315,7 +315,7 @@ export function PublicMenuClient({
|
|||||||
<div className="bg-stone-900 text-white px-5 py-4 border-b border-stone-800 animate-slide-up">
|
<div className="bg-stone-900 text-white px-5 py-4 border-b border-stone-800 animate-slide-up">
|
||||||
<div className="flex items-center justify-between mb-3">
|
<div className="flex items-center justify-between mb-3">
|
||||||
<p className="text-xs font-bold uppercase tracking-wider text-stone-400">
|
<p className="text-xs font-bold uppercase tracking-wider text-stone-400">
|
||||||
Canlı Tema Önizleme (5 Şablon)
|
Canlı Tema Önizleme (6 Şablon)
|
||||||
</p>
|
</p>
|
||||||
<button
|
<button
|
||||||
type="button"
|
type="button"
|
||||||
@@ -325,7 +325,7 @@ export function PublicMenuClient({
|
|||||||
Kapat ✕
|
Kapat ✕
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
<div className="grid grid-cols-5 gap-2">
|
<div className="grid grid-cols-3 sm:grid-cols-6 gap-2">
|
||||||
{Object.values(THEME_PRESETS).map((preset) => {
|
{Object.values(THEME_PRESETS).map((preset) => {
|
||||||
const isSelected = selectedThemeKey === preset.key;
|
const isSelected = selectedThemeKey === preset.key;
|
||||||
return (
|
return (
|
||||||
@@ -451,15 +451,82 @@ export function PublicMenuClient({
|
|||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
{/* Items Container: Grid / Card / List Layout based on Theme */}
|
||||||
{/* Items Container: Grid / Card / List Layout based on Theme */}
|
{/* Items Container: Grid / Card / List Layout based on Theme */}
|
||||||
<div
|
<div
|
||||||
className={
|
className={
|
||||||
theme.config.productLayout === "list"
|
theme.key === "artisan"
|
||||||
|
? "grid grid-cols-2 gap-3 sm:gap-4"
|
||||||
|
: theme.config.productLayout === "list"
|
||||||
? "space-y-3"
|
? "space-y-3"
|
||||||
: "grid grid-cols-1 gap-3.5"
|
: "grid grid-cols-1 gap-3.5"
|
||||||
}
|
}
|
||||||
>
|
>
|
||||||
{category.menu_items.map((item) => (
|
{category.menu_items.map((item) => {
|
||||||
|
if (theme.key === "artisan") {
|
||||||
|
return (
|
||||||
|
<article
|
||||||
|
key={item.id}
|
||||||
|
onClick={() => setSelectedItem(item)}
|
||||||
|
className="group relative rounded-3xl p-3.5 transition-all duration-300 cursor-pointer border flex flex-col justify-between hover:scale-[1.02] active:scale-[0.98] shadow-md"
|
||||||
|
style={{
|
||||||
|
backgroundColor: theme.cardBg,
|
||||||
|
borderColor: theme.cardBorder,
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{/* Image Container with 3D Dish presentation */}
|
||||||
|
<div className="relative w-full aspect-square rounded-2xl overflow-hidden bg-stone-900/60 mb-3 flex items-center justify-center border border-white/5">
|
||||||
|
{item.image_url ? (
|
||||||
|
<img
|
||||||
|
src={item.image_url}
|
||||||
|
alt={item.name}
|
||||||
|
className="w-full h-full object-cover group-hover:scale-105 transition-transform duration-500"
|
||||||
|
loading="lazy"
|
||||||
|
/>
|
||||||
|
) : (
|
||||||
|
<div className="text-3xl opacity-60">✨</div>
|
||||||
|
)}
|
||||||
|
<span
|
||||||
|
className="absolute top-2 right-2 px-2 py-0.5 rounded-full text-[9px] font-extrabold uppercase tracking-wide shadow-md"
|
||||||
|
style={{ backgroundColor: theme.config.primaryColor, color: "#121316" }}
|
||||||
|
>
|
||||||
|
ÖZEL
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{/* Info */}
|
||||||
|
<div className="flex-1 flex flex-col justify-between">
|
||||||
|
<div>
|
||||||
|
<h3 className="font-bold text-xs sm:text-sm text-white tracking-tight leading-snug line-clamp-1 group-hover:text-amber-400 transition-colors">
|
||||||
|
{item.name}
|
||||||
|
</h3>
|
||||||
|
{item.description ? (
|
||||||
|
<p className="text-[11px] text-stone-400 mt-1 line-clamp-2 leading-relaxed">
|
||||||
|
{item.description}
|
||||||
|
</p>
|
||||||
|
) : null}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="mt-3 pt-2.5 border-t border-white/5 flex items-center justify-between">
|
||||||
|
<span
|
||||||
|
className="text-sm sm:text-base font-black tracking-tight"
|
||||||
|
style={{ color: theme.config.primaryColor }}
|
||||||
|
>
|
||||||
|
₺{item.price.toFixed(0)}
|
||||||
|
</span>
|
||||||
|
<span
|
||||||
|
className="w-6 h-6 rounded-full flex items-center justify-center text-xs font-bold text-stone-950 shadow-sm transition-transform group-hover:scale-110"
|
||||||
|
style={{ backgroundColor: theme.config.primaryColor }}
|
||||||
|
>
|
||||||
|
+
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</article>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
<article
|
<article
|
||||||
key={item.id}
|
key={item.id}
|
||||||
onClick={() => setSelectedItem(item)}
|
onClick={() => setSelectedItem(item)}
|
||||||
@@ -514,7 +581,8 @@ export function PublicMenuClient({
|
|||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
</article>
|
</article>
|
||||||
))}
|
);
|
||||||
|
})}
|
||||||
</div>
|
</div>
|
||||||
</section>
|
</section>
|
||||||
))
|
))
|
||||||
|
|||||||
@@ -16,6 +16,25 @@ export interface ThemePreset {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export const THEME_PRESETS: Record<string, ThemePreset> = {
|
export const THEME_PRESETS: Record<string, ThemePreset> = {
|
||||||
|
artisan: {
|
||||||
|
key: "artisan",
|
||||||
|
name: "Amber Artisan",
|
||||||
|
fontFamily: "heading",
|
||||||
|
config: {
|
||||||
|
primaryColor: "#E5A855",
|
||||||
|
background: "#121316",
|
||||||
|
productLayout: "card",
|
||||||
|
categoryLayout: "tabs",
|
||||||
|
},
|
||||||
|
cardBg: "#1C1E24",
|
||||||
|
cardBorder: "rgba(255, 255, 255, 0.08)",
|
||||||
|
textPrimary: "#FFFFFF",
|
||||||
|
textSecondary: "#9DA3AF",
|
||||||
|
accentBg: "rgba(229, 168, 85, 0.14)",
|
||||||
|
headerGradient: "linear-gradient(180deg, #1A1C22 0%, #121316 100%)",
|
||||||
|
badgeBg: "#282B34",
|
||||||
|
badgeText: "#E5A855",
|
||||||
|
},
|
||||||
elegant: {
|
elegant: {
|
||||||
key: "elegant",
|
key: "elegant",
|
||||||
name: "Elegant Gold",
|
name: "Elegant Gold",
|
||||||
|
|||||||
Reference in New Issue
Block a user