415 lines
18 KiB
TypeScript
415 lines
18 KiB
TypeScript
|
|
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); }}>←</button>
|
||
|
|
<button class="btn" onClick={() => { setFlowIndex((flowIndex() + 1) % flows.length); setStepIndex(0); }}>→</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>
|
||
|
|
);
|
||
|
|
}
|