feat: enhance landing page, for-people sections, blog main, and components including TheLoop and PhoneMockup

This commit is contained in:
R-Bharathraj
2026-07-06 13:21:09 +05:30
parent 727a6bcb62
commit 57e64f86b6
18 changed files with 1037 additions and 386 deletions

View File

@@ -1,8 +1,10 @@
'use client';
import React, { useEffect, useRef, useState } from 'react';
import Image from 'next/image';
import { gsap } from 'gsap';
import { ScrollTrigger } from 'gsap/ScrollTrigger';
import { PhoneFrame, PhoneBottomNav, BellIcon, FlameIcon } from './PhoneMockup';
if (typeof window !== 'undefined') gsap.registerPlugin(ScrollTrigger);
@@ -11,9 +13,6 @@ const feed = [
{ store: 'Walking 5,000 steps', pts: +80, time: '1h ago', type: 'earn' },
{ store: 'Spin Wheel Game', pts: +120, time: '3h ago', type: 'earn' },
{ store: 'Selfie Booth', pts: +200, time: 'Yesterday', type: 'earn' },
{ store: 'Scratch Card', pts: +40, time: 'Yesterday', type: 'earn' },
{ store: 'Match Master', pts: +75, time: '2 days ago', type: 'earn' },
{ store: 'Maze Challenge', pts: +95, time: '3 days ago', type: 'earn' },
];
export default function EarnRewardsSection() {
@@ -35,27 +34,20 @@ export default function EarnRewardsSection() {
rowRefs.current.forEach((row, i) => {
if (!row) return;
const active = i === idx;
row.style.background = active ? '#16a34a' : 'rgba(23,21,18,0.55)';
row.style.borderColor = active ? '#16a34a' : 'rgba(255,255,255,0.14)';
row.style.transform = active ? 'translateX(10px) scale(1.06)' : 'translateX(0) scale(1)';
row.style.boxShadow = active ? '0 16px 40px -12px rgba(22,163,74,0.5)' : 'none';
row.style.zIndex = active ? '2' : '1';
row.style.background = active ? '#f0fdf4' : 'transparent';
row.style.borderColor = active ? '#16a34a' : 'transparent';
row.style.transform = active ? 'translateX(4px) scale(1.02)' : 'translateX(0) scale(1)';
row.style.boxShadow = active ? '0 10px 24px -12px rgba(22,163,74,0.35)' : 'none';
// Flip inner text/icon colors for contrast per background
const title = row.querySelector<HTMLElement>('.feed-title');
if (title) title.style.color = '#ffffff';
const time = row.querySelector<HTMLElement>('.feed-time');
if (time) time.style.color = active ? 'rgba(255,255,255,0.75)' : 'rgba(255,255,255,0.55)';
const icon = row.querySelector<HTMLElement>('.feed-icon');
if (icon) {
icon.style.background = active ? 'rgba(255,255,255,0.15)' : 'rgba(74,222,128,0.1)';
icon.style.borderColor = active ? 'rgba(255,255,255,0.5)' : 'rgba(74,222,128,0.45)';
icon.style.color = active ? '#ffffff' : '#4ade80';
icon.style.background = active ? 'rgba(22,163,74,0.14)' : 'rgba(23,21,18,0.04)';
icon.style.borderColor = active ? '#16a34a' : 'rgba(23,21,18,0.08)';
icon.style.color = active ? '#16a34a' : '#9ca3af';
}
const points = row.querySelector<HTMLElement>('.feed-pts');
if (points) {
points.style.color = active ? '#ffffff' : '#4ade80';
points.style.background = active ? 'rgba(255,255,255,0.15)' : 'rgba(74,222,128,0.12)';
points.style.background = active ? 'rgba(22,163,74,0.14)' : 'rgba(22,163,74,0.08)';
}
});
};
@@ -103,7 +95,7 @@ export default function EarnRewardsSection() {
background: '#f0fdf4', border: '1.5px solid #16a34a', borderRadius: 100, padding: '7px 16px',
}}>
<span style={{ width: 7, height: 7, borderRadius: '50%', background: '#16a34a', flexShrink: 0, animation: 'fpPulse 1.5s infinite' }} />
<span style={{ fontSize: 11, fontWeight: 700, color: '#16a34a', fontFamily: 'Sora, sans-serif', letterSpacing: '0.1em', textTransform: 'uppercase' }}>Live LYT balance</span>
<span style={{ fontSize: 11, fontWeight: 700, color: '#16a34a', fontFamily: 'Sora, sans-serif', letterSpacing: '0.1em', textTransform: 'uppercase' }}>Live LYTs balance</span>
</div>
{/* Giant gold number */}
@@ -125,7 +117,7 @@ export default function EarnRewardsSection() {
<span style={{ fontSize: 13, color: '#4f463a', fontFamily: 'Sora, sans-serif' }}>redeemable value</span>
</div>
<div style={{ marginBottom: 16 }}><span className="fp-kicker fp-rise">Earn<span className="fp-kicker-num">03</span></span></div>
<div style={{ marginBottom: 16 }}><span className="fp-kicker fp-rise">Earn<span className="fp-kicker-num">04</span></span></div>
<h2 style={{
fontSize: 'clamp(28px, 3.4vw, 48px)', fontWeight: 800, lineHeight: 1.08,
@@ -139,83 +131,107 @@ export default function EarnRewardsSection() {
<p className="fp-rise" style={{
fontSize: 15, lineHeight: 1.8, color: '#4f463a', fontFamily: 'Sora, sans-serif', maxWidth: 380, margin: 0,
}}>
Earn LYT (Loyaly Tokens) through daily app login, completing 5,000-step walking challenges, playing Maze, Spin Wheel, Scratch Card, and Match Master games, or visiting Selfie Booths at partner malls. Every activity adds more LYT to your balance.
Earn LYTs (Loyaly Tokens) through daily app login, completing 5,000-step walking challenges, playing Maze, Spin Wheel, Scratch Card, and Match Master games, or visiting Selfie Booths at partner malls. Every activity adds more LYTs to your balance.
</p>
</div>
{/* Right — live feed */}
<div className="fp-rise" style={{ transitionDelay: '0.15s' }}>
{/* Feed header */}
<div style={{
display: 'flex', justifyContent: 'space-between', alignItems: 'center',
marginBottom: 14, paddingBottom: 14, borderBottom: '2px solid #f4be28',
}}>
<span style={{ fontSize: 12, fontWeight: 700, letterSpacing: '0.14em', textTransform: 'uppercase', color: '#171512', fontFamily: 'Sora, sans-serif' }}>Activity feed</span>
<span style={{ fontSize: 11, color: '#16a34a', fontWeight: 700, fontFamily: 'Sora, sans-serif', display: 'flex', alignItems: 'center', gap: 5,
background: '#f0fdf4', border: '1px solid #16a34a', borderRadius: 100, padding: '4px 10px',
}}>
<span style={{ width: 5, height: 5, borderRadius: '50%', background: '#16a34a', display: 'block', animation: 'fpPulse 1.5s infinite' }} />
LIVE
</span>
</div>
{/* Right — phone mockup, matches the in-app Earn / Home experience */}
<div className="fp-rise" style={{ transitionDelay: '0.15s', display: 'flex', justifyContent: 'center' }}>
<PhoneFrame floatClassName="erm-phone-shell">
{/* Feed rows */}
<div style={{ display: 'flex', flexDirection: 'column', gap: 6 }}>
{feed.map((tx, i) => (
<div key={i} ref={el => { rowRefs.current[i] = el; }} style={{
position: 'relative', zIndex: i === 0 ? 2 : 1,
display: 'flex', alignItems: 'center', justifyContent: 'space-between',
padding: '12px 14px', borderRadius: 12,
background: i === 0 ? '#16a34a' : 'rgba(23,21,18,0.55)',
border: `1.5px solid ${i === 0 ? '#16a34a' : 'rgba(255,255,255,0.14)'}`,
backdropFilter: 'blur(16px)',
WebkitBackdropFilter: 'blur(16px)',
transform: i === 0 ? 'translateX(10px) scale(1.06)' : 'translateX(0) scale(1)',
boxShadow: i === 0 ? '0 16px 40px -12px rgba(22,163,74,0.5)' : 'none',
transition: 'background 0.35s ease, border-color 0.35s ease, transform 0.35s cubic-bezier(0.34,1.56,0.64,1), box-shadow 0.35s ease',
}}>
<div style={{ display: 'flex', alignItems: 'center', gap: 12 }}>
<div className="feed-icon" style={{
width: 36, height: 36, borderRadius: 10, flexShrink: 0,
background: i === 0 ? 'rgba(255,255,255,0.15)' : 'rgba(74,222,128,0.1)',
border: `1.5px solid ${i === 0 ? 'rgba(255,255,255,0.5)' : 'rgba(74,222,128,0.45)'}`,
display: 'flex', alignItems: 'center', justifyContent: 'center',
fontSize: 15, fontWeight: 900,
color: i === 0 ? '#ffffff' : '#4ade80',
transition: 'background 0.35s ease, border-color 0.35s ease, color 0.35s ease',
}}>{tx.type === 'earn' ? '↑' : '↓'}</div>
<div>
<div className="feed-title" style={{ fontSize: 13, fontWeight: 700, color: '#ffffff', fontFamily: 'Sora, sans-serif', transition: 'color 0.35s ease' }}>{tx.store}</div>
<div className="feed-time" style={{ fontSize: 11, color: i === 0 ? 'rgba(255,255,255,0.75)' : 'rgba(255,255,255,0.55)', fontFamily: 'Sora, sans-serif', marginTop: 1, transition: 'color 0.35s ease' }}>{tx.time}</div>
</div>
{/* Amber header */}
<div style={{ background: 'linear-gradient(180deg, #fcd34d 0%, #f4be28 100%)', padding: '34px 16px 14px' }}>
<div style={{ display: 'flex', alignItems: 'center', justifyContent: 'space-between', marginBottom: 12 }}>
<Image src="/images/loyalyai.png" alt="Loyaly.AI" width={100} height={26} style={{ objectFit: 'contain', height: 16, width: 'auto' }} />
<div style={{ width: 26, height: 26, borderRadius: '50%', background: 'rgba(255,255,255,0.55)', display: 'flex', alignItems: 'center', justifyContent: 'center' }}>
<BellIcon />
</div>
<span className="feed-pts" style={{
fontSize: 15, fontWeight: 900, fontFamily: 'Sora, sans-serif',
color: i === 0 ? '#ffffff' : '#4ade80', letterSpacing: '-0.02em',
background: i === 0 ? 'rgba(255,255,255,0.15)' : 'rgba(74,222,128,0.12)',
padding: '4px 10px', borderRadius: 8,
transition: 'color 0.35s ease, background 0.35s ease',
}}>
{tx.pts > 0 ? '+' : ''}{tx.pts}
</span>
</div>
))}
</div>
<div style={{ display: 'flex', alignItems: 'center', gap: 6 }}>
<FlameIcon />
<span style={{ fontSize: 11.5, fontWeight: 600, color: '#171512', fontFamily: 'Sora, sans-serif' }}>6-day streak · keep it going!</span>
</div>
</div>
{/* Summary strip */}
<div style={{
marginTop: 16, display: 'grid', gridTemplateColumns: '1fr 1fr', gap: 10,
}}>
{[
{ label: 'Earned this month', val: '660 LYT', color: '#16a34a', bg: '#f0fdf4', border: '#16a34a' },
{ label: 'Redeemable value', val: '₹660', color: '#f4be28', bg: '#fff7e0', border: '#f4be28' },
].map((s, i) => (
<div key={i} style={{ padding: '14px 16px', borderRadius: 14, background: s.bg, border: `1.5px solid ${s.border}` }}>
<div style={{ fontSize: 11, color: 'rgba(23,21,18,0.5)', fontFamily: 'Sora, sans-serif', marginBottom: 4 }}>{s.label}</div>
<div style={{ fontSize: 18, fontWeight: 900, color: s.color, fontFamily: 'Sora, sans-serif' }}>{s.val}</div>
</div>
))}
</div>
{/* Balance card */}
<div style={{ margin: '14px 14px 0', borderRadius: 18, padding: '16px 18px', background: 'linear-gradient(135deg, #f4be28 0%, #e09820 100%)', position: 'relative', overflow: 'hidden' }}>
<div style={{ position: 'absolute', top: '-30%', right: '-8%', width: 90, height: 90, borderRadius: '50%', background: 'rgba(255,255,255,0.14)' }} />
<div style={{ fontSize: 10, color: 'rgba(23,21,18,0.65)', fontWeight: 700, fontFamily: 'Sora, sans-serif', letterSpacing: '0.1em', textTransform: 'uppercase' }}>Total LYTs</div>
<div style={{ fontSize: 30, color: '#171512', fontWeight: 900, fontFamily: 'Sora, sans-serif', letterSpacing: '-0.03em', marginTop: 2 }}>284</div>
<div style={{ fontSize: 10.5, color: 'rgba(23,21,18,0.6)', fontFamily: 'Sora, sans-serif', marginTop: 3 }}> 284 redeemable</div>
</div>
{/* Feed header */}
<div style={{
display: 'flex', justifyContent: 'space-between', alignItems: 'center',
margin: '16px 14px 6px',
}}>
<span style={{ fontSize: 10.5, fontWeight: 700, letterSpacing: '0.1em', textTransform: 'uppercase', color: '#171512', fontFamily: 'Sora, sans-serif' }}>Activity feed</span>
<span style={{ fontSize: 9.5, color: '#16a34a', fontWeight: 700, fontFamily: 'Sora, sans-serif', display: 'flex', alignItems: 'center', gap: 4,
background: '#f0fdf4', border: '1px solid #16a34a', borderRadius: 100, padding: '3px 8px',
}}>
<span style={{ width: 4.5, height: 4.5, borderRadius: '50%', background: '#16a34a', display: 'block', animation: 'fpPulse 1.5s infinite' }} />
LIVE
</span>
</div>
{/* Feed rows */}
<div style={{ padding: '2px 10px', display: 'flex', flexDirection: 'column', gap: 3 }}>
{feed.map((tx, i) => (
<div key={i} ref={el => { rowRefs.current[i] = el; }} style={{
display: 'grid', gridTemplateColumns: '32px minmax(0,1fr) auto', alignItems: 'center', gap: 10,
padding: '8px 8px', borderRadius: 12,
background: i === 0 ? '#f0fdf4' : 'transparent',
border: `1px solid ${i === 0 ? '#16a34a' : 'transparent'}`,
transform: i === 0 ? 'translateX(4px) scale(1.02)' : 'translateX(0) scale(1)',
boxShadow: i === 0 ? '0 10px 24px -12px rgba(22,163,74,0.35)' : 'none',
transition: 'background 0.35s ease, border-color 0.35s ease, transform 0.35s cubic-bezier(0.34,1.56,0.64,1), box-shadow 0.35s ease',
}}>
<div className="feed-icon" style={{
width: 32, height: 32, borderRadius: 9, flexShrink: 0,
background: i === 0 ? 'rgba(22,163,74,0.14)' : 'rgba(23,21,18,0.04)',
border: `1.5px solid ${i === 0 ? '#16a34a' : 'rgba(23,21,18,0.08)'}`,
display: 'flex', alignItems: 'center', justifyContent: 'center',
color: i === 0 ? '#16a34a' : '#9ca3af',
transition: 'background 0.35s ease, border-color 0.35s ease, color 0.35s ease',
}}>
<svg width="13" height="13" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2.6" strokeLinecap="round" strokeLinejoin="round"><path d="M12 19V5" /><path d="M5 12l7-7 7 7" /></svg>
</div>
<div style={{ minWidth: 0 }}>
<div style={{
fontSize: 11.5, fontWeight: 700, color: '#171512', fontFamily: 'Sora, sans-serif',
overflow: 'hidden', textOverflow: 'ellipsis', whiteSpace: 'nowrap',
}}>{tx.store}</div>
<div style={{ fontSize: 9, color: '#9ca3af', fontFamily: 'Sora, sans-serif', marginTop: 1 }}>{tx.time}</div>
</div>
<span className="feed-pts" style={{
fontSize: 12, fontWeight: 900, fontFamily: 'Sora, sans-serif',
color: '#16a34a', letterSpacing: '-0.01em',
background: i === 0 ? 'rgba(22,163,74,0.14)' : 'rgba(22,163,74,0.08)',
padding: '3px 8px', borderRadius: 8, whiteSpace: 'nowrap',
transition: 'background 0.35s ease',
}}>
+{tx.pts}
</span>
</div>
))}
</div>
{/* Summary strip */}
<div style={{ margin: '10px 14px 12px', display: 'grid', gridTemplateColumns: '1fr 1fr', gap: 8 }}>
{[
{ label: 'Earned this month', val: '660 LYTs', color: '#16a34a', bg: '#f0fdf4', border: '#16a34a' },
{ label: 'Redeemable value', val: '₹660', color: '#bc7122', bg: '#fff7e0', border: '#f4be28' },
].map((s, i) => (
<div key={i} style={{ padding: '10px 12px', borderRadius: 12, background: s.bg, border: `1.5px solid ${s.border}` }}>
<div style={{ fontSize: 8.5, color: 'rgba(23,21,18,0.5)', fontFamily: 'Sora, sans-serif', marginBottom: 3 }}>{s.label}</div>
<div style={{ fontSize: 14, fontWeight: 900, color: s.color, fontFamily: 'Sora, sans-serif' }}>{s.val}</div>
</div>
))}
</div>
<PhoneBottomNav active="home" />
</PhoneFrame>
</div>
</div>
</div>