chore: sync full current production website state to Gitea
This commit is contained in:
Binary file not shown.
|
Before Width: | Height: | Size: 25 KiB After Width: | Height: | Size: 3.2 KiB |
@@ -13,7 +13,7 @@
|
||||
* FUTURE:
|
||||
* - When real online ordering launches, this page could show "Order from Askim"
|
||||
* vs "Order from Backaplan" with different delivery radii.
|
||||
* - Instagram handles for each location are mentioned where relevant.
|
||||
* - Both branches now have the same opening hours.
|
||||
*/
|
||||
|
||||
import Navbar from "@/components/Navbar";
|
||||
@@ -98,7 +98,7 @@ export default function LocationsPage() {
|
||||
|
||||
<div>
|
||||
<div className="text-[#B38B4D] text-xs tracking-widest mb-1">OPENING HOURS</div>
|
||||
<div>Varies — please check our Instagram <span className="text-[#B38B4D]">@shahisweets_bp</span> for current hours.</div>
|
||||
<div>Monday – Sunday • 11:00 – 21:00</div>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
|
||||
+16
-50
@@ -1,7 +1,7 @@
|
||||
"use client";
|
||||
|
||||
/**
|
||||
* MENU PAGE — Premium Sidebar + Beautiful Loading Experience
|
||||
* MENU PAGE — Premium Sidebar Navigation
|
||||
*/
|
||||
|
||||
import { useEffect, useState, useMemo } from "react";
|
||||
@@ -11,26 +11,16 @@ import { ScrollTrigger } from "gsap/ScrollTrigger";
|
||||
import Navbar from "@/components/Navbar";
|
||||
import Footer from "@/components/Footer";
|
||||
import { useCart } from "@/components/CartContext";
|
||||
import { motion, AnimatePresence } from "framer-motion";
|
||||
|
||||
gsap.registerPlugin(ScrollTrigger);
|
||||
|
||||
export default function MenuPage() {
|
||||
const [isLoading, setIsLoading] = useState(true);
|
||||
const [activeCategory, setActiveCategory] = useState("All");
|
||||
const [searchQuery, setSearchQuery] = useState("");
|
||||
const [showVegetarianOnly, setShowVegetarianOnly] = useState(false);
|
||||
|
||||
const { addToCart } = useCart();
|
||||
|
||||
// Beautiful loading screen on initial load
|
||||
useEffect(() => {
|
||||
const timer = setTimeout(() => {
|
||||
setIsLoading(false);
|
||||
}, 1350);
|
||||
return () => clearTimeout(timer);
|
||||
}, []);
|
||||
|
||||
// Sidebar categories
|
||||
const sidebarCategories = [
|
||||
{ id: "All", name: "All Dishes" },
|
||||
@@ -73,43 +63,6 @@ export default function MenuPage() {
|
||||
window.scrollTo({ top: 220, behavior: "smooth" });
|
||||
};
|
||||
|
||||
// === BEAUTIFUL LOADING SCREEN ===
|
||||
if (isLoading) {
|
||||
return (
|
||||
<div className="min-h-screen bg-[#fbf7ef] flex items-center justify-center">
|
||||
<div className="text-center">
|
||||
<div className="relative mx-auto mb-8 w-20 h-20">
|
||||
<div className="absolute inset-0 rounded-full border-2 border-[#c99a2e]/30" />
|
||||
<motion.div
|
||||
className="absolute inset-0 rounded-full border-2 border-transparent border-t-[#c99a2e] border-r-[#d4a73d]"
|
||||
animate={{ rotate: 360 }}
|
||||
transition={{ duration: 1.3, repeat: Infinity, ease: "linear" }}
|
||||
/>
|
||||
<div className="absolute inset-[6px] rounded-full border border-[#0f5a4a]/20" />
|
||||
</div>
|
||||
|
||||
<div className="space-y-2">
|
||||
<h2 className="font-serif text-3xl tracking-tight text-[#101724]">
|
||||
Loading the Menu
|
||||
</h2>
|
||||
<p className="text-[#68717f] text-sm tracking-[1.5px]">Preparing the Royal Table...</p>
|
||||
</div>
|
||||
|
||||
<div className="flex justify-center gap-2 mt-6">
|
||||
{[0, 1, 2].map((i) => (
|
||||
<motion.div
|
||||
key={i}
|
||||
className="w-1.5 h-1.5 rounded-full bg-[#c99a2e]"
|
||||
animate={{ opacity: [0.3, 1, 0.3] }}
|
||||
transition={{ duration: 1.1, repeat: Infinity, delay: i * 0.18 }}
|
||||
/>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="min-h-screen bg-[#F8F5F0] text-[#2C2A26]">
|
||||
<Navbar />
|
||||
@@ -270,7 +223,7 @@ export default function MenuPage() {
|
||||
}}
|
||||
/>
|
||||
|
||||
{/* Video on Hover */}
|
||||
{/* Video on Hover - robust source selection with optimized fallbacks */}
|
||||
<video
|
||||
muted
|
||||
loop
|
||||
@@ -278,7 +231,20 @@ export default function MenuPage() {
|
||||
preload="metadata"
|
||||
className="absolute inset-0 w-full h-full object-cover opacity-0 group-hover:opacity-100 transition-opacity duration-150"
|
||||
>
|
||||
<source src={`/videos/${item.video.replace(".mp4", ".webm")}`} type="video/webm" />
|
||||
{/* Optimized variants first (smaller, better quality) */}
|
||||
<source
|
||||
src={`/videos/${item.video.replace(".mp4", "-optimized.webm")}`}
|
||||
type="video/webm"
|
||||
/>
|
||||
<source
|
||||
src={`/videos/${item.video.replace(".mp4", "-optimized.mp4")}`}
|
||||
type="video/mp4"
|
||||
/>
|
||||
{/* Base variants as fallback */}
|
||||
<source
|
||||
src={`/videos/${item.video.replace(".mp4", ".webm")}`}
|
||||
type="video/webm"
|
||||
/>
|
||||
<source src={`/videos/${item.video}`} type="video/mp4" />
|
||||
</video>
|
||||
|
||||
|
||||
+7
-6
@@ -186,20 +186,21 @@ export default function ShahiKitchenHomepage() {
|
||||
|
||||
{/* HERO - Full Banner Video with responsive framing */}
|
||||
<section className="relative min-h-[70dvh] sm:min-h-[78dvh] md:min-h-[85dvh] lg:min-h-[92dvh] xl:min-h-[100dvh]
|
||||
flex items-center justify-center pt-20 lg:pt-[88px] overflow-hidden bg-[#fbf7ef]">
|
||||
flex items-center justify-center pt-40 sm:pt-44 md:pt-52 lg:pt-[200px] xl:pt-[220px] overflow-hidden bg-[#fbf7ef]">
|
||||
|
||||
{/* Banner Video - Optimized positioning per device */}
|
||||
<video
|
||||
autoPlay
|
||||
muted
|
||||
loop
|
||||
playsInline
|
||||
preload="auto"
|
||||
className="absolute inset-0 z-10 w-full h-full object-cover
|
||||
object-[50%_22%] sm:object-[50%_26%] md:object-[50%_30%]
|
||||
lg:object-[50%_35%] xl:object-[50%_38%]"
|
||||
object-[50%_10%] sm:object-[50%_12%] md:object-[50%_16%]
|
||||
lg:object-[50%_20%] xl:object-[50%_24%]"
|
||||
onError={(e) => console.error('Hero banner video failed to load', e)}
|
||||
>
|
||||
<source src="/videos/banner.webm" type="video/webm" />
|
||||
<source src="/videos/banner.mp4" type="video/mp4" />
|
||||
{/* Using the compressed banner1.mp4 from images/logo as intended for the hero */}
|
||||
<source src="/images/logo/banner1.mp4" type="video/mp4" />
|
||||
</video>
|
||||
|
||||
{/* Subtle gradient to improve visibility of baked-in text */}
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
* Contains:
|
||||
* - Brand + short tagline
|
||||
* - Both physical locations with full addresses + phone/email
|
||||
* - Opening hours (different per branch — Backaplan is more variable)
|
||||
* - Opening hours (same for both branches)
|
||||
* - Quick links + social profiles
|
||||
*
|
||||
* Note: The phone numbers and addresses here are the canonical source.
|
||||
@@ -24,10 +24,10 @@ export default function Footer() {
|
||||
{/* Brand */}
|
||||
<div>
|
||||
<div className="flex items-center gap-3 mb-4">
|
||||
<div className="w-10 h-10 rounded-xl overflow-hidden border border-[#c99a2e]/30 bg-white p-0.5 shadow-sm">
|
||||
<div className="w-12 h-12 rounded-xl overflow-hidden border border-[#c99a2e]/30 bg-white p-1 shadow-sm">
|
||||
<img
|
||||
src="/images/logo-shahi-chef-icon.jpg"
|
||||
alt="Shahi Kitchen Chef Logo"
|
||||
src="/images/logo/logo1.png"
|
||||
alt="Shahi Kitchen Logo"
|
||||
className="w-full h-full object-contain"
|
||||
/>
|
||||
</div>
|
||||
@@ -66,7 +66,7 @@ export default function Footer() {
|
||||
<div className="text-[#2C2A26] text-sm tracking-[1.5px] mb-4">OPENING HOURS</div>
|
||||
<div className="text-sm space-y-1">
|
||||
<div><span className="font-medium">Askim:</span> Mon–Sun 11:00–21:00</div>
|
||||
<div><span className="font-medium">Backaplan:</span> Check Instagram for current hours</div>
|
||||
<div><span className="font-medium">Backaplan:</span> Mon–Sun 11:00–21:00</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
@@ -54,11 +54,11 @@ export default function Navbar({ variant = "default" }: NavbarProps) {
|
||||
|
||||
return (
|
||||
<nav
|
||||
className="fixed top-0 left-0 right-0 z-50 h-16 border-b border-[#c99a2e]/10 bg-[#fbf7ef]/80 backdrop-blur-3xl"
|
||||
className="fixed top-0 left-0 right-0 z-[60] h-[64px] border-b border-[#c99a2e]/20 bg-[#fbf7ef] shadow-sm backdrop-blur-xl"
|
||||
>
|
||||
<div className="max-w-7xl mx-auto px-6 flex items-center justify-between h-full">
|
||||
{/* Subtle gold accent line at the very bottom */}
|
||||
<div className="absolute bottom-0 left-0 right-0 h-px bg-gradient-to-r from-transparent via-[#c99a2e]/30 to-transparent" />
|
||||
{/* Top subtle gold line for extra frame separation */}
|
||||
<div className="absolute top-0 left-0 right-0 h-px bg-gradient-to-r from-transparent via-[#c99a2e]/20 to-transparent" />
|
||||
{/* Premium Animated Logo */}
|
||||
<Link href="/" className="group flex items-center gap-3">
|
||||
<div className="relative">
|
||||
@@ -68,8 +68,8 @@ export default function Navbar({ variant = "default" }: NavbarProps) {
|
||||
className="grid h-12 w-12 place-items-center overflow-hidden rounded-2xl border border-[#c99a2e]/30 bg-white shadow-xl shadow-[#0f5a4a]/10 p-1 transition-all duration-300 group-hover:border-[#c99a2e]/70 group-hover:shadow-[#c99a2e]/25"
|
||||
>
|
||||
<img
|
||||
src="/images/logo-shahi-chef-icon.jpg"
|
||||
alt="Shahi Kitchen - Cute Chef with Large Mustaches"
|
||||
src="/images/logo/logo1.png"
|
||||
alt="Shahi Kitchen Logo"
|
||||
className="h-10 w-10 object-contain transition-all duration-500"
|
||||
/>
|
||||
</motion.span>
|
||||
@@ -186,7 +186,7 @@ export default function Navbar({ variant = "default" }: NavbarProps) {
|
||||
<div className="flex items-center justify-between mb-10">
|
||||
<div className="flex items-center gap-3">
|
||||
<img
|
||||
src="/images/logo-shahi-chef-icon.jpg"
|
||||
src="/images/logo/logo1.png"
|
||||
alt="Shahi Kitchen"
|
||||
className="h-12 w-12 rounded-xl object-contain"
|
||||
/>
|
||||
|
||||
@@ -37,7 +37,7 @@ export default function PlayfulHeroScene() {
|
||||
<div className="relative w-full h-full min-h-[520px] md:min-h-[620px] flex items-center justify-center overflow-hidden">
|
||||
|
||||
{/* Large cream background circle - matches website exactly so logo absorbs */}
|
||||
<div className="absolute left-1/2 top-1/2 -translate-x-1/2 -translate-y-1/2
|
||||
<div className="absolute left-1/2 top-[58%] -translate-x-1/2 -translate-y-1/2
|
||||
w-[440px] h-[440px] md:w-[540px] md:h-[540px] lg:w-[620px] lg:h-[620px]
|
||||
bg-[#fbf7ef] rounded-full blur-[130px] opacity-95" />
|
||||
|
||||
@@ -60,7 +60,7 @@ export default function PlayfulHeroScene() {
|
||||
opacity: { duration: 0.4 },
|
||||
scale: { duration: 0.4 }
|
||||
}}
|
||||
className="w-[280px] h-[280px] md:w-[360px] md:h-[360px] lg:w-[420px] lg:h-[420px]"
|
||||
className="w-[300px] h-[300px] md:w-[380px] md:h-[380px] lg:w-[440px] lg:h-[440px]"
|
||||
>
|
||||
<img
|
||||
src={getLogoSrc()}
|
||||
|
||||
@@ -0,0 +1,24 @@
|
||||
module.exports = {
|
||||
apps: [
|
||||
{
|
||||
name: 'shahikitchen',
|
||||
cwd: '/var/www/shahikitchen.se',
|
||||
script: 'npm',
|
||||
args: 'run start',
|
||||
env: {
|
||||
NODE_ENV: 'production',
|
||||
PORT: 3001
|
||||
},
|
||||
instances: 1,
|
||||
exec_mode: 'fork',
|
||||
max_memory_restart: '700M',
|
||||
error_file: '/home/deploy/.pm2/logs/shahikitchen-error.log',
|
||||
out_file: '/home/deploy/.pm2/logs/shahikitchen-out.log',
|
||||
log_date_format: 'YYYY-MM-DD HH:mm:ss Z',
|
||||
kill_timeout: 8000,
|
||||
autorestart: true,
|
||||
watch: false,
|
||||
min_uptime: '10s'
|
||||
}
|
||||
]
|
||||
};
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
|
After Width: | Height: | Size: 1.3 MiB |
Binary file not shown.
Binary file not shown.
Executable
+87
@@ -0,0 +1,87 @@
|
||||
#!/bin/bash
|
||||
#
|
||||
# Shahi Kitchen Production Deploy Script
|
||||
# Run as: sudo -u deploy /var/www/shahikitchen.se/scripts/deploy.sh
|
||||
#
|
||||
# This script supports two modes:
|
||||
# 1. Tarball mode (current primary method): Place new shahi.tar.gz in /tmp or /root and run
|
||||
# 2. Git mode (if you initialize git in the future)
|
||||
#
|
||||
set -euo pipefail
|
||||
|
||||
APP_DIR="/var/www/shahikitchen.se"
|
||||
PM2_APP_NAME="shahikitchen"
|
||||
PORT=3001
|
||||
|
||||
echo "=========================================="
|
||||
echo " Shahi Kitchen - Production Deploy"
|
||||
echo " $(date)"
|
||||
echo "=========================================="
|
||||
|
||||
cd "$APP_DIR"
|
||||
|
||||
# --- Detect mode ---
|
||||
if [ -f "/tmp/shahi.tar.gz" ] || [ -f "/root/shahi.tar.gz" ]; then
|
||||
echo "[1/6] Tarball update detected"
|
||||
TARBALL=""
|
||||
if [ -f "/tmp/shahi.tar.gz" ]; then TARBALL="/tmp/shahi.tar.gz"; fi
|
||||
if [ -f "/root/shahi.tar.gz" ]; then TARBALL="/root/shahi.tar.gz"; fi
|
||||
|
||||
echo "Using tarball: $TARBALL"
|
||||
|
||||
echo "Stopping PM2 app (graceful)..."
|
||||
pm2 stop "$PM2_APP_NAME" || true
|
||||
|
||||
echo "Backing up current .next (quick safety)..."
|
||||
rm -rf .next.bak 2>/dev/null || true
|
||||
cp -a .next .next.bak 2>/dev/null || true
|
||||
|
||||
echo "Extracting new tarball..."
|
||||
tar --strip-components=1 -xzf "$TARBALL"
|
||||
|
||||
echo "Cleaning shipped node_modules + cache..."
|
||||
rm -rf node_modules .next/cache 2>/dev/null || true
|
||||
|
||||
echo "Running npm ci..."
|
||||
npm ci
|
||||
|
||||
echo "Building..."
|
||||
npm run build
|
||||
|
||||
elif git rev-parse --git-dir > /dev/null 2>&1; then
|
||||
echo "[1/6] Git update mode"
|
||||
pm2 stop "$PM2_APP_NAME" || true
|
||||
git fetch --all
|
||||
git reset --hard origin/main || git reset --hard origin/master
|
||||
npm ci
|
||||
npm run build
|
||||
else
|
||||
echo "ERROR: No tarball found in /tmp or /root, and no git repository."
|
||||
echo "Please either:"
|
||||
echo " - scp your new shahi.tar.gz to the server, or"
|
||||
echo " - Run: cp /path/to/shahi.tar.gz /tmp/shahi.tar.gz"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "[2/6] Dependencies and build complete"
|
||||
|
||||
echo "[3/6] Starting / restarting PM2..."
|
||||
pm2 start ecosystem.config.cjs --only "$PM2_APP_NAME" || pm2 reload "$PM2_APP_NAME" --update-env || true
|
||||
pm2 save
|
||||
|
||||
echo "[4/6] Reloading Nginx..."
|
||||
sudo nginx -t && sudo systemctl reload nginx
|
||||
|
||||
echo "[5/6] Post-deploy health checks..."
|
||||
echo "PM2 status:"
|
||||
pm2 list | grep -E "shahikitchen|App name" || true
|
||||
|
||||
echo ""
|
||||
echo "Testing local Next.js process..."
|
||||
curl -s --max-time 5 "http://127.0.0.1:${PORT}" | head -c 300 || echo "(first request may be slow)"
|
||||
|
||||
echo ""
|
||||
echo "[6/6] Deploy finished successfully at $(date)"
|
||||
echo "=========================================="
|
||||
echo "Website should be live at: http://76.13.210.183"
|
||||
echo "=========================================="
|
||||
Reference in New Issue
Block a user