nxtgauge-frontend-solid/src/components/PublicLanding.tsx

415 lines
18 KiB
TypeScript
Raw Normal View History

import { A } from '@solidjs/router';
import { createMemo, createSignal, For, onCleanup, onMount, Show } from 'solid-js';
type RoleCard = {
title: string;
description: string;
button: string;
href: string;
image: string;
chip: string;
};
const roleCards: RoleCard[] = [
{
title: 'Post a Job',
description: 'Create verified job openings and find the right talent faster.',
button: 'Start as Company',
href: '/onboarding?schemaId=company_onboarding_v1',
chip: 'Company',
image: 'https://images.unsplash.com/photo-1484480974693-6ca0a78fb36b?q=80&w=800&auto=format&fit=crop',
},
{
title: 'Apply for Jobs',
description: 'Build your profile and apply to approved opportunities quickly.',
button: 'Start as Job Seeker',
href: '/onboarding?schemaId=jobseeker_onboarding_v1',
chip: 'Job Seeker',
image: 'https://images.unsplash.com/photo-1586281380349-632531db7ed4?q=80&w=800&auto=format&fit=crop',
},
{
title: 'Hire a Professional',
description: 'Post your requirement and discover trusted specialists.',
button: 'Start as Customer',
href: '/onboarding?schemaId=customer_onboarding_v1',
chip: 'Customer',
image: 'https://images.unsplash.com/photo-1450101499163-c8848c66ca85?q=80&w=800&auto=format&fit=crop',
},
{
title: 'Join as Developer',
description: 'Build products and grow with verified client demand.',
button: 'Join Developer',
href: '/onboarding?schemaId=professional_onboarding_v1&profession=Developer',
chip: 'Professional',
image: 'https://images.unsplash.com/photo-1498050108023-c5249f4df085?q=80&w=800&auto=format&fit=crop',
},
{
title: 'Join as Photographer',
description: 'Capture events and campaigns with trusted bookings.',
button: 'Join Photographer',
href: '/onboarding?schemaId=professional_onboarding_v1&profession=Photographer',
chip: 'Professional',
image: 'https://images.unsplash.com/photo-1516035069371-29a1b244cc32?q=80&w=800&auto=format&fit=crop',
},
{
title: 'Join as Makeup Artist',
description: 'Offer styling services with profile-based trust signals.',
button: 'Join Makeup Artist',
href: '/onboarding?schemaId=professional_onboarding_v1&profession=Makeup%20Artist',
chip: 'Professional',
image: 'https://images.unsplash.com/photo-1522335789203-aabd1fc54bc9?q=80&w=800&auto=format&fit=crop',
},
{
title: 'Join as Tutor',
description: 'Teach learners and build your reputation with verified profiles.',
button: 'Join Tutor',
href: '/onboarding?schemaId=professional_onboarding_v1&profession=Tutor',
chip: 'Professional',
image: 'https://images.unsplash.com/photo-1497633762265-9d179a990aa6?q=80&w=800&auto=format&fit=crop',
},
{
title: 'Join as Video Editor',
description: 'Create compelling edits and work with quality clients.',
button: 'Join Video Editor',
href: '/onboarding?schemaId=professional_onboarding_v1&profession=Video%20Editor',
chip: 'Professional',
image: 'https://images.unsplash.com/photo-1574717024653-61fd2cf4d44d?q=80&w=800&auto=format&fit=crop',
},
{
title: 'Join as Graphic Designer',
description: 'Design brand-ready visuals and collaborate with growing businesses.',
button: 'Join Graphic Designer',
href: '/onboarding?schemaId=professional_onboarding_v1&profession=Graphic%20Designer',
chip: 'Professional',
image: 'https://images.unsplash.com/photo-1558655146-d09347e92766?q=80&w=800&auto=format&fit=crop',
},
{
title: 'Join as Social Media Manager',
description: 'Plan campaigns and scale audience growth for clients.',
button: 'Join Social Manager',
href: '/onboarding?schemaId=professional_onboarding_v1&profession=Social%20Media%20Manager',
chip: 'Professional',
image: 'https://images.unsplash.com/photo-1611162618071-b39a2ec055fb?q=80&w=800&auto=format&fit=crop',
},
{
title: 'Join as Fitness Trainer',
description: 'Coach clients with structured plans and trusted profiles.',
button: 'Join Trainer',
href: '/onboarding?schemaId=professional_onboarding_v1&profession=Fitness%20Trainer',
chip: 'Professional',
image: 'https://images.unsplash.com/photo-1517836357463-d25dfeac3438?q=80&w=800&auto=format&fit=crop',
},
{
title: 'Join as Catering Services',
description: 'Showcase event-ready menus to customers and companies.',
button: 'Join Catering',
href: '/onboarding?schemaId=professional_onboarding_v1&profession=Catering%20Services',
chip: 'Professional',
image: 'https://images.unsplash.com/photo-1555244162-803834f70033?q=80&w=800&auto=format&fit=crop',
},
];
const benefits = [
{ title: 'Verified profiles & businesses', body: 'Identity and profile checks reduce fake submissions and spam.' },
{ title: 'Approval-based quality (24-48 hours)', body: 'Profiles, requirements, and jobs are reviewed before visibility.' },
{ title: 'Smart matching using tags/skills', body: 'Tag-based relevance helps surface better opportunities faster.' },
{ title: 'Focused discovery with filters', body: 'Search and filter tools keep opportunity discovery focused.' },
{ title: 'Controlled contact visibility', body: 'Sensitive contact flow remains controlled by role and workflow.' },
{ title: 'Notifications & updates', body: 'Track approvals, responses, applications, and key updates.' },
];
const flows = [
{
label: 'Customers',
title: 'Need to solution, with verified trust in the middle',
description: 'Post your requirement, pass quality checks, and receive focused responses.',
image: 'https://images.unsplash.com/photo-1454165804606-c3d57bc86b40?q=80&w=1200&auto=format&fit=crop',
steps: [
{ title: 'Create account', description: 'Sign up quickly with customer intent.' },
{ title: 'Share requirement', description: 'Add budget, scope, and timing.' },
{ title: 'Review and verify', description: 'Quality checks run before visibility.' },
{ title: 'Track responses', description: 'Monitor replies and status updates.' },
],
},
{
label: 'Professionals',
title: 'Profile first, opportunity next',
description: 'Build profile quality once, then receive better-fit lead discovery.',
image: 'https://images.unsplash.com/photo-1461749280684-dccba630e2f6?q=80&w=1200&auto=format&fit=crop',
steps: [
{ title: 'Pick role and skills', description: 'Choose service category and specialization.' },
{ title: 'Build profile', description: 'Add portfolio, strengths, and proof.' },
{ title: 'Pass verification', description: 'Approval protects platform trust.' },
{ title: 'Respond to opportunities', description: 'Manage matching leads in one flow.' },
],
},
{
label: 'Companies',
title: 'Hiring workflows without chaos',
description: 'Publish requirements, keep quality high, and track applicants clearly.',
image: 'https://images.unsplash.com/photo-1486406146926-c627a92ad1ab?q=80&w=1200&auto=format&fit=crop',
steps: [
{ title: 'Create company profile', description: 'Set hiring context and org details.' },
{ title: 'Post requirements', description: 'Publish role details and expectations.' },
{ title: 'Approval before publish', description: 'Listings are reviewed first.' },
{ title: 'Manage pipeline', description: 'Track candidates and responses.' },
],
},
{
label: 'Job Seekers',
title: 'Onboard once, apply with confidence',
description: 'Get visible only after approval, then discover jobs with targeted filters.',
image: 'https://images.unsplash.com/photo-1450101499163-c8848c66ca85?q=80&w=1200&auto=format&fit=crop',
steps: [
{ title: 'Set up profile', description: 'Complete essentials and work preferences.' },
{ title: 'Approval check', description: 'Review keeps quality consistent.' },
{ title: 'Explore matching jobs', description: 'Filter by practical criteria.' },
{ title: 'Apply and track', description: 'Submit applications and watch status.' },
],
},
];
const faqs = [
{
q: 'What is Nxtgauge?',
a: 'Nxtgauge connects customers, professionals, companies, and job seekers in one trusted platform.',
},
{
q: 'Who can join Nxtgauge?',
a: 'Customers, service professionals, companies, and job seekers can create an account and choose their path.',
},
{
q: 'Why does Nxtgauge require verification?',
a: 'Verification helps reduce fake profiles and improves trust across the platform.',
},
{
q: 'How long does account approval take?',
a: 'Most profile approvals are completed within 24-48 hours.',
},
{
q: 'Do I need to choose my role during signup?',
a: 'No. You can sign up once and continue with the role flow that fits you best.',
},
];
export default function PublicLanding() {
const [scrolled, setScrolled] = createSignal(false);
const [mobileOpen, setMobileOpen] = createSignal(false);
const [filter, setFilter] = createSignal<'all' | 'customer' | 'professional' | 'company' | 'jobseeker'>('all');
const [flowIndex, setFlowIndex] = createSignal(0);
const [stepIndex, setStepIndex] = createSignal(0);
const [openFaq, setOpenFaq] = createSignal(0);
onMount(() => {
const onScroll = () => setScrolled(window.scrollY > 10);
onScroll();
window.addEventListener('scroll', onScroll, { passive: true });
const timer = window.setInterval(() => {
setStepIndex((prev) => {
const active = flows[flowIndex()];
if (prev + 1 < active.steps.length) return prev + 1;
setFlowIndex((f) => (f + 1) % flows.length);
return 0;
});
}, 3200);
onCleanup(() => {
window.removeEventListener('scroll', onScroll);
window.clearInterval(timer);
});
});
const filteredCards = createMemo(() => {
const active = filter();
if (active === 'all') return roleCards;
if (active === 'customer') return roleCards.filter((x) => x.chip === 'Customer');
if (active === 'professional') return roleCards.filter((x) => x.chip === 'Professional');
if (active === 'company') return roleCards.filter((x) => x.chip === 'Company');
return roleCards.filter((x) => x.chip === 'Job Seeker');
});
return (
<main class="public-main">
<header class={`public-header ${scrolled() ? 'public-header-scrolled' : ''}`}>
<div class="container nav-row">
<A href="/"><img class="brand-logo" src="/nxtgauge-logo.png" alt="NXTGAUGE" /></A>
<nav class="nav-links desktop-only">
<A href="/">Home</A>
<A href="/about">About Us</A>
<A href="/contact">Contact Us</A>
</nav>
<div class="nav-actions desktop-only">
<A class="btn" href="/onboarding?schemaId=professional_onboarding_v1">Login</A>
<A class="btn primary" href="/onboarding?schemaId=customer_onboarding_v1">Sign Up</A>
</div>
<button class="btn mobile-menu" onClick={() => setMobileOpen(!mobileOpen())}>Menu</button>
</div>
<Show when={mobileOpen()}>
<div class="mobile-nav container">
<A href="/" onClick={() => setMobileOpen(false)}>Home</A>
<A href="/about" onClick={() => setMobileOpen(false)}>About Us</A>
<A href="/contact" onClick={() => setMobileOpen(false)}>Contact Us</A>
</div>
</Show>
</header>
<section class="public-hero scene-dark">
<div class="container hero-grid-2">
<div>
<h1 class="hero-title">Hire verified professionals. Post jobs. Get approvals in 24-48 hours.</h1>
<p class="hero-copy">Nxtgauge connects customers, companies, job seekers, and professionals through a trusted approval workflow.</p>
<div class="hero-actions">
<A class="btn primary" href="/onboarding?schemaId=customer_onboarding_v1">Hire a Professional</A>
<A class="btn ghost-dark" href="/onboarding?schemaId=jobseeker_onboarding_v1">Apply for Jobs</A>
</div>
</div>
<div class="hero-stack">
<article class="float-card">
<h3>Customers</h3>
<p>Post requirements with clear intent and receive verified responses.</p>
</article>
<article class="float-card">
<h3>Professionals</h3>
<p>Complete onboarding and verification, then discover relevant leads.</p>
</article>
<article class="float-card">
<h3>Companies</h3>
<p>Create approved job listings and track applications in one workflow.</p>
</article>
<article class="float-card">
<h3>Job Seekers</h3>
<p>Build profile, clear approvals, apply and track opportunities.</p>
</article>
</div>
</div>
</section>
<section class="public-section scene-dark">
<div class="container panel">
<div class="section-head">
<div>
<h2>Choose Your Path</h2>
<p>One account, multiple journeys. Pick your goal and get started.</p>
</div>
<div class="filter-row">
<button class={`chip-btn ${filter() === 'all' ? 'active' : ''}`} onClick={() => setFilter('all')}>All Paths</button>
<button class={`chip-btn ${filter() === 'customer' ? 'active' : ''}`} onClick={() => setFilter('customer')}>Customers</button>
<button class={`chip-btn ${filter() === 'professional' ? 'active' : ''}`} onClick={() => setFilter('professional')}>Professionals</button>
<button class={`chip-btn ${filter() === 'company' ? 'active' : ''}`} onClick={() => setFilter('company')}>Companies</button>
<button class={`chip-btn ${filter() === 'jobseeker' ? 'active' : ''}`} onClick={() => setFilter('jobseeker')}>Job Seekers</button>
</div>
</div>
<div class="path-grid">
<For each={filteredCards()}>
{(card) => (
<article class="path-card">
<img src={card.image} alt={card.title} />
<div class="path-body">
<span class="role-badge">{card.chip}</span>
<h3>{card.title}</h3>
<p>{card.description}</p>
<A class="btn primary" href={card.href}>{card.button}</A>
</div>
</article>
)}
</For>
</div>
</div>
</section>
<section class="public-section scene-dark">
<div class="container panel panel-dark">
<h2 class="center">Why Nxtgauge</h2>
<p class="center sub">Trust, approvals, and better matching in one flow.</p>
<div class="benefit-grid">
<For each={benefits}>{(item) => <article class="benefit-card"><h3>{item.title}</h3><p>{item.body}</p></article>}</For>
</div>
</div>
</section>
<section class="public-section scene-light">
<div class="container panel panel-light">
<h2 class="center">How It Works</h2>
<p class="center sub">Clear journey, zero confusion.</p>
<article class="flow-card">
<img src={flows[flowIndex()].image} alt={flows[flowIndex()].label} />
<div>
<p class="eyebrow">{flows[flowIndex()].label}</p>
<h3>{flows[flowIndex()].title}</h3>
<p class="sub">{flows[flowIndex()].description}</p>
<div class="step-list">
<For each={flows[flowIndex()].steps}>
{(step, idx) => (
<div class={`step-item ${idx() === stepIndex() ? 'active' : ''}`}>
<span>{idx() + 1}</span>
<div>
<h4>{step.title}</h4>
<p>{step.description}</p>
</div>
</div>
)}
</For>
</div>
<div class="actions">
<button class="btn" onClick={() => { setFlowIndex((flowIndex() - 1 + flows.length) % flows.length); setStepIndex(0); }}>&larr;</button>
<button class="btn" onClick={() => { setFlowIndex((flowIndex() + 1) % flows.length); setStepIndex(0); }}>&rarr;</button>
</div>
</div>
</article>
</div>
</section>
<section class="public-section scene-dark">
<div class="container panel panel-dark faq-wrap">
<h2 class="center">Frequently asked questions</h2>
<p class="center sub">Quick answers before you create your account.</p>
<div class="faq-list">
<For each={faqs}>
{(item, idx) => (
<article class={`faq-item ${openFaq() === idx() ? 'open' : ''}`}>
<button class="faq-q" onClick={() => setOpenFaq(openFaq() === idx() ? -1 : idx())}>
<span>{item.q}</span>
<span>{openFaq() === idx() ? '-' : '+'}</span>
</button>
<Show when={openFaq() === idx()}><p class="faq-a">{item.a}</p></Show>
</article>
)}
</For>
</div>
</div>
</section>
<section class="public-section scene-dark">
<div class="container panel panel-dark cta-row">
<div>
<p class="eyebrow">Quick Actions</p>
<h2>Ready to get started?</h2>
<p class="sub">Pick your next action and continue with the correct role flow.</p>
</div>
<div class="hero-actions">
<A class="btn primary" href="/onboarding?schemaId=customer_onboarding_v1">Hire a Professional</A>
<A class="btn ghost-dark" href="/onboarding?schemaId=jobseeker_onboarding_v1">Apply for Jobs</A>
<A class="btn ghost-dark" href="/onboarding?schemaId=company_onboarding_v1">Post a Job</A>
</div>
</div>
</section>
<footer class="public-footer">
<div class="container footer-row">
<img class="brand-logo" src="/nxtgauge-logo.png" alt="NXTGAUGE" />
<p>© {new Date().getFullYear()} Nxtgauge. All rights reserved.</p>
<div class="footer-links">
<A href="/about">About Us</A>
<A href="/contact">Contact Us</A>
</div>
</div>
</footer>
</main>
);
}