diff --git a/api-dashboard/src/App.tsx b/api-dashboard/src/App.tsx
index f478cba3..ae5900db 100644
--- a/api-dashboard/src/App.tsx
+++ b/api-dashboard/src/App.tsx
@@ -843,7 +843,7 @@ function App() {
๐ก Dev Sandbox Access:
{loginType === 'SYSTEM' ? (
-
Default Admin: admin / Password: admin123
+
Default Admin: admin / Password: admin
) : (
Sign in with your Google account. First-time users will be asked for a mobile number to complete registration.
)}
diff --git a/backend/src/main/java/com/rit/canteen/sales/service/DatabaseSeeder.java b/backend/src/main/java/com/rit/canteen/sales/service/DatabaseSeeder.java
index 20521144..8d020ecb 100644
--- a/backend/src/main/java/com/rit/canteen/sales/service/DatabaseSeeder.java
+++ b/backend/src/main/java/com/rit/canteen/sales/service/DatabaseSeeder.java
@@ -2,15 +2,21 @@ package com.rit.canteen.sales.service;
import com.rit.canteen.sales.model.BaseItem;
import com.rit.canteen.sales.model.Product;
+import com.rit.canteen.sales.model.Stall;
+import com.rit.canteen.sales.model.SystemUser;
import com.rit.canteen.sales.repository.BaseItemRepository;
import com.rit.canteen.sales.repository.ProductRepository;
+import com.rit.canteen.sales.repository.StallRepository;
+import com.rit.canteen.sales.repository.SystemUserRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.CommandLineRunner;
-import org.springframework.stereotype.Component;
import org.springframework.jdbc.core.JdbcTemplate;
-import java.util.List;
+import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
+import org.springframework.stereotype.Component;
import java.math.BigDecimal;
+import java.util.List;
+import java.util.Optional;
@Component
public class DatabaseSeeder implements CommandLineRunner {
@@ -21,6 +27,15 @@ public class DatabaseSeeder implements CommandLineRunner {
@Autowired
private ProductRepository productRepository;
+ @Autowired
+ private StallRepository stallRepository;
+
+ @Autowired
+ private SystemUserRepository systemUserRepository;
+
+ @Autowired
+ private BCryptPasswordEncoder passwordEncoder;
+
@Autowired
private JdbcTemplate jdbcTemplate;
@@ -34,6 +49,8 @@ public class DatabaseSeeder implements CommandLineRunner {
repairLobColumns();
seedCategories();
seedProducts();
+ seedStalls();
+ seedMasterUser();
}
private void repairFeedbackSchema() {
@@ -254,4 +271,42 @@ public class DatabaseSeeder implements CommandLineRunner {
p.setActive(true);
return p;
}
+
+ private void seedStalls() {
+ if (stallRepository.count() == 0) {
+ List
allProducts = productRepository.findAll();
+
+ Stall s1 = new Stall("Main Canteen Stall", "Primary food counter serving meals, fast food, and beverages", null);
+ Stall s2 = new Stall("Bakery & Juice Counter", "Fresh bakery items, pastries, snacks, and fresh fruit juices", null);
+ Stall s3 = new Stall("South Indian Express", "Authentic dosas, idlis, vadas, and South Indian breakfast specials", null);
+
+ s1.setProducts(allProducts);
+ s2.setProducts(allProducts.stream()
+ .filter(p -> "Bakery & Sweets".equalsIgnoreCase(p.getCategory()) || "Beverages & Drinks".equalsIgnoreCase(p.getCategory()) || "Snacks & Quick Bites".equalsIgnoreCase(p.getCategory()))
+ .toList());
+ s3.setProducts(allProducts.stream()
+ .filter(p -> "Snacks & Quick Bites".equalsIgnoreCase(p.getCategory()) || "Indian Main Course".equalsIgnoreCase(p.getCategory()))
+ .toList());
+
+ stallRepository.saveAll(List.of(s1, s2, s3));
+ System.out.println(">>> SEEDED DEFAULT STALLS (Main Canteen, Bakery & Juice Counter, South Indian Express)");
+ }
+ }
+
+ private void seedMasterUser() {
+ Optional existingAdmin = systemUserRepository.findByEmail("admin");
+ if (existingAdmin.isEmpty()) {
+ SystemUser admin = new SystemUser();
+ admin.setName("Admin Master");
+ admin.setEmail("admin");
+ admin.setPassword(passwordEncoder.encode("admin"));
+ admin.setRole("MASTER");
+ admin.setPermissions(List.of("dashboard", "sale", "customers", "purchases", "inventory", "expense", "reports", "stores", "table", "wallet", "promotions", "feedback"));
+ admin.setViewOnly(false);
+ systemUserRepository.save(admin);
+ System.out.println(">>> SEEDED ADMIN MASTER USER (username: admin, password: admin)");
+ } else {
+ System.out.println(">>> ADMIN MASTER USER EXISTS. Skipping admin user creation.");
+ }
+ }
}
diff --git a/backend/src/main/resources/application.properties b/backend/src/main/resources/application.properties
index 8b15d5a8..51318e13 100644
--- a/backend/src/main/resources/application.properties
+++ b/backend/src/main/resources/application.properties
@@ -27,7 +27,7 @@ app.jwt.expiration-ms=86400000
# Master Account โ REQUIRED environment variables
# ============================================================
app.master.username=${MASTER_USER:admin}
-app.master.password=${MASTER_PASSWORD:admin123}
+app.master.password=${MASTER_PASSWORD:admin}
# File upload configuration
spring.servlet.multipart.max-file-size=10MB
diff --git a/create_master_user.py b/create_master_user.py
new file mode 100644
index 00000000..4e570ae7
--- /dev/null
+++ b/create_master_user.py
@@ -0,0 +1,239 @@
+#!/usr/bin/env python3
+"""
+Master User Creation Script for Positeasy Canteen Automation System.
+
+This script creates or updates a master administrator user in the database
+with username 'admin' and password 'admin', and synchronizes the application configuration.
+"""
+
+import sys
+import os
+import re
+import argparse
+import bcrypt
+import psycopg2
+
+# Default Configuration
+DEFAULT_USERNAME = "admin"
+DEFAULT_PASSWORD = "admin"
+DEFAULT_NAME = "Admin Master"
+DEFAULT_ROLE = "MASTER"
+
+DEFAULT_DB_HOST = "localhost"
+DEFAULT_DB_PORT = 5432
+DEFAULT_DB_NAME = "positeasy"
+DEFAULT_DB_USER = "postgres"
+DEFAULT_DB_PASS = "sidharth"
+
+ALL_PERMISSIONS = [
+ "dashboard",
+ "sale",
+ "customers",
+ "purchases",
+ "inventory",
+ "expense",
+ "reports",
+ "stores",
+ "table",
+ "wallet",
+ "promotions",
+ "feedback"
+]
+
+def hash_password(password: str) -> str:
+ """Hash password using bcrypt compatible with Spring Security BCryptPasswordEncoder."""
+ salt = bcrypt.gensalt(rounds=10)
+ hashed = bcrypt.hashpw(password.encode('utf-8'), salt)
+ return hashed.decode('utf-8')
+
+def parse_application_properties(prop_path: str) -> dict:
+ """Parse db credentials from backend application.properties if available."""
+ config = {}
+ if not os.path.exists(prop_path):
+ return config
+
+ with open(prop_path, 'r', encoding='utf-8') as f:
+ for line in f:
+ line = line.strip()
+ if line and not line.startswith('#') and '=' in line:
+ key, value = line.split('=', 1)
+ config[key.strip()] = value.strip()
+ return config
+
+def update_application_properties(prop_path: str, username: str, password: str) -> bool:
+ """Update app.master.username and app.master.password in application.properties."""
+ if not os.path.exists(prop_path):
+ print(f"โ ๏ธ [Config] File not found: {prop_path}")
+ return False
+
+ with open(prop_path, 'r', encoding='utf-8') as f:
+ content = f.read()
+
+ # Update or add app.master.username and app.master.password
+ new_user_line = f"app.master.username=${{MASTER_USER:{username}}}"
+ new_pass_line = f"app.master.password=${{MASTER_PASSWORD:{password}}}"
+
+ if re.search(r'^app\.master\.username=.*$', content, flags=re.MULTILINE):
+ content = re.sub(r'^app\.master\.username=.*$', new_user_line, content, flags=re.MULTILINE)
+ else:
+ content += f"\n{new_user_line}"
+
+ if re.search(r'^app\.master\.password=.*$', content, flags=re.MULTILINE):
+ content = re.sub(r'^app\.master\.password=.*$', new_pass_line, content, flags=re.MULTILINE)
+ else:
+ content += f"\n{new_pass_line}"
+
+ with open(prop_path, 'w', encoding='utf-8') as f:
+ f.write(content)
+
+ print(f"โ
[Config] Updated {prop_path} with default master credentials ({username}/{password}).")
+ return True
+
+def update_frontend_demo_credentials(app_tsx_path: str, username: str, password: str) -> bool:
+ """Update UI demo credentials displayed in api-dashboard if file exists."""
+ if not os.path.exists(app_tsx_path):
+ return False
+
+ with open(app_tsx_path, 'r', encoding='utf-8') as f:
+ content = f.read()
+
+ old_pattern = r'Default Admin:\s*[^<]*\s*/\s*Password:\s*[^<]*'
+ new_text = f'Default Admin: {username} / Password: {password}'
+
+ if re.search(old_pattern, content):
+ content = re.sub(old_pattern, new_text, content)
+ with open(app_tsx_path, 'w', encoding='utf-8') as f:
+ f.write(content)
+ print(f"โ
[UI] Updated demo credentials in {app_tsx_path}.")
+ return True
+ return False
+
+def create_or_update_master_user(db_params: dict, username: str, password: str, name: str) -> bool:
+ """Insert or update master user in PostgreSQL database."""
+ print(f"\n๐ Connecting to PostgreSQL database '{db_params['dbname']}' on {db_params['host']}:{db_params['port']}...")
+
+ try:
+ conn = psycopg2.connect(**db_params)
+ conn.autocommit = False
+ cur = conn.cursor()
+
+ # Check if system_users table exists
+ cur.execute("""
+ SELECT EXISTS (
+ SELECT FROM information_schema.tables
+ WHERE table_name = 'system_users'
+ );
+ """)
+ table_exists = cur.fetchone()[0]
+
+ if not table_exists:
+ print("โ Table 'system_users' does not exist in the database. Has backend schema initialized?")
+ conn.close()
+ return False
+
+ # Check if master user with this username (stored in email column) exists
+ cur.execute("SELECT id, name, role FROM system_users WHERE email = %s;", (username,))
+ row = cur.fetchone()
+
+ hashed_pass = hash_password(password)
+
+ if row:
+ user_id = row[0]
+ print(f"๐ Existing master user found (ID: {user_id}). Updating credentials...")
+ cur.execute("""
+ UPDATE system_users
+ SET name = %s, password = %s, role = %s, view_only = false
+ WHERE id = %s;
+ """, (name, hashed_pass, DEFAULT_ROLE, user_id))
+ else:
+ print(f"โ Creating new master user '{username}'...")
+ cur.execute("""
+ INSERT INTO system_users (name, email, password, role, view_only)
+ VALUES (%s, %s, %s, %s, false)
+ RETURNING id;
+ """, (name, username, hashed_pass, DEFAULT_ROLE))
+ user_id = cur.fetchone()[0]
+
+ # Reset permissions for this user
+ cur.execute("DELETE FROM system_user_permissions WHERE user_id = %s;", (user_id,))
+ for perm in ALL_PERMISSIONS:
+ cur.execute("""
+ INSERT INTO system_user_permissions (user_id, permission)
+ VALUES (%s, %s);
+ """, (user_id, perm))
+
+ conn.commit()
+
+ # Verification query
+ cur.execute("""
+ SELECT u.id, u.name, u.email, u.role, count(p.permission)
+ FROM system_users u
+ LEFT JOIN system_user_permissions p ON u.id = p.user_id
+ WHERE u.id = %s
+ GROUP BY u.id, u.name, u.email, u.role;
+ """, (user_id,))
+ ver = cur.fetchone()
+ cur.close()
+ conn.close()
+
+ print("\n" + "=" * 50)
+ print("๐ MASTER USER CREATED / UPDATED SUCCESSFULLY")
+ print("=" * 50)
+ print(f" User ID: {ver[0]}")
+ print(f" Name: {ver[1]}")
+ print(f" Username: {ver[2]}")
+ print(f" Password: {password}")
+ print(f" Role: {ver[3]}")
+ print(f" Permissions: {ver[4]} granted ({', '.join(ALL_PERMISSIONS[:4])}...)")
+ print("=" * 50 + "\n")
+ return True
+
+ except Exception as e:
+ print(f"โ Database error: {e}")
+ return False
+
+def main():
+ parser = argparse.ArgumentParser(description="Create or update master user for Positeasy Canteen Automation.")
+ parser.add_argument("-u", "--username", default=DEFAULT_USERNAME, help="Master username (default: admin)")
+ parser.add_argument("-p", "--password", default=DEFAULT_PASSWORD, help="Master password (default: admin)")
+ parser.add_argument("-n", "--name", default=DEFAULT_NAME, help="Display name for master user")
+ parser.add_argument("--host", default=DEFAULT_DB_HOST, help="PostgreSQL host (default: localhost)")
+ parser.add_argument("--port", type=int, default=DEFAULT_DB_PORT, help="PostgreSQL port (default: 5432)")
+ parser.add_argument("--dbname", default=DEFAULT_DB_NAME, help="PostgreSQL database name (default: positeasy)")
+ parser.add_argument("--dbuser", default=DEFAULT_DB_USER, help="PostgreSQL database user (default: postgres)")
+ parser.add_argument("--dbpass", default=DEFAULT_DB_PASS, help="PostgreSQL database password")
+
+ args = parser.parse_args()
+
+ project_root = os.path.dirname(os.path.abspath(__file__))
+ prop_path = os.path.join(project_root, "backend", "src", "main", "resources", "application.properties")
+ app_tsx_path = os.path.join(project_root, "api-dashboard", "src", "App.tsx")
+
+ db_params = {
+ "host": args.host,
+ "port": args.port,
+ "dbname": args.dbname,
+ "user": args.dbuser,
+ "password": args.dbpass
+ }
+
+ print("๐ Starting Master User setup script...")
+
+ # 1. Database creation / update
+ db_success = create_or_update_master_user(db_params, args.username, args.password, args.name)
+
+ # 2. Sync application.properties
+ update_application_properties(prop_path, args.username, args.password)
+
+ # 3. Sync frontend dashboard UI
+ update_frontend_demo_credentials(app_tsx_path, args.username, args.password)
+
+ if db_success:
+ print("โจ All steps completed successfully! You can now log in with:")
+ print(f" Username: {args.username}")
+ print(f" Password: {args.password}")
+ else:
+ print("โ ๏ธ Database operation failed or incomplete. Check database connectivity.")
+
+if __name__ == "__main__":
+ main()
diff --git a/ordering_site/src/components/ItemCard.tsx b/ordering_site/src/components/ItemCard.tsx
index 2b887b83..64343929 100644
--- a/ordering_site/src/components/ItemCard.tsx
+++ b/ordering_site/src/components/ItemCard.tsx
@@ -97,7 +97,7 @@ const ItemCard: React.FC = ({ item, isLast, variant = 'list' }) =
) : (
๐ฒ
)}
- {item.isPopular && Bestseller}
+ {item.isPopular && item.stock !== 0 && Bestseller}
{item.stock === 0 && Sold Out}
diff --git a/ordering_site/src/index.css b/ordering_site/src/index.css
index 577f11c7..b7177521 100644
--- a/ordering_site/src/index.css
+++ b/ordering_site/src/index.css
@@ -267,3 +267,328 @@ main::-webkit-scrollbar {
.veg-nonveg-indicator.non-veg .dot {
background-color: #ef4444;
}
+
+/* DESKTOP SCREEN OPTIMIZATIONS */
+@media (min-width: 769px) {
+ body {
+ display: block;
+ background-color: var(--surface);
+ }
+
+ .container {
+ max-width: 100% !important;
+ width: 100% !important;
+ margin: 0 !important;
+ height: auto !important;
+ min-height: 100vh !important;
+ border-radius: 0 !important;
+ border: none !important;
+ box-shadow: none !important;
+ background-color: var(--surface) !important;
+ }
+
+ main {
+ overflow-y: visible !important;
+ }
+
+ /* Home Screen layout adjustments */
+ .welcome-section {
+ display: flex !important;
+ justify-content: space-between !important;
+ align-items: center !important;
+ padding: 32px 60px 16px !important;
+ }
+
+ .search-bar-container {
+ padding: 16px 60px 24px !important;
+ }
+
+ .search-bar {
+ max-width: 550px !important;
+ }
+
+ /* Grid listings on desktop - Full Width */
+ .categories-grid {
+ grid-template-columns: repeat(10, 1fr) !important;
+ gap: 20px !important;
+ padding: 0 60px 24px !important;
+ }
+
+ .category-image-wrapper {
+ max-width: 90px !important;
+ max-height: 90px !important;
+ }
+
+ .stalls-carousel {
+ display: grid !important;
+ grid-template-columns: repeat(4, 1fr) !important;
+ gap: 24px !important;
+ padding: 16px 60px 24px !important;
+ overflow-x: visible !important;
+ }
+
+ .stall-card {
+ min-width: 100% !important;
+ max-width: 100% !important;
+ height: 200px !important;
+ }
+
+ .popular-carousel {
+ display: grid !important;
+ grid-template-columns: repeat(5, 1fr) !important;
+ gap: 24px !important;
+ padding: 16px 60px 24px !important;
+ overflow-x: visible !important;
+ }
+
+ /* Multi-column items listing */
+ .recommended-section .items-list,
+ .search-results-section .items-list,
+ .stall-items-section .items-list {
+ display: grid !important;
+ grid-template-columns: repeat(3, 1fr) !important;
+ gap: 24px !important;
+ padding: 16px 60px 24px !important;
+ }
+
+ .section-header {
+ padding: 24px 60px 12px !important;
+ }
+
+ /* Floating Pill Bottom Navigation Bar */
+ .bottom-nav {
+ position: fixed !important;
+ bottom: 24px !important;
+ left: 50% !important;
+ transform: translateX(-50%) !important;
+ width: 500px !important;
+ border-radius: 100px !important;
+ box-shadow: 0 10px 40px rgba(44, 58, 42, 0.15) !important;
+ border: 1px solid var(--border) !important;
+ height: 64px !important;
+ padding-bottom: 0 !important;
+ z-index: 1001 !important;
+ background: var(--surface) !important;
+ }
+
+ /* Redesigned Item Detail Page for Desktop */
+ .item-detail-page {
+ display: flex !important;
+ flex-direction: column !important;
+ padding: 0 !important;
+ height: auto !important;
+ }
+
+ .item-detail-page .detail-header-overlay {
+ position: static !important;
+ width: 100% !important;
+ border-bottom: 1px solid var(--border) !important;
+ }
+
+ .item-detail-page main {
+ display: flex !important;
+ flex-direction: row !important;
+ gap: 40px !important;
+ padding: 40px 60px !important;
+ align-items: flex-start !important;
+ }
+
+ .item-detail-page .item-hero {
+ flex: 1 !important;
+ height: 480px !important;
+ border-radius: 20px !important;
+ box-shadow: 0 10px 30px rgba(44, 58, 42, 0.08) !important;
+ overflow: hidden !important;
+ }
+
+ .item-detail-page .item-hero-image {
+ width: 100% !important;
+ height: 100% !important;
+ object-fit: cover !important;
+ }
+
+ .item-detail-page .item-details-content {
+ flex: 1.2 !important;
+ margin-top: 0 !important;
+ padding: 0 !important;
+ background: transparent !important;
+ box-shadow: none !important;
+ border-radius: 0 !important;
+ }
+
+ .item-detail-page .item-name-large {
+ font-size: 2.2rem !important;
+ font-weight: 850 !important;
+ color: var(--text-dark) !important;
+ }
+
+ .item-detail-page .item-subtitle {
+ font-size: 1rem !important;
+ color: var(--primary) !important;
+ font-weight: 700 !important;
+ }
+
+ .item-detail-page .item-long-description {
+ font-size: 0.95rem !important;
+ line-height: 1.6 !important;
+ color: var(--text-mid) !important;
+ margin-bottom: 24px !important;
+ }
+
+ .item-detail-page .item-extra-info {
+ background: var(--primary-light) !important;
+ border-radius: 16px !important;
+ padding: 20px !important;
+ border: 1px solid var(--border) !important;
+ margin-bottom: 24px !important;
+ }
+
+ .item-detail-page .item-footer {
+ position: static !important;
+ display: flex !important;
+ align-items: center !important;
+ justify-content: space-between !important;
+ background: var(--surface) !important;
+ border: 1px solid var(--border) !important;
+ border-radius: 20px !important;
+ padding: 20px 24px !important;
+ box-shadow: var(--shadow) !important;
+ margin-top: 24px !important;
+ }
+
+ .item-detail-page .footer-price-info {
+ display: flex !important;
+ flex-direction: column !important;
+ }
+
+ .item-detail-page .total-label {
+ font-size: 0.8rem !important;
+ text-transform: uppercase !important;
+ letter-spacing: 0.5px !important;
+ }
+
+ .item-detail-page .total-value {
+ font-size: 1.8rem !important;
+ font-weight: 850 !important;
+ color: var(--primary) !important;
+ }
+
+ .item-detail-page .primary-action-button {
+ height: 48px !important;
+ padding: 0 32px !important;
+ font-size: 0.95rem !important;
+ border-radius: 100px !important;
+ width: auto !important;
+ min-width: 160px !important;
+ }
+
+ /* Stall Detail Page Split Flow */
+ .stall-detail-page main.detail-content {
+ display: flex !important;
+ gap: 40px !important;
+ padding: 24px 60px !important;
+ align-items: flex-start !important;
+ }
+
+ .stall-main-card {
+ flex: 1 !important;
+ max-width: 320px !important;
+ margin: 0 !important;
+ position: sticky !important;
+ top: 24px !important;
+ background: var(--surface) !important;
+ padding: 24px !important;
+ border-radius: 20px !important;
+ border: 1px solid var(--border) !important;
+ box-shadow: var(--shadow) !important;
+ z-index: 100 !important;
+ }
+
+ .stall-items-section {
+ flex: 2.2 !important;
+ padding: 0 !important;
+ }
+
+ .stall-items-section .section-title {
+ padding: 0 0 16px 0 !important;
+ }
+
+ .stall-items-section .items-list {
+ display: grid !important;
+ grid-template-columns: repeat(2, 1fr) !important;
+ gap: 20px !important;
+ padding: 0 !important;
+ }
+
+ /* Cart split flow */
+ .cart-page main {
+ display: flex !important;
+ gap: 40px !important;
+ padding: 24px 60px !important;
+ align-items: flex-start !important;
+ }
+
+ .cart-items-section {
+ flex: 1.6 !important;
+ }
+
+ .bill-details {
+ flex: 1 !important;
+ margin-top: 0 !important;
+ background: var(--surface) !important;
+ padding: 24px !important;
+ border-radius: 16px !important;
+ border: 1px solid var(--border) !important;
+ box-shadow: var(--shadow) !important;
+ }
+
+ .cart-footer {
+ padding: 20px 60px !important;
+ border-top: 1px solid var(--border) !important;
+ }
+
+ /* Checkout split flow */
+ .checkout-page main {
+ display: flex !important;
+ gap: 40px !important;
+ padding: 24px 60px !important;
+ align-items: flex-start !important;
+ }
+
+ .checkout-section {
+ flex: 1.6 !important;
+ margin-bottom: 0 !important;
+ background: transparent !important;
+ }
+
+ .checkout-summary-container-desktop {
+ flex: 1 !important;
+ display: flex !important;
+ flex-direction: column !important;
+ gap: 24px !important;
+ }
+
+ .checkout-page .order-summary-mini,
+ .checkout-page .insufficient-warning-premium {
+ margin: 0 !important;
+ background: var(--surface) !important;
+ padding: 24px !important;
+ border-radius: 16px !important;
+ border: 1px solid var(--border) !important;
+ box-shadow: var(--shadow) !important;
+ }
+
+ /* Handle footer buttons in desktop splits */
+ .checkout-footer {
+ display: none !important;
+ }
+
+ .desktop-checkout-action {
+ display: block !important;
+ }
+}
+
+/* Hide desktop checkout actions on mobile */
+.desktop-checkout-action {
+ display: none;
+}
diff --git a/ordering_site/src/pages/CheckoutScreen.tsx b/ordering_site/src/pages/CheckoutScreen.tsx
index 94434890..99aa52bf 100644
--- a/ordering_site/src/pages/CheckoutScreen.tsx
+++ b/ordering_site/src/pages/CheckoutScreen.tsx
@@ -336,52 +336,64 @@ const CheckoutScreen: React.FC = () => {
-
-
-
{paymentMethod === 'RAZORPAY' ? 'Amount payable' : 'Tokens to be deducted'}
-
- {paymentMethod === 'RAZORPAY' ? 'โน' : '๐
ก'}{totalPrice.toLocaleString()}
-
+
+
+
+ {paymentMethod === 'RAZORPAY' ? 'Amount payable' : 'Tokens to be deducted'}
+
+ {paymentMethod === 'RAZORPAY' ? 'โน' : '๐
ก'}{totalPrice.toLocaleString()}
+
+
+
Inclusive of applicable item prices ยท No extra platform fee
+
+
+ {statusMessage && (
+
+
+
+
+ )}
+
+ {isInsufficient && paymentMethod === 'RITZ_TOKEN' && (
+
+
+

+
+
+
+
+ Short by ๐
ก{(totalPrice - currentBalance).toLocaleString()}
+
+
Top up tokens, or pay online with Razorpay instead.
+
+
+ )}
+
+
+
-
Inclusive of applicable item prices ยท No extra platform fee
-
- {statusMessage && (
-
-
-
-
- )}
-
- {isInsufficient && paymentMethod === 'RITZ_TOKEN' && (
-
-
-

-
-
-
-
- Short by ๐
ก{(totalPrice - currentBalance).toLocaleString()}
-
-
Top up tokens, or pay online with Razorpay instead.
-
-
- )}
diff --git a/ordering_site/src/pages/StallDetailScreen.css b/ordering_site/src/pages/StallDetailScreen.css
index 6e8aab8e..89eec8df 100644
--- a/ordering_site/src/pages/StallDetailScreen.css
+++ b/ordering_site/src/pages/StallDetailScreen.css
@@ -7,16 +7,23 @@
position: relative;
height: 220px;
width: 100%;
+ z-index: 1 !important;
}
.detail-header.sticky {
height: auto;
padding: 12px 16px;
background: var(--surface);
- z-index: 100;
+ z-index: 100 !important;
box-shadow: var(--shadow);
}
+.detail-content {
+ position: relative;
+ z-index: 50 !important;
+ margin-top: -40px !important;
+}
+
.stall-detail-page .add-to-cart-container {
position: absolute;
bottom: -12px;
@@ -77,13 +84,13 @@
}
.stall-main-card {
- margin: -40px 16px 20px;
- background: var(--surface);
+ margin: 0 16px 20px;
+ background: var(--surface) !important;
border-radius: 24px;
- padding: 24px;
+ padding: 20px;
position: relative;
box-shadow: var(--shadow);
- z-index: 5;
+ z-index: 100 !important;
}
.stall-header-info {