eeshaAI commited on
Commit
aa1f0fd
·
1 Parent(s): 4d91720

fix: search shows products immediately (AI loads in background) + more dramatic page transitions

Browse files
Files changed (2) hide show
  1. src/app/search/page.tsx +21 -18
  2. src/app/template.tsx +6 -9
src/app/search/page.tsx CHANGED
@@ -35,19 +35,10 @@ function SearchContent() {
35
  setAllProducts([]);
36
  setVideos([]);
37
 
38
- // Search products + videos in parallel with AI
39
- const [searchResp, vidResp, aiResp] = await Promise.all([
40
  api.products.search(q, null),
41
  api.videos.feed(50).catch(() => ({ success: false, videos: [] })),
42
- fetch('/api/ai-chat', {
43
- method: 'POST',
44
- headers: { 'Content-Type': 'application/json' },
45
- body: JSON.stringify({
46
- message: `A user searched for "${q}" on Cellex (a Nigerian e-commerce marketplace). Provide a helpful, comprehensive answer about what's available. Mention types of products, price ranges, and shopping tips. Be friendly and informative (2-3 paragraphs).`,
47
- context: 'Search overview',
48
- history: [],
49
- }),
50
- }),
51
  ]);
52
 
53
  const products = searchResp.success
@@ -55,6 +46,7 @@ function SearchContent() {
55
  : [];
56
  setAllProducts(products);
57
  setAiProducts(products.slice(0, 4));
 
58
 
59
  // Filter videos
60
  if (vidResp.success) {
@@ -67,15 +59,26 @@ function SearchContent() {
67
  setVideos(filtered);
68
  }
69
 
70
- // AI response
71
- if (aiResp.ok) {
72
- const data = await aiResp.json();
73
- setAiAnswer(data.reply || data.message || data.content || `Here's what I found for "${q}": ${products.length} products available.`);
74
- } else {
 
 
 
 
 
 
 
 
 
 
 
 
 
75
  setAiAnswer(`Here's what I found for "${q}": ${products.length} products available on Cellex.`);
76
  }
77
-
78
- setLoading(false);
79
  }, []);
80
 
81
  useEffect(() => {
 
35
  setAllProducts([]);
36
  setVideos([]);
37
 
38
+ // Step 1: Fetch products + videos FIRST (fast, shows results immediately)
39
+ const [searchResp, vidResp] = await Promise.all([
40
  api.products.search(q, null),
41
  api.videos.feed(50).catch(() => ({ success: false, videos: [] })),
 
 
 
 
 
 
 
 
 
42
  ]);
43
 
44
  const products = searchResp.success
 
46
  : [];
47
  setAllProducts(products);
48
  setAiProducts(products.slice(0, 4));
49
+ setLoading(false); // Stop loading — products are visible now
50
 
51
  // Filter videos
52
  if (vidResp.success) {
 
59
  setVideos(filtered);
60
  }
61
 
62
+ // Step 2: Fetch AI response IN THE BACKGROUND (don't block product display)
63
+ try {
64
+ const aiResp = await fetch('/api/ai-chat', {
65
+ method: 'POST',
66
+ headers: { 'Content-Type': 'application/json' },
67
+ body: JSON.stringify({
68
+ message: `A user searched for "${q}" on Cellex (a Nigerian e-commerce marketplace). Provide a helpful, comprehensive answer about what's available. Mention types of products, price ranges, and shopping tips. Be friendly and informative (2-3 paragraphs).`,
69
+ context: 'Search overview',
70
+ history: [],
71
+ }),
72
+ });
73
+ if (aiResp.ok) {
74
+ const data = await aiResp.json();
75
+ setAiAnswer(data.reply || data.message || data.content || `Here's what I found for "${q}": ${products.length} products available on Cellex.`);
76
+ } else {
77
+ setAiAnswer(`Here's what I found for "${q}": ${products.length} products available on Cellex.`);
78
+ }
79
+ } catch {
80
  setAiAnswer(`Here's what I found for "${q}": ${products.length} products available on Cellex.`);
81
  }
 
 
82
  }, []);
83
 
84
  useEffect(() => {
src/app/template.tsx CHANGED
@@ -5,11 +5,8 @@ import { motion } from 'framer-motion';
5
 
6
  /**
7
  * Template — cinematic page transitions using framer-motion.
8
- *
9
- * Each page:
10
- * - Enters: slides in from right (12px) + fades in + slides up (8px)
11
- * - Uses spring physics for a natural, premium feel
12
- * - Re-triggers on every pathname change
13
  */
14
  export default function Template({ children }: { children: React.ReactNode }) {
15
  const pathname = usePathname();
@@ -17,10 +14,10 @@ export default function Template({ children }: { children: React.ReactNode }) {
17
  return (
18
  <motion.div
19
  key={pathname}
20
- initial={{ opacity: 0, x: 12, y: 8 }}
21
- animate={{ opacity: 1, x: 0, y: 0 }}
22
- exit={{ opacity: 0, x: -12, scale: 0.98 }}
23
- transition={{ duration: 0.35, ease: [0.32, 0.72, 0, 1] }}
24
  >
25
  {children}
26
  </motion.div>
 
5
 
6
  /**
7
  * Template — cinematic page transitions using framer-motion.
8
+ * More dramatic: slides in from right + scales up slightly + fades in.
9
+ * Re-triggers on every pathname change.
 
 
 
10
  */
11
  export default function Template({ children }: { children: React.ReactNode }) {
12
  const pathname = usePathname();
 
14
  return (
15
  <motion.div
16
  key={pathname}
17
+ initial={{ opacity: 0, x: 30, scale: 0.98 }}
18
+ animate={{ opacity: 1, x: 0, scale: 1 }}
19
+ transition={{ duration: 0.4, ease: [0.22, 1, 0.36, 1] }}
20
+ style={{ willChange: 'transform, opacity' }}
21
  >
22
  {children}
23
  </motion.div>