first commit

This commit is contained in:
2026-01-17 14:17:42 +05:30
commit 0f194eb9e7
328 changed files with 73544 additions and 0 deletions

BIN
public/Kashmina Rice.pdf Normal file

Binary file not shown.

BIN
public/Padmaja Singh.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 320 KiB

BIN
public/Rajeev Singh.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 156 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 19 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 105 KiB

BIN
public/apple-touch-icon.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 17 KiB

9
public/browserconfig.xml Normal file
View File

@@ -0,0 +1,9 @@
<?xml version="1.0" encoding="utf-8"?>
<browserconfig>
<msapplication>
<tile>
<square150x150logo src="/icons/mstile-150x150.png"/>
<TileColor>#3B82F6</TileColor>
</tile>
</msapplication>
</browserconfig>

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 17 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 25 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 21 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 39 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.5 KiB

BIN
public/factory.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 285 KiB

BIN
public/farmer.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.1 MiB

BIN
public/favicon-16x16.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 711 B

BIN
public/favicon-32x32.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.8 KiB

BIN
public/favicon-96x96.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.3 KiB

BIN
public/favicon.ico Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 MiB

1
public/hero-bg.jpg Normal file
View File

@@ -0,0 +1 @@
https://images.unsplash.com/photo-1586201375761-83865001e31c?w=1920&h=1080&fit=crop&crop=center

Binary file not shown.

After

Width:  |  Height:  |  Size: 389 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.8 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 MiB

BIN
public/kashmina-logo.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 210 KiB

BIN
public/lab.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 305 KiB

BIN
public/logo.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 MiB

BIN
public/main-loading.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.0 MiB

99
public/manifest.json Normal file
View File

@@ -0,0 +1,99 @@
{
"name": "Padmaaja Rasooi - Premium Rice Products",
"short_name": "Padmaaja Rasooi",
"description": "Premium quality rice products and grains. Experience the finest rice sourced directly from local farmers.",
"start_url": "/",
"display": "standalone",
"background_color": "#ffffff",
"theme_color": "#10B981",
"orientation": "portrait-primary",
"scope": "/",
"lang": "en",
"categories": ["business", "food", "shopping", "productivity"],
"screenshots": [
{
"src": "/images/screenshot-wide.png",
"sizes": "1280x720",
"type": "image/png",
"form_factor": "wide"
},
{
"src": "/images/screenshot-narrow.png",
"sizes": "375x812",
"type": "image/png",
"form_factor": "narrow"
}
],
"icons": [
{
"src": "/android-chrome-192x192.png",
"sizes": "192x192",
"type": "image/png",
"purpose": "maskable any"
},
{
"src": "/android-chrome-512x512.png",
"sizes": "512x512",
"type": "image/png",
"purpose": "maskable any"
},
{
"src": "/apple-touch-icon.png",
"sizes": "180x180",
"type": "image/png"
},
{
"src": "/favicon-96x96.png",
"sizes": "96x96",
"type": "image/png"
},
{
"src": "/favicon-32x32.png",
"sizes": "32x32",
"type": "image/png"
},
{
"src": "/favicon-16x16.png",
"sizes": "16x16",
"type": "image/png"
}
],
"shortcuts": [
{
"name": "Dashboard",
"short_name": "Dashboard",
"description": "View your customer dashboard",
"url": "/dashboard",
"icons": [
{
"src": "/icons/shortcut-dashboard.png",
"sizes": "96x96"
}
]
},
{
"name": "Products",
"short_name": "Shop",
"description": "Browse products",
"url": "/products",
"icons": [
{
"src": "/icons/shortcut-products.png",
"sizes": "96x96"
}
]
},
{
"name": "Commissions",
"short_name": "Earnings",
"description": "Check your commissions",
"url": "/dashboard/commissions",
"icons": [
{
"src": "/icons/shortcut-commissions.png",
"sizes": "96x96"
}
]
}
]
}

BIN
public/rice_bags.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 351 KiB

370
public/sw.js Normal file
View File

@@ -0,0 +1,370 @@
// Cache version - increment this when you want to force cache invalidation
const CACHE_VERSION = Date.now()
const CACHE_NAME = `padmaaja-rasooi-cache-v${CACHE_VERSION}`
const STATIC_CACHE_NAME = `padmaaja-rasooi-static-v${CACHE_VERSION}`
const DYNAMIC_CACHE_NAME = `padmaaja-rasooi-dynamic-v${CACHE_VERSION}`
// Build timestamp for cache busting
const BUILD_TIMESTAMP = new Date().toISOString()
// App version from environment
const APP_VERSION = self.APP_VERSION || '1.0.0'
// Files to cache immediately
const STATIC_FILES = [
'/',
'/offline',
'/manifest.json',
'/icons/icon-192x192.png',
'/icons/icon-512x512.png',
'/apple-touch-icon.png',
'/favicon-32x32.png',
'/favicon-16x16.png',
'/logo.png',
]
// API routes that should be cached
const API_ROUTES = [
'/api/products',
'/api/categories',
'/api/dashboard',
'/api/orders',
'/api/cart',
'/api/payments'
]
// Install event - cache static files and force update
self.addEventListener('install', (event) => {
console.log('🚀 Service Worker: Installing... v' + CACHE_VERSION)
console.log('📅 Build timestamp:', BUILD_TIMESTAMP)
console.log('🏷️ App version:', APP_VERSION)
event.waitUntil(
caches.open(STATIC_CACHE_NAME)
.then((cache) => {
console.log('📦 Service Worker: Caching static files')
return cache.addAll(STATIC_FILES)
})
.then(() => {
console.log('✅ Service Worker: Installation complete')
// Force immediate activation of new service worker
return self.skipWaiting()
})
.catch((error) => {
console.error('❌ Service Worker: Installation failed', error)
})
)
})
// Activate event - clean up old caches and notify clients
self.addEventListener('activate', (event) => {
console.log('Service Worker: Activating... v' + CACHE_VERSION)
event.waitUntil(
caches.keys()
.then((cacheNames) => {
// Delete all old caches
return Promise.all(
cacheNames.map((cacheName) => {
if (!cacheName.includes(`v${CACHE_VERSION}`)) {
console.log('Service Worker: Deleting old cache', cacheName)
return caches.delete(cacheName)
}
})
)
})
.then(() => {
console.log('Service Worker: Activation complete')
// Take control of all pages immediately
return self.clients.claim()
})
.then(() => {
// Notify all clients about the update
return self.clients.matchAll().then(clients => {
clients.forEach(client => {
client.postMessage({
type: 'SW_UPDATED',
version: CACHE_VERSION,
timestamp: BUILD_TIMESTAMP,
appVersion: APP_VERSION
})
})
})
})
)
})
// Fetch event - serve from cache or network
self.addEventListener('fetch', (event) => {
const { request } = event
const url = new URL(request.url)
// Skip non-GET requests
if (request.method !== 'GET') return
// Skip cross-origin requests
if (url.origin !== location.origin) return
// Handle different types of requests
if (url.pathname.startsWith('/api/')) {
// API requests - network first, then cache
event.respondWith(handleApiRequest(request))
} else if (url.pathname.startsWith('/_next/static/')) {
// Static assets - cache first
event.respondWith(handleStaticAssets(request))
} else {
// Pages - network first, then cache
event.respondWith(handlePageRequest(request))
}
})
// Handle API requests
async function handleApiRequest(request) {
const url = new URL(request.url)
try {
// Try network first
const networkResponse = await fetch(request)
// Cache successful responses for GET requests
if (networkResponse.ok && request.method === 'GET') {
const cache = await caches.open(DYNAMIC_CACHE_NAME)
cache.put(request, networkResponse.clone())
}
return networkResponse
} catch (error) {
// Network failed, try cache
const cachedResponse = await caches.match(request)
if (cachedResponse) {
return cachedResponse
}
// Return offline response for API calls
return new Response(
JSON.stringify({
error: 'Network unavailable',
offline: true,
message: 'You are currently offline. Please check your internet connection to access fresh product information.'
}),
{
status: 503,
headers: { 'Content-Type': 'application/json' }
}
)
}
}
// Handle static assets
async function handleStaticAssets(request) {
try {
// Try cache first
const cachedResponse = await caches.match(request)
if (cachedResponse) {
return cachedResponse
}
// Try network
const networkResponse = await fetch(request)
// Cache the response
const cache = await caches.open(STATIC_CACHE_NAME)
cache.put(request, networkResponse.clone())
return networkResponse
} catch (error) {
// Return cached version or fail silently for assets
return caches.match(request)
}
}
// Handle page requests
async function handlePageRequest(request) {
try {
// Try network first
const networkResponse = await fetch(request)
// Cache successful responses
if (networkResponse.ok) {
const cache = await caches.open(DYNAMIC_CACHE_NAME)
cache.put(request, networkResponse.clone())
}
return networkResponse
} catch (error) {
// Network failed, try cache
const cachedResponse = await caches.match(request)
if (cachedResponse) {
return cachedResponse
}
// Return offline page
const offlineResponse = await caches.match('/offline')
return offlineResponse || new Response('Offline', { status: 503 })
}
}
// Background sync for offline actions
self.addEventListener('sync', (event) => {
console.log('Service Worker: Background sync', event.tag)
if (event.tag === 'cart-sync') {
event.waitUntil(syncCart())
} else if (event.tag === 'order-sync') {
event.waitUntil(syncOrders())
} else if (event.tag === 'contact-sync') {
event.waitUntil(syncContactForms())
}
})
// Sync cart data when online
async function syncCart() {
try {
// Get stored cart data
const cartData = await getStoredData('cart')
if (cartData) {
// Sync with server
await fetch('/api/cart/sync', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(cartData)
})
// Clear stored data
await clearStoredData('cart')
}
} catch (error) {
console.error('Cart sync failed:', error)
}
}
// Sync order data when online
async function syncOrders() {
try {
const orderData = await getStoredData('orders')
if (orderData) {
await fetch('/api/orders/sync', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(orderData)
})
await clearStoredData('orders')
}
} catch (error) {
console.error('Order sync failed:', error)
}
}
// Sync contact form data when online
async function syncContactForms() {
try {
const contactData = await getStoredData('contact')
if (contactData) {
await fetch('/api/contact/sync', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(contactData)
})
await clearStoredData('contact')
}
} catch (error) {
console.error('Contact sync failed:', error)
}
}
// Push notification handling
self.addEventListener('push', (event) => {
console.log('Service Worker: Push notification received')
const options = {
body: 'New authentic food products available at Padmaaja Rasooi!',
icon: '/icons/icon-192x192.png',
badge: '/icons/badge-72x72.png',
vibrate: [100, 50, 100],
data: {
dateOfArrival: Date.now(),
primaryKey: 1
},
actions: [
{
action: 'explore',
title: 'View Products',
icon: '/icons/action-products.png'
},
{
action: 'close',
title: 'Close',
icon: '/icons/action-close.png'
}
]
}
event.waitUntil(
self.registration.showNotification('Padmaaja Rasooi', options)
)
})
// Notification click handling
self.addEventListener('notificationclick', (event) => {
console.log('Service Worker: Notification clicked')
event.notification.close()
if (event.action === 'explore') {
event.waitUntil(
clients.openWindow('/products')
)
} else if (event.action === 'close') {
// Just close the notification
} else {
// Default action - open app
event.waitUntil(
clients.openWindow('/')
)
}
})
// Handle messages from the main thread
self.addEventListener('message', (event) => {
console.log('Service Worker: Message received', event.data)
if (event.data && event.data.type === 'SKIP_WAITING') {
// Force the waiting service worker to become the active service worker
self.skipWaiting()
}
if (event.data && event.data.type === 'CACHE_INVALIDATE') {
// Clear all caches and force reload
event.waitUntil(
caches.keys().then(cacheNames => {
return Promise.all(
cacheNames.map(cacheName => caches.delete(cacheName))
)
}).then(() => {
// Notify client that caches are cleared
event.ports[0].postMessage({ success: true })
})
)
}
})
// Utility functions
async function getStoredData(key) {
try {
const cache = await caches.open(DYNAMIC_CACHE_NAME)
const response = await cache.match(`/offline-data/${key}`)
return response ? response.json() : null
} catch (error) {
return null
}
}
async function clearStoredData(key) {
try {
const cache = await caches.open(DYNAMIC_CACHE_NAME)
await cache.delete(`/offline-data/${key}`)
} catch (error) {
console.error('Failed to clear stored data:', error)
}
}