Skip to content

Commit a2c290f

Browse files
committed
feat: Add premium splash screens, fix expo development build, and clean up code
1 parent f9dbb5f commit a2c290f

6 files changed

Lines changed: 616 additions & 214 deletions

File tree

frontend/src/App.jsx

Lines changed: 168 additions & 117 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { useState, useMemo } from 'react'
1+
import { useState, useMemo, useEffect } from 'react'
22
import Header from './components/Header'
33
import Sidebar from './components/Sidebar'
44
import ProductGrid from './components/ProductGrid'
@@ -11,6 +11,7 @@ import Checkout from './components/Checkout'
1111
import AccountModal from './components/AccountModal'
1212

1313
function App() {
14+
const [showSplash, setShowSplash] = useState(true);
1415
const [selectedCategories, setSelectedCategories] = useState([]);
1516
const [selectedThemes, setSelectedThemes] = useState([]);
1617
const [selectedProduct, setSelectedProduct] = useState(null);
@@ -41,6 +42,13 @@ function App() {
4142
} catch { return []; }
4243
});
4344

45+
useEffect(() => {
46+
const timer = setTimeout(() => {
47+
setShowSplash(false);
48+
}, 2500);
49+
return () => clearTimeout(timer);
50+
}, []);
51+
4452
const userOrdersKey = (user) => `zappify_orders_${user?.email}`;
4553

4654
const handleLogin = (user) => {
@@ -119,130 +127,173 @@ function App() {
119127
const isEmbed = new URLSearchParams(window.location.search).get('embed') === '1';
120128

121129
return (
122-
<div className="zappify-app">
123-
{!isEmbed && <Header
124-
onOpenOverlay={setActiveOverlay}
125-
onNavigate={handleNavigate}
126-
cartCount={cartItems.reduce((sum, i) => sum + i.qty, 0)}
127-
wishlistCount={wishlistItems.length}
128-
activeNav={activeNav}
129-
loggedInUser={loggedInUser}
130-
onOpenAccount={() => setShowAccount(true)}
131-
searchQuery={searchQuery}
132-
onSearch={setSearchQuery}
133-
/>}
134-
135-
<main className="app-main">
136-
<div className="container-broad main-layout">
137-
<AnimatePresence mode="wait">
138-
{!selectedProduct ? (
139-
<motion.div
140-
key="grid"
141-
className="grid-view"
142-
initial={{ opacity: 0, x: -20 }}
143-
animate={{ opacity: 1, x: 0 }}
144-
exit={{ opacity: 0, x: -20 }}
145-
transition={{ duration: 0.3 }}
146-
>
147-
<div className="layout-split">
148-
<Sidebar
149-
selectedCategories={selectedCategories}
150-
selectedThemes={selectedThemes}
151-
onToggleFilter={toggleFilter}
152-
/>
153-
<ProductGrid
154-
products={filteredProducts}
155-
onProductClick={(product) => { setSelectedProduct(product); window.scrollTo({ top: 0, behavior: 'smooth' }); }}
156-
onToggleWishlist={toggleWishlist}
157-
isWishlisted={isWishlisted}
158-
/>
159-
</div>
160-
</motion.div>
161-
) : (
162-
<motion.div
163-
key="detail"
164-
className="detail-view"
165-
initial={{ opacity: 0, y: 20 }}
166-
animate={{ opacity: 1, y: 0 }}
167-
exit={{ opacity: 0, y: -20 }}
168-
transition={{ duration: 0.4 }}
169-
>
170-
<ProductDetail
171-
product={selectedProduct}
172-
onBack={() => setSelectedProduct(null)}
173-
onAddToCart={addToCart}
174-
onToggleWishlist={toggleWishlist}
175-
isWishlisted={isWishlisted(selectedProduct.id)}
176-
/>
177-
</motion.div>
130+
<AnimatePresence mode="wait">
131+
{showSplash ? (
132+
<SplashScreen key="splash" />
133+
) : (
134+
<motion.div
135+
key="app-content"
136+
className="zappify-app"
137+
initial={{ opacity: 0 }}
138+
animate={{ opacity: 1 }}
139+
transition={{ duration: 0.8 }}
140+
>
141+
{!isEmbed && <Header
142+
onOpenOverlay={setActiveOverlay}
143+
onNavigate={handleNavigate}
144+
cartCount={cartItems.reduce((sum, i) => sum + i.qty, 0)}
145+
wishlistCount={wishlistItems.length}
146+
activeNav={activeNav}
147+
loggedInUser={loggedInUser}
148+
onOpenAccount={() => setShowAccount(true)}
149+
searchQuery={searchQuery}
150+
onSearch={setSearchQuery}
151+
/>}
152+
153+
<main className="app-main">
154+
<div className="container-broad main-layout">
155+
<AnimatePresence mode="wait">
156+
{!selectedProduct ? (
157+
<motion.div
158+
key="grid"
159+
className="grid-view"
160+
initial={{ opacity: 0, x: -20 }}
161+
animate={{ opacity: 1, x: 0 }}
162+
exit={{ opacity: 0, x: -20 }}
163+
transition={{ duration: 0.3 }}
164+
>
165+
<div className="layout-split">
166+
<Sidebar
167+
selectedCategories={selectedCategories}
168+
selectedThemes={selectedThemes}
169+
onToggleFilter={toggleFilter}
170+
/>
171+
<ProductGrid
172+
products={filteredProducts}
173+
onProductClick={(product) => { setSelectedProduct(product); window.scrollTo({ top: 0, behavior: 'smooth' }); }}
174+
onToggleWishlist={toggleWishlist}
175+
isWishlisted={isWishlisted}
176+
/>
177+
</div>
178+
</motion.div>
179+
) : (
180+
<motion.div
181+
key="detail"
182+
className="detail-view"
183+
initial={{ opacity: 0, y: 20 }}
184+
animate={{ opacity: 1, y: 0 }}
185+
exit={{ opacity: 0, y: -20 }}
186+
transition={{ duration: 0.4 }}
187+
>
188+
<ProductDetail
189+
product={selectedProduct}
190+
onBack={() => setSelectedProduct(null)}
191+
onAddToCart={addToCart}
192+
onToggleWishlist={toggleWishlist}
193+
isWishlisted={isWishlisted(selectedProduct.id)}
194+
/>
195+
</motion.div>
196+
)}
197+
</AnimatePresence>
198+
</div>
199+
</main>
200+
201+
<footer className="zappify-footer">
202+
<div className="container-broad">
203+
<div className="footer-bottom">
204+
<p>&copy; 2026 Zappify Shoe Store. All rights reserved.</p>
205+
</div>
206+
</div>
207+
</footer>
208+
209+
<AnimatePresence>
210+
{activeOverlay && (
211+
<Overlay
212+
type={activeOverlay}
213+
onClose={() => setActiveOverlay(null)}
214+
cartItems={cartItems}
215+
wishlistItems={wishlistItems}
216+
onRemoveFromCart={removeFromCart}
217+
onToggleWishlist={toggleWishlist}
218+
onLoginSuccess={handleLogin}
219+
onCheckout={() => { setActiveOverlay(null); setShowCheckout(true); }}
220+
loggedInUser={loggedInUser}
221+
onSwitchOverlay={setActiveOverlay}
222+
/>
178223
)}
179224
</AnimatePresence>
180-
</div>
181-
</main>
182225

183-
<footer className="zappify-footer">
184-
<div className="container-broad">
185-
<div className="footer-bottom">
186-
<p>&copy; 2026 Zappify Shoe Store. All rights reserved.</p>
187-
</div>
188-
</div>
189-
</footer>
190-
191-
<AnimatePresence>
192-
{activeOverlay && (
193-
<Overlay
194-
type={activeOverlay}
195-
onClose={() => setActiveOverlay(null)}
196-
cartItems={cartItems}
197-
wishlistItems={wishlistItems}
198-
onRemoveFromCart={removeFromCart}
199-
onToggleWishlist={toggleWishlist}
200-
onLoginSuccess={handleLogin}
201-
onCheckout={() => { setActiveOverlay(null); setShowCheckout(true); }}
202-
loggedInUser={loggedInUser}
203-
onSwitchOverlay={setActiveOverlay}
204-
/>
205-
)}
206-
</AnimatePresence>
207-
208-
{showCheckout && (
209-
<Checkout
210-
cartItems={cartItems}
211-
onClose={() => setShowCheckout(false)}
212-
onRemoveFromCart={removeFromCart}
213-
onOrderPlaced={(items) => {
214-
const newOrders = items.map(item => ({
215-
...item,
216-
orderId: Math.floor(10000000 + Math.random() * 90000000).toString(),
217-
placedAt: new Date().toISOString(),
218-
status: 'Placed',
219-
}));
220-
const updated = [...placedOrders, ...newOrders];
221-
setPlacedOrders(updated);
222-
localStorage.setItem(userOrdersKey(loggedInUser), JSON.stringify(updated));
223-
setCartItems([]);
224-
localStorage.removeItem('zappify_cart');
225-
}}
226-
/>
227-
)}
226+
{showCheckout && (
227+
<Checkout
228+
cartItems={cartItems}
229+
onClose={() => setShowCheckout(false)}
230+
onRemoveFromCart={removeFromCart}
231+
onOrderPlaced={(items) => {
232+
const newOrders = items.map(item => ({
233+
...item,
234+
orderId: Math.floor(10000000 + Math.random() * 90000000).toString(),
235+
placedAt: new Date().toISOString(),
236+
status: 'Placed',
237+
}));
238+
const updated = [...placedOrders, ...newOrders];
239+
setPlacedOrders(updated);
240+
localStorage.setItem(userOrdersKey(loggedInUser), JSON.stringify(updated));
241+
setCartItems([]);
242+
localStorage.removeItem('zappify_cart');
243+
}}
244+
/>
245+
)}
228246

229-
{showAccount && loggedInUser && (
230-
<AccountModal
231-
user={loggedInUser}
232-
orders={placedOrders}
233-
onClose={() => setShowAccount(false)}
234-
onLogout={() => { handleLogout(); setShowAccount(false); }}
235-
onCancelOrder={(orderId) => {
236-
const updated = placedOrders.map(o => o.orderId === orderId ? { ...o, status: 'Cancelled' } : o);
237-
setPlacedOrders(updated);
238-
localStorage.setItem(userOrdersKey(loggedInUser), JSON.stringify(updated));
239-
}}
240-
/>
247+
{showAccount && loggedInUser && (
248+
<AccountModal
249+
user={loggedInUser}
250+
orders={placedOrders}
251+
onClose={() => setShowAccount(false)}
252+
onLogout={() => { handleLogout(); setShowAccount(false); }}
253+
onCancelOrder={(orderId) => {
254+
const updated = placedOrders.map(o => o.orderId === orderId ? { ...o, status: 'Cancelled' } : o);
255+
setPlacedOrders(updated);
256+
localStorage.setItem(userOrdersKey(loggedInUser), JSON.stringify(updated));
257+
}}
258+
/>
259+
)}
260+
</motion.div>
241261
)}
242-
</div>
262+
</AnimatePresence>
243263
);
244264
}
245265

266+
const SplashScreen = () => (
267+
<motion.div
268+
className="splash-container"
269+
initial={{ opacity: 1 }}
270+
exit={{ opacity: 0 }}
271+
transition={{ duration: 0.8, ease: "easeInOut" }}
272+
>
273+
<motion.div
274+
className="splash-content"
275+
initial={{ scale: 0.85, opacity: 0, y: 10 }}
276+
animate={{ scale: 1, opacity: 1, y: 0 }}
277+
transition={{
278+
duration: 1,
279+
ease: [0.22, 1, 0.36, 1],
280+
opacity: { duration: 0.6 }
281+
}}
282+
>
283+
<div className="splash-logo">
284+
<span>Z</span>appify
285+
</div>
286+
<div className="splash-subtitle">Premium Shoe Store</div>
287+
<motion.div
288+
className="splash-loader"
289+
initial={{ opacity: 0 }}
290+
animate={{ opacity: 1 }}
291+
transition={{ delay: 0.8 }}
292+
/>
293+
</motion.div>
294+
</motion.div>
295+
);
296+
246297
const Overlay = ({ type, onClose, cartItems, wishlistItems, onRemoveFromCart, onToggleWishlist, onLoginSuccess, onCheckout, loggedInUser, onSwitchOverlay }) => {
247298
const [isSignUp, setIsSignUp] = useState(false);
248299
const [formData, setFormData] = useState({ name: '', email: '', password: '', confirm: '' });

0 commit comments

Comments
 (0)