repositories
loading repo index
repositories
loading repo index
repository
loading code, commits, and activity
Pan-African Youth Internship,…
stars
latest
clone command
git clone gitlawb://did:key:z6MkmNFz...XP9B/pan-african-you...git clone gitlawb://did:key:z6MkmNFz.../pan-african-you...53f59357sync from playground21m ago| #1 | import { useState, useEffect, useRef, type ReactNode } from "react"; |
| #2 | import RegistrationPage from "./RegistrationPage"; |
| #3 | import OrganisationRegistrationPage from "./OrganisationRegistrationPage"; |
| #4 | import OrganisationDashboard from "./OrganisationDashboard"; |
| #5 | import LoginPage from "./LoginPage"; |
| #6 | import YouthDashboard from "./YouthDashboard"; |
| #7 | import AdminDashboard from "./AdminDashboard"; |
| #8 | import { supabase } from "./supabaseClient"; |
| #9 | |
| #10 | const DASHBOARD_PAGES = ["youth-dashboard", "org-dashboard", "admin-dashboard"]; |
| #11 | |
| #12 | function PageTransition({ children, pageKey }: { children: ReactNode; pageKey: string }) { |
| #13 | const [animState, setAnimState] = useState<"entering" | "idle">("entering"); |
| #14 | const prevKey = useRef(pageKey); |
| #15 | const isDashboard = DASHBOARD_PAGES.includes(pageKey); |
| #16 | |
| #17 | useEffect(() => { |
| #18 | if (prevKey.current !== pageKey) { |
| #19 | prevKey.current = pageKey; |
| #20 | if (isDashboard) { |
| #21 | setAnimState("idle"); |
| #22 | } else { |
| #23 | setAnimState("entering"); |
| #24 | const timer = setTimeout(() => setAnimState("idle"), 550); |
| #25 | return () => clearTimeout(timer); |
| #26 | } |
| #27 | } |
| #28 | }, [pageKey, isDashboard]); |
| #29 | |
| #30 | return ( |
| #31 | <div className={animState === "entering" && !isDashboard ? "page-transition-enter" : ""} key={pageKey}> |
| #32 | {children} |
| #33 | </div> |
| #34 | ); |
| #35 | } |
| #36 | |
| #37 | const NAV_LINKS = [ |
| #38 | { label: "Features", href: "#features" }, |
| #39 | { label: "How It Works", href: "#how-it-works" }, |
| #40 | { label: "For Youth", href: "#for-youth" }, |
| #41 | { label: "For Organisations", href: "#for-orgs" }, |
| #42 | { label: "Partners", href: "#partners" }, |
| #43 | ]; |
| #44 | |
| #45 | const YOUTH_FEATURES = [ |
| #46 | { |
| #47 | icon: ( |
| #48 | <svg viewBox="0 0 24 24"><path d="M20 21v-2a4 4 0 0 0-4-4H8a4 4 0 0 0-4 4v2" /><circle cx="12" cy="7" r="4" /></svg> |
| #49 | ), |
| #50 | title: "Personal Profiles & Portfolios", |
| #51 | desc: "Create a digital profile showcasing your skills, qualifications, and experience to stand out to employers.", |
| #52 | }, |
| #53 | { |
| #54 | icon: ( |
| #55 | <svg viewBox="0 0 24 24"><path d="M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z" /><polyline points="14 2 14 8 20 8" /><line x1="16" y1="13" x2="8" y2="13" /><line x1="16" y1="17" x2="8" y2="17" /><polyline points="10 9 9 9 8 9" /></svg> |
| #56 | ), |
| #57 | title: "CV Upload & Management", |
| #58 | desc: "Upload and manage your CV directly on the platform for quick applications.", |
| #59 | }, |
| #60 | { |
| #61 | icon: ( |
| #62 | <svg viewBox="0 0 24 24"><circle cx="11" cy="11" r="8" /><line x1="21" y1="21" x2="16.65" y2="16.65" /></svg> |
| #63 | ), |
| #64 | title: "Smart Opportunity Search", |
| #65 | desc: "Filter by country, field, paid/unpaid, duration, remote/on-site, and sector.", |
| #66 | }, |
| #67 | { |
| #68 | icon: ( |
| #69 | <svg viewBox="0 0 24 24"><polygon points="13 2 3 14 12 14 11 22 21 10 12 10 13 2" /></svg> |
| #70 | ), |
| #71 | title: "One-Click Applications", |
| #72 | desc: "Apply to opportunities instantly with a single click using your stored profile.", |
| #73 | }, |
| #74 | { |
| #75 | icon: ( |
| #76 | <svg viewBox="0 0 24 24"><line x1="18" y1="20" x2="18" y2="10" /><line x1="12" y1="20" x2="12" y2="4" /><line x1="6" y1="20" x2="6" y2="14" /></svg> |
| #77 | ), |
| #78 | title: "Application Tracking", |
| #79 | desc: "Monitor the status of all your applications in one dashboard.", |
| #80 | }, |
| #81 | { |
| #82 | icon: ( |
| #83 | <svg viewBox="0 0 24 24"><path d="M18 8A6 6 0 0 0 6 8c0 7-3 9-3 9h18s-3-2-3-9" /><path d="M13.73 21a2 2 0 0 1-3.46 0" /></svg> |
| #84 | ), |
| #85 | title: "Built-in Notifications", |
| #86 | desc: "Get notified about the status of your application inside your profile.", |
| #87 | }, |
| #88 | ]; |
| #89 | |
| #90 | const ORG_FEATURES = [ |
| #91 | { |
| #92 | icon: ( |
| #93 | <svg viewBox="0 0 24 24"><rect x="3" y="3" width="18" height="18" rx="2" ry="2" /><line x1="9" y1="3" x2="9" y2="21" /></svg> |
| #94 | ), |
| #95 | title: "Free Opportunity Posting", |
| #96 | desc: "Post internships, volunteering roles, and field placements with a simple, guided workflow.", |
| #97 | }, |
| #98 | { |
| #99 | icon: ( |
| #100 | <svg viewBox="0 0 24 24"><path d="M17 21v-2a4 4 0 0 0-4-4H5a4 4 0 0 0-4 4v2" /><circle cx="9" cy="7" r="4" /><path d="M23 21v-2a4 4 0 0 0-3-3.87" /><path d="M16 3.13a4 4 0 0 1 0 7.75" /></svg> |
| #101 | ), |
| #102 | title: "Applicant Management", |
| #103 | desc: "Review, shortlist, and manage applicants efficiently from a centralised dashboard.", |
| #104 | }, |
| #105 | { |
| #106 | icon: ( |
| #107 | <svg viewBox="0 0 24 24"><path d="M12 22s8-4 8-10V5l-8-3-8 3v7c0 6 8 10 8 10z" /><polyline points="9 12 11 14 15 10" /></svg> |
| #108 | ), |
| #109 | title: "Organisation Verification", |
| #110 | desc: "Build trust with a verified badge that shows your organisation is legitimate and trustworthy.", |
| #111 | }, |
| #112 | { |
| #113 | icon: ( |
| #114 | <svg viewBox="0 0 24 24"><circle cx="11" cy="11" r="8" /><line x1="21" y1="21" x2="16.65" y2="16.65" /><line x1="11" y1="8" x2="11" y2="14" /><line x1="8" y1="11" x2="14" y2="11" /></svg> |
| #115 | ), |
| #116 | title: "Talent Search", |
| #117 | desc: "Search and discover qualified youth based on skills, location, and qualifications.", |
| #118 | }, |
| #119 | ]; |
| #120 | |
| #121 | const PLATFORM_FEATURES = [ |
| #122 | { |
| #123 | icon: ( |
| #124 | <svg viewBox="0 0 24 24"><path d="M22 12h-4l-3 9L9 3l-3 9H2" /></svg> |
| #125 | ), |
| #126 | title: "Supporting School-to-Work Transitions", |
| #127 | desc: "Helping students and graduates move from academic learning into practical work environments through real-world experience and exposure.", |
| #128 | }, |
| #129 | { |
| #130 | icon: ( |
| #131 | <svg viewBox="0 0 24 24"><rect x="2" y="7" width="20" height="14" rx="2" ry="2" /><path d="M16 21V5a2 2 0 0 0-2-2h-4a2 2 0 0 0-2 2v16" /></svg> |
| #132 | ), |
| #133 | title: "Building Employability & Professional Skills", |
| #134 | desc: "Enabling youth to strengthen workplace readiness through hands-on experience, skill development, and professional engagement opportunities.", |
| #135 | }, |
| #136 | { |
| #137 | icon: ( |
| #138 | <svg viewBox="0 0 24 24"><path d="M17 21v-2a4 4 0 0 0-4-4H5a4 4 0 0 0-4 4v2" /><circle cx="9" cy="7" r="4" /><path d="M23 21v-2a4 4 0 0 0-3-3.87" /><path d="M16 3.13a4 4 0 0 1 0 7.75" /></svg> |
| #139 | ), |
| #140 | title: "Connecting Youth with Employers", |
| #141 | desc: "Helping organisations discover motivated young talent while giving youth direct access to internships, volunteering, fieldwork, and graduate opportunities.", |
| #142 | }, |
| #143 | { |
| #144 | icon: ( |
| #145 | <svg viewBox="0 0 24 24"><circle cx="12" cy="12" r="10" /><line x1="2" y1="12" x2="22" y2="12" /><path d="M12 2a15.3 15.3 0 0 1 4 10 15.3 15.3 0 0 1-4 10 15.3 15.3 0 0 1-4-10 15.3 15.3 0 0 1 4-10z" /></svg> |
| #146 | ), |
| #147 | title: "Creating a Trusted Opportunity Ecosystem", |
| #148 | desc: "Providing verified opportunities and trusted organisational partnerships to reduce fraud, misinformation, and exploitative recruitment practices.", |
| #149 | }, |
| #150 | ]; |
| #151 | |
| #152 | const STEPS = [ |
| #153 | { |
| #154 | num: "01", |
| #155 | title: "Create Your Profile", |
| #156 | desc: "Sign up and build your digital profile with your skills, qualifications, and experience.", |
| #157 | }, |
| #158 | { |
| #159 | num: "02", |
| #160 | title: "Discover Opportunities", |
| #161 | desc: "Search and filter internships, volunteering, and field placements across Africa.", |
| #162 | }, |
| #163 | { |
| #164 | num: "03", |
| #165 | title: "Apply & Track", |
| #166 | desc: "Apply with one click and track your application status in real time.", |
| #167 | }, |
| #168 | { |
| #169 | num: "04", |
| #170 | title: "Gain Experience", |
| #171 | desc: "Secure placements, build your career, and grow your professional network.", |
| #172 | }, |
| #173 | ]; |
| #174 | |
| #175 | export default function App() { |
| #176 | const [mobileMenuOpen, setMobileMenuOpen] = useState(false); |
| #177 | const logoClickCount = useRef(0); |
| #178 | const logoClickTimer = useRef<ReturnType<typeof setTimeout> | null>(null); |
| #179 | const [page, setPage] = useState<"home" | "register" | "org-register" | "org-dashboard" | "login" | "admin-login" | "youth-dashboard" | "admin-dashboard" | "privacy" | "terms" | "cookies">("home"); |
| #180 | const [authUserId, setAuthUserId] = useState<string | null>(null); |
| #181 | const [stats, setStats] = useState([ |
| #182 | { value: "...", label: "Youth Registered" }, |
| #183 | { value: "...", label: "Opportunities Listed" }, |
| #184 | { value: "...", label: "Registered Institutions" }, |
| #185 | ]); |
| #186 | const [statsLoading, setStatsLoading] = useState(true); |
| #187 | |
| #188 | // Fetch live stats from Supabase |
| #189 | useEffect(() => { |
| #190 | async function fetchStats() { |
| #191 | try { |
| #192 | const [youthCount, orgCount, oppsCount] = await Promise.all([ |
| #193 | supabase.from('youth_profiles').select('*', { count: 'exact', head: true }), |
| #194 | supabase.from('organisation_profiles').select('*', { count: 'exact', head: true }), |
| #195 | supabase.from('opportunities').select('*', { count: 'exact', head: true }), |
| #196 | ]); |
| #197 | |
| #198 | setStats([ |
| #199 | { value: String(youthCount.count || 0), label: "Youth Registered" }, |
| #200 | { value: String(oppsCount.count || 0), label: "Opportunities Listed" }, |
| #201 | { value: String(orgCount.count || 0), label: "Registered Institutions" }, |
| #202 | ]); |
| #203 | } catch (err) { |
| #204 | console.error("Failed to fetch stats:", err); |
| #205 | } finally { |
| #206 | setStatsLoading(false); |
| #207 | } |
| #208 | } |
| #209 | |
| #210 | fetchStats(); |
| #211 | }, []); |
| #212 | |
| #213 | // Check URL path for /admin on mount, and ?page= query param |
| #214 | useEffect(() => { |
| #215 | if (window.location.pathname === "/admin") { |
| #216 | setPage("admin-login"); |
| #217 | } |
| #218 | const params = new URLSearchParams(window.location.search); |
| #219 | const pageParam = params.get("page"); |
| #220 | if (pageParam === "terms" || pageParam === "privacy" || pageParam === "cookies") { |
| #221 | setPage(pageParam as "terms" | "privacy" | "cookies"); |
| #222 | } |
| #223 | }, []); |
| #224 | |
| #225 | // Check for existing session on mount and restore page |
| #226 | useEffect(() => { |
| #227 | async function restoreSession() { |
| #228 | const { data: { session } } = await supabase.auth.getSession(); |
| #229 | |
| #230 | if (!session?.user?.id) { |
| #231 | if (window.location.pathname === "/admin") { |
| #232 | setPage("admin-login"); |
| #233 | } |
| #234 | setPage("home"); |
| #235 | return; |
| #236 | } |
| #237 | |
| #238 | const savedType = sessionStorage.getItem("fursalink_user_type"); |
| #239 | const savedUserId = sessionStorage.getItem("fursalink_user_id"); |
| #240 | setAuthUserId(session.user.id); |
| #241 | |
| #242 | // Use saved type if it matches current session user |
| #243 | if (savedUserId === session.user.id && savedType) { |
| #244 | if (savedType === "admin") setPage("admin-dashboard"); |
| #245 | else if (savedType === "youth") setPage("youth-dashboard"); |
| #246 | else if (savedType === "organisation") setPage("org-dashboard"); |
| #247 | return; |
| #248 | } |
| #249 | |
| #250 | // Fallback: check profile tables |
| #251 | const [youthCheck, orgCheck, adminCheck] = await Promise.all([ |
| #252 | supabase.from("youth_profiles").select("user_id").eq("user_id", session.user.id).maybeSingle(), |
| #253 | supabase.from("organisation_profiles").select("user_id").eq("user_id", session.user.id).maybeSingle(), |
| #254 | supabase.from("admin_users").select("user_id").eq("user_id", session.user.id).maybeSingle(), |
| #255 | ]); |
| #256 | |
| #257 | if (adminCheck.data) { |
| #258 | sessionStorage.setItem("fursalink_user_type", "admin"); |
| #259 | setPage("admin-dashboard"); |
| #260 | } else if (youthCheck.data) { |
| #261 | sessionStorage.setItem("fursalink_user_type", "youth"); |
| #262 | setPage("youth-dashboard"); |
| #263 | } else if (orgCheck.data) { |
| #264 | sessionStorage.setItem("fursalink_user_type", "organisation"); |
| #265 | setPage("org-dashboard"); |
| #266 | } |
| #267 | } |
| #268 | |
| #269 | restoreSession(); |
| #270 | |
| #271 | const { data: { subscription } } = supabase.auth.onAuthStateChange((_event, session) => { |
| #272 | if (session?.user?.id) { |
| #273 | // Only update if this is the same user this tab logged in as |
| #274 | const savedId = sessionStorage.getItem("fursalink_user_id"); |
| #275 | if (savedId === session.user.id) { |
| #276 | setAuthUserId(session.user.id); |
| #277 | } |
| #278 | } else { |
| #279 | setAuthUserId(null); |
| #280 | sessionStorage.removeItem("fursalink_user_type"); |
| #281 | sessionStorage.removeItem("fursalink_user_id"); |
| #282 | setPage("home"); |
| #283 | } |
| #284 | }); |
| #285 | |
| #286 | return () => subscription.unsubscribe(); |
| #287 | }, []); |
| #288 | |
| #289 | const handleSignOut = async () => { |
| #290 | await supabase.auth.signOut(); |
| #291 | sessionStorage.removeItem("fursalink_user_type"); |
| #292 | sessionStorage.removeItem("fursalink_user_id"); |
| #293 | setAuthUserId(null); |
| #294 | setPage("home"); |
| #295 | }; |
| #296 | |
| #297 | return ( |
| #298 | <> |
| #299 | {/* Navigation */} |
| #300 | {page === "home" && ( |
| #301 | <nav className="nav"> |
| #302 | <div className="nav-inner"> |
| #303 | <a href="#" className="logo" onClick={(e) => { |
| #304 | e.preventDefault(); |
| #305 | logoClickCount.current += 1; |
| #306 | if (logoClickTimer.current) clearTimeout(logoClickTimer.current); |
| #307 | if (logoClickCount.current >= 5) { |
| #308 | logoClickCount.current = 0; |
| #309 | setPage("admin-login"); |
| #310 | return; |
| #311 | } |
| #312 | logoClickTimer.current = setTimeout(() => { |
| #313 | logoClickCount.current = 0; |
| #314 | setPage("home"); |
| #315 | }, 1500); |
| #316 | }}> |
| #317 | <span className="logo-icon"><img src="https://i.imgur.com/FT8aHGw.png" alt="FursaLink" /></span> |
| #318 | <span className="logo-text"> |
| #319 | Fursa<span className="logo-highlight">Link</span> |
| #320 | </span> |
| #321 | </a> |
| #322 | <div className="nav-links"> |
| #323 | {NAV_LINKS.map((link) => ( |
| #324 | <a key={link.href} href={link.href} className="nav-link"> |
| #325 | {link.label} |
| #326 | </a> |
| #327 | ))} |
| #328 | </div> |
| #329 | <div className="nav-actions"> |
| #330 | <button type="button" className="btn btn-outline btn-sm" onClick={() => setPage("login")}>Log In</button> |
| #331 | <button type="button" className="btn btn-primary btn-sm" onClick={() => setPage("register")}>Get Started</button> |
| #332 | </div> |
| #333 | <button |
| #334 | className="mobile-menu-btn" |
| #335 | onClick={() => setMobileMenuOpen(!mobileMenuOpen)} |
| #336 | aria-label="Toggle menu" |
| #337 | > |
| #338 | {mobileMenuOpen ? "✕" : "☰"} |
| #339 | </button> |
| #340 | </div> |
| #341 | {mobileMenuOpen && ( |
| #342 | <div className="mobile-menu"> |
| #343 | {NAV_LINKS.map((link) => ( |
| #344 | <a |
| #345 | key={link.href} |
| #346 | href={link.href} |
| #347 | className="mobile-menu-link" |
| #348 | onClick={() => setMobileMenuOpen(false)} |
| #349 | > |
| #350 | {link.label} |
| #351 | </a> |
| #352 | ))} |
| #353 | <div className="mobile-menu-actions"> |
| #354 | <button type="button" className="btn btn-outline" onClick={() => { setMobileMenuOpen(false); setPage("login"); }}>Log In</button> |
| #355 | <button type="button" className="btn btn-primary" onClick={() => { setMobileMenuOpen(false); setPage("register"); }}>Get Started</button> |
| #356 | </div> |
| #357 | </div> |
| #358 | )} |
| #359 | </nav> |
| #360 | )} |
| #361 | |
| #362 | {page === "register" && ( |
| #363 | <PageTransition pageKey="register"> |
| #364 | <RegistrationPage onBack={() => setPage("home")} /> |
| #365 | </PageTransition> |
| #366 | )} |
| #367 | |
| #368 | {page === "org-register" && ( |
| #369 | <PageTransition pageKey="org-register"> |
| #370 | <OrganisationRegistrationPage |
| #371 | onBack={() => setPage("home")} |
| #372 | onComplete={() => setPage("org-dashboard")} |
| #373 | /> |
| #374 | </PageTransition> |
| #375 | )} |
| #376 | |
| #377 | {page === "login" && ( |
| #378 | <PageTransition pageKey="login"> |
| #379 | <LoginPage |
| #380 | onBack={() => setPage("home")} |
| #381 | onYouthLogin={(userId) => { setAuthUserId(userId); setPage("youth-dashboard"); }} |
| #382 | onOrgLogin={(userId) => { setAuthUserId(userId); setPage("org-dashboard"); }} |
| #383 | onAdminLogin={(userId) => { setAuthUserId(userId); setPage("admin-dashboard"); }} |
| #384 | onYouthRegister={() => setPage("register")} |
| #385 | onOrgRegister={() => setPage("org-register")} |
| #386 | /> |
| #387 | </PageTransition> |
| #388 | )} |
| #389 | |
| #390 | {page === "admin-login" && ( |
| #391 | <PageTransition pageKey="admin-login"> |
| #392 | <LoginPage |
| #393 | onBack={() => setPage("home")} |
| #394 | onYouthLogin={() => {}} |
| #395 | onOrgLogin={() => {}} |
| #396 | onAdminLogin={(userId) => { setAuthUserId(userId); setPage("admin-dashboard"); }} |
| #397 | onYouthRegister={() => {}} |
| #398 | onOrgRegister={() => {}} |
| #399 | adminOnly |
| #400 | /> |
| #401 | </PageTransition> |
| #402 | )} |
| #403 | |
| #404 | {page === "youth-dashboard" && ( |
| #405 | <PageTransition pageKey="youth-dashboard"> |
| #406 | <YouthDashboard userId={authUserId} onBack={handleSignOut} /> |
| #407 | </PageTransition> |
| #408 | )} |
| #409 | |
| #410 | {page === "org-dashboard" && ( |
| #411 | <PageTransition pageKey="org-dashboard"> |
| #412 | <OrganisationDashboard userId={authUserId} onBack={handleSignOut} /> |
| #413 | </PageTransition> |
| #414 | )} |
| #415 | |
| #416 | {page === "admin-dashboard" && ( |
| #417 | <PageTransition pageKey="admin-dashboard"> |
| #418 | <AdminDashboard userId={authUserId} onBack={handleSignOut} /> |
| #419 | </PageTransition> |
| #420 | )} |
| #421 | |
| #422 | {page === "privacy" && ( |
| #423 | <PageTransition pageKey="privacy"> |
| #424 | <div style={{ minHeight: "100vh", background: "#fff" }}> |
| #425 | <nav className="nav"> |
| #426 | <div className="nav-inner"> |
| #427 | <a href="#" className="logo" onClick={(e) => { e.preventDefault(); setPage("home"); }}> |
| #428 | <span className="logo-icon"><img src="https://i.imgur.com/FT8aHGw.png" alt="FursaLink" /></span> |
| #429 | <span className="logo-text">Fursa<span className="logo-highlight">Link</span></span> |
| #430 | </a> |
| #431 | <button type="button" className="btn btn-outline btn-sm" onClick={() => setPage("home")}>Back to Home</button> |
| #432 | </div> |
| #433 | </nav> |
| #434 | <div style={{ maxWidth: "800px", margin: "0 auto", padding: "6rem 1.5rem 3rem" }}> |
| #435 | <h1 style={{ fontSize: "2rem", fontWeight: 800, marginBottom: "0.5rem" }}>FURSALINK AFRICA — PRIVACY POLICY</h1> |
| #436 | <p style={{ color: "#6b7280", marginBottom: "2rem" }}>Last updated: June 2026</p> |
| #437 | <p style={{ marginBottom: "1.5rem", lineHeight: 1.7 }}>We respect your privacy and are committed to protecting your personal information. This Privacy Policy applies to your use of the FursaLink Africa platform ("Platform") accessible at fursalinkafrica.com and related mobile applications. This Policy sets out how we collect, store, protect, share and use any personal data we may collect from you when you use or interact with the Platform.</p> |
| #438 | |
| #439 | {[ |
| #440 | { title: "1. About FursaLink Africa", body: "FursaLink Africa Limited is the data controller responsible for your personal data (referred to as \"we\", \"us\" or \"our\" in this Policy). If you have any questions about this Policy please contact us at:\n\nEmail: privacy@fursalinkafrica.com\nWhatsApp: +255 758 205 593" }, |
| #441 | { title: "2. Who This Policy Applies To", body: "This Policy applies to:\n\n• Youth users — students and graduates using the Platform to find opportunities\n• Organisation users — companies, NGOs, government bodies and institutions posting opportunities\n• Visitors — anyone browsing the Platform without an account\n\nThis Platform is not intended for children under 18 years of age and we do not knowingly collect data relating to children." }, |
| #442 | { title: "3. Terms", body: "For ease of reference:\n\n• Account means the account you create when registering on the Platform\n• Personal data means information relating to you that can identify you as an individual\n• Platform means the FursaLink Africa website and related applications\n• Services means services made available through the Platform\n• Youth User means a student or graduate registered on the Platform seeking opportunities\n• Organisation User means a company, NGO, institution or employer registered to post opportunities" }, |
| #443 | { title: "4. Data We Collect", body: "Depending on how you use the Platform we may collect:\n\n• Identity information such as your full name, date of birth, gender, nationality and profile photo.\n• Contact information such as your email address, phone number, city and country of residence.\n• Education information such as your university, programme, level of study, year of study, graduation year and GPA.\n• Professional information such as your skills, languages, career interests, work experience and CV documents.\n• Organisation information such as organisation name, type, sector, registration details, contact person details and verification documents.\n• Account information such as your username, password, login activity and platform preferences.\n• Document uploads such as CVs, cover letters, academic transcripts, portfolios, student IDs and organisation verification documents stored securely in our cloud storage.\n• Technical information such as your IP address, browser type, device information and usage data collected automatically when you use the Platform.\n• Payment information such as your mobile money number when processing premium subscription payments. We do not store full payment credentials.\n• Communications such as messages sent between organisations and youth users through the Platform notification system." }, |
| #444 | { title: "5. How We Collect Data", body: "We collect personal information:\n\n• Directly from you when you register, complete your profile, apply for opportunities or contact us\n• Automatically through cookies and technical tools when you browse the Platform\n• From third party authentication providers such as Google when you use social login features" }, |
| #445 | { title: "6. How We Use Your Data", body: "We use your personal data to:\n\n• Create and manage your account on the Platform\n• Match youth users with relevant opportunities based on their profile\n• Allow organisations to review applications and contact applicants\n• Process premium subscription payments\n• Send notifications about applications, opportunities and platform updates\n• Verify organisation registrations and maintain platform integrity\n• Improve and develop Platform features and user experience\n• Comply with legal obligations\n• Prevent fraud and misuse of the Platform\n• Send marketing communications where you have consented" }, |
| #446 | { title: "7. Sharing Your Data", body: "We will not sell your personal data to third parties. We may share your data with:\n\n• Organisations — when you apply for an opportunity your profile information including name, education, skills and CV is shared with the relevant organisation\n• Youth users — organisation profiles and opportunity listings are visible to registered youth users\n• Service providers — including Supabase (database and storage), payment processors (Selcom), and email service providers who process data on our behalf under strict data protection agreements\n• Legal authorities — where required by law or to protect the rights and safety of our users" }, |
| #447 | { title: "8. Data Storage and Security", body: "Your data is stored securely on Supabase infrastructure. We implement appropriate technical and organisational security measures to protect your personal data from unauthorised access, loss or disclosure.\n\nDocument uploads including CVs and verification documents are stored in secure cloud storage with access controls. However we cannot guarantee absolute security of data transmitted over the internet." }, |
| #448 | { title: "9. Youth User Data", body: "When a youth user applies for an opportunity the following information is shared with the relevant organisation:\n\n• Full name\n• Email address\n• University and programme\n• Skills\n• CV document (if uploaded)\n• Application status\n\nYouth users control what information they include in their profiles and can update or delete their information at any time." }, |
| #449 | { title: "10. Organisation User Data", body: "Organisation profiles including name, type, sector, country, contact details and verification status are visible to registered youth users on the Platform. Organisation users are responsible for ensuring all opportunity listings are accurate, genuine and comply with applicable employment laws." }, |
| #450 | { title: "11. Cookies", body: "The Platform uses cookies and similar technologies to improve your experience, remember your preferences and analyse Platform usage. You can control cookie settings through your browser but disabling cookies may affect Platform functionality." }, |
| #451 | { title: "12. Premium Subscriptions and Payments", body: "Premium subscription payments of 2,000 TZS per month are processed through approved payment partners including Selcom. We collect your mobile money number to process payments but do not store full payment credentials. Payment data is handled in accordance with the payment provider's security standards." }, |
| #452 | { title: "13. Data Retention", body: "We retain your personal data for as long as your account is active or as needed to provide Services. You may request deletion of your account and personal data at any time. Some data may be retained for legal or compliance purposes after account deletion." }, |
| #453 | { title: "14. Your Rights", body: "You have the right to:\n\n• Access your personal data held by us\n• Correct inaccurate or incomplete personal data\n• Request deletion of your personal data\n• Object to processing of your personal data\n• Withdraw consent for marketing communications at any time\n• Request transfer of your personal data\n• Lodge a complaint with the relevant data protection authority\n\nTo exercise any of these rights contact us at privacy@fursalinkafrica.com" }, |
| #454 | { title: "15. Children's Privacy", body: "The Platform is not intended for users under 18 years of age. We do not knowingly collect personal data from children. If you believe a child has provided us with personal data please contact us immediately." }, |
| #455 | { title: "16. Third Party Links", body: "The Platform may contain links to third party websites. We are not responsible for the privacy practices or content of those sites. We encourage you to review the privacy policies of any third party sites you visit." }, |
| #456 | { title: "17. Changes to This Policy", body: "We may update this Privacy Policy from time to time. Changes will be posted on the Platform and where significant we will notify registered users by email or platform notification. Your continued use of the Platform after changes are posted constitutes acceptance of the updated Policy." }, |
| #457 | { title: "18. Governing Law", body: "This Policy is governed by the laws of the United Republic of Tanzania and complies with applicable data protection legislation across our operating markets including Tanzania, Kenya, Nigeria and South Africa." }, |
| #458 | { title: "19. Contact Us", body: "For any privacy related questions or requests:\n\nEmail: privacy@fursalinkafrica.com\nWhatsApp: +255 758 205 593\nAddress: FursaLink Africa Limited, Tanzania" }, |
| #459 | ].map((section) => ( |
| #460 | <div key={section.title} style={{ marginBottom: "1.5rem" }}> |
| #461 | <h2 style={{ fontSize: "1.15rem", fontWeight: 700, marginBottom: "0.5rem" }}>{section.title}</h2> |
| #462 | <p style={{ lineHeight: 1.8, whiteSpace: "pre-wrap", color: "#374151" }}>{section.body}</p> |
| #463 | </div> |
| #464 | ))} |
| #465 | </div> |
| #466 | </div> |
| #467 | </PageTransition> |
| #468 | )} |
| #469 | |
| #470 | {page === "terms" && ( |
| #471 | <PageTransition pageKey="terms"> |
| #472 | <div style={{ minHeight: "100vh", background: "#fff" }}> |
| #473 | <nav className="nav"> |
| #474 | <div className="nav-inner"> |
| #475 | <a href="#" className="logo" onClick={(e) => { e.preventDefault(); setPage("home"); }}> |
| #476 | <span className="logo-icon"><img src="https://i.imgur.com/FT8aHGw.png" alt="FursaLink" /></span> |
| #477 | <span className="logo-text">Fursa<span className="logo-highlight">Link</span></span> |
| #478 | </a> |
| #479 | <button type="button" className="btn btn-outline btn-sm" onClick={() => setPage("home")}>Back to Home</button> |
| #480 | </div> |
| #481 | </nav> |
| #482 | <div style={{ maxWidth: "800px", margin: "0 auto", padding: "6rem 1.5rem 3rem" }}> |
| #483 | <h1 style={{ fontSize: "2rem", fontWeight: 800, marginBottom: "0.5rem" }}>FURSALINK AFRICA — TERMS & CONDITIONS</h1> |
| #484 | <p style={{ color: "#6b7280", marginBottom: "2rem" }}>Last updated: June 2026</p> |
| #485 | <p style={{ marginBottom: "1.5rem", lineHeight: 1.7 }}>Please read this agreement carefully before accessing or using FursaLink Africa ("Platform"). By accessing or using the Platform, you agree to be bound by these terms. FursaLink Africa may modify this agreement at any time, and such modifications shall be effective immediately upon posting.</p> |
| #486 | |
| #487 | {[ |
| #488 | { title: "1. Copyright and Trademarks", body: "All content, trademarks, logos, and intellectual property on this Platform are owned by FursaLink Africa Limited unless otherwise indicated. You agree not to infringe any intellectual property rights owned by FursaLink Africa Limited, including but not limited to the FursaLink name, logo, and platform design." }, |
| #489 | { title: "2. Use of Information", body: "Information on this Platform is for personal, non-commercial use only and may not be sold, redistributed, or used for commercial purposes. This includes but is not limited to the use of organisation or youth contact details for unsolicited correspondence.\n\nYou may not modify, copy, reproduce, republish, upload, post, transmit or distribute in any way any material from this Platform including code, images, opportunity listings, organisation profiles, youth profiles, pricing data, user interface design, and software.\n\nYou may not use data mining, robots, screen scraping, or similar data gathering tools on this Platform without prior written consent from FursaLink Africa Limited." }, |
| #490 | { title: "3. Youth Users", body: "By registering as a youth user you confirm that:\n\n• You are at least 18 years old or have parental consent\n• The information provided in your profile is accurate and truthful\n• You will not misrepresent your qualifications, skills, or experience to organisations\n• You understand that free accounts are limited to 2 applications per month\n• Premium accounts at 2,000 TZS/month unlock unlimited applications and additional features" }, |
| #491 | { title: "4. Organisation Users", body: "By registering as an organisation you confirm that:\n\n• Your organisation is legally registered and operating\n• All opportunity listings posted are genuine and accurate\n• You will not post fraudulent, misleading, or exploitative opportunities\n• You agree to respond to applicants in a timely and professional manner\n• Your organisation email is valid and monitored\n• You accept that FursaLink Africa reserves the right to verify and approve or reject your organisation listing" }, |
| #492 | { title: "5. Verification", body: "FursaLink Africa verifies organisations through official work email verification. Verified organisations receive a trusted badge visible to all youth users. FursaLink Africa reserves the right to revoke verification status if an organisation is found to be misrepresenting itself or posting fraudulent opportunities." }, |
| #493 | { title: "6. No Guarantees of Availability", body: "FursaLink Africa gives no guarantee of the continued availability of any particular opportunity listed on the Platform. We are not liable should an organisation fill or withdraw a vacancy at any time prior to removal of the listing.\n\nWhilst FursaLink Africa takes reasonable efforts to ensure opportunities and profiles are genuine, we give no guarantee that every listing is free from errors or inaccuracies." }, |
| #494 | { title: "7. Payments and Subscriptions", body: "Premium subscriptions are charged at 2,000 TZS per month. Payments are processed through approved payment partners. FursaLink Africa does not store payment card or mobile money credentials. Subscriptions auto-renew monthly unless cancelled. Refunds are considered on a case by case basis." }, |
| #495 | { title: "8. Privacy and Data", body: "FursaLink Africa is committed to protecting your personal data. By using the Platform you consent to the collection and use of your information as described in our Privacy Policy. Your profile information may be shared with organisations when you apply for opportunities.\n\nWe take reasonable measures to protect your data but cannot guarantee absolute security of information transmitted over the internet." }, |
| #496 | { title: "9. Prohibited Conduct", body: "You agree not to:\n\n• Post false, misleading, or fraudulent information\n• Harass, abuse, or discriminate against other users\n• Use the Platform for any unlawful purpose\n• Attempt to gain unauthorised access to any part of the Platform\n• Use the Platform to send unsolicited messages or spam\n• Exploit youth users in any way" }, |
| #497 | { title: "10. Limitation of Liability", body: "FursaLink Africa does not endorse or recommend any organisation, employer, or opportunity listed on the Platform. We strongly recommend that users conduct their own due diligence before entering into any agreement with any organisation found on the Platform.\n\nFursaLink Africa will not be liable for any loss or damage arising from your use of the Platform or reliance on any information contained therein." }, |
| #498 | { title: "11. Termination", body: "FursaLink Africa reserves the right to suspend or terminate any account that violates these terms without notice." }, |
| #499 | { title: "12. Governing Law", body: "This agreement is governed by the laws of the United Republic of Tanzania. Any disputes shall be subject to the exclusive jurisdiction of Tanzanian courts." }, |
| #500 | { title: "13. Contact", body: "For any questions regarding these terms contact us at:\n\nEmail: legal@fursalinkafrica.com\nWhatsApp: +255 758 205 593\nWebsite: fursalinkafrica.com" }, |
| #501 | ].map((section) => ( |
| #502 | <div key={section.title} style={{ marginBottom: "1.5rem" }}> |
| #503 | <h2 style={{ fontSize: "1.15rem", fontWeight: 700, marginBottom: "0.5rem" }}>{section.title}</h2> |
| #504 | <p style={{ lineHeight: 1.8, whiteSpace: "pre-wrap", color: "#374151" }}>{section.body}</p> |
| #505 | </div> |
| #506 | ))} |
| #507 | </div> |
| #508 | </div> |
| #509 | </PageTransition> |
| #510 | )} |
| #511 | |
| #512 | {page === "cookies" && ( |
| #513 | <PageTransition pageKey="cookies"> |
| #514 | <div style={{ minHeight: "100vh", background: "#fff" }}> |
| #515 | <nav className="nav"> |
| #516 | <div className="nav-inner"> |
| #517 | <a href="#" className="logo" onClick={(e) => { e.preventDefault(); setPage("home"); }}> |
| #518 | <span className="logo-icon"><img src="https://i.imgur.com/FT8aHGw.png" alt="FursaLink" /></span> |
| #519 | <span className="logo-text">Fursa<span className="logo-highlight">Link</span></span> |
| #520 | </a> |
| #521 | <button type="button" className="btn btn-outline btn-sm" onClick={() => setPage("home")}>Back to Home</button> |
| #522 | </div> |
| #523 | </nav> |
| #524 | <div style={{ maxWidth: "800px", margin: "0 auto", padding: "6rem 1.5rem 3rem" }}> |
| #525 | <h1 style={{ fontSize: "2rem", fontWeight: 800, marginBottom: "0.5rem" }}>FURSALINK AFRICA — COOKIE POLICY</h1> |
| #526 | <p style={{ color: "#6b7280", marginBottom: "2rem" }}>Last updated: June 2026</p> |
| #527 | |
| #528 | {[ |
| #529 | { title: "1. What is a Cookie?", body: "A cookie is a small piece of information sent by a web server to be stored on your web browser so that it can be read back later. Cookies help websites remember specific information about visitors to improve their experience. A cookie is a text file saved in your browser's directory and stored in RAM while the browser is running. It may also be stored on your device's hard drive after you log off." }, |
| #530 | { title: "2. FursaLink Africa and Cookies", body: "FursaLink Africa is committed to continually improving the experience for youth users, organisations and all visitors who use our Platform at fursalinkafrica.com.\n\nCookies are currently one of the most effective ways to identify a user in order to provide personalised access to their account and information. By using cookies, FursaLink Africa can:\n\n• Keep you securely logged into your account\n• Remember your preferences and settings\n• Personalise your opportunity recommendations\n• Provide a faster and smoother browsing experience\n• Maintain your session as you navigate between pages" }, |
| #531 | { title: "3. Types of Cookies We Use", body: "Essential Cookies\nThese are necessary for the Platform to function properly. They enable core features such as user authentication, session management and security. Without these cookies the Platform cannot function.\n\nExamples:\n• Session cookies that keep you logged in as a youth user or organisation\n• Security cookies that protect your account from unauthorised access\n• Authentication tokens from Supabase that manage your login state\n\nFunctional Cookies\nThese cookies remember your preferences and settings to provide a more personalised experience.\n\nExamples:\n• Remembering your login type (Youth, Organisation or Admin)\n• Saving your search filters and preferences\n• Remembering your dashboard tab preferences\n\nAnalytics Cookies\nTo measure Platform activity and improve user experience, FursaLink Africa may use analytics tools to compile information about your visit including:\n\n• Browser type and device information\n• IP address and approximate location\n• Pages visited and time spent on each page\n• Actions taken on the Platform such as applications submitted\n• Day and time of your visit\n\nThis information helps us understand how users interact with the Platform and improve our services. Any personally identifiable information gathered is treated as confidential in accordance with our Privacy Policy.\n\nThird Party Cookies\nFursaLink Africa may allow trusted service providers and business partners to place cookies on our Platform including:\n\n• Supabase — for database authentication and session management\n• Google Analytics — for Platform usage analysis\n• Google OAuth — when you use Sign in with Google" }, |
| #532 | { title: "4. How to Control or Turn Off Cookies", body: "You can control cookies through your browser settings. Most browsers allow you to:\n\n• View which cookies are stored on your device\n• Delete existing cookies\n• Block cookies from specific websites\n• Block all third party cookies\n• Set preferences for certain types of cookies\n\nBrowser cookie settings guides:\n• Chrome: Settings → Privacy and Security → Cookies\n• Safari: Preferences → Privacy → Manage Website Data\n• Firefox: Options → Privacy & Security → Cookies\n• Edge: Settings → Privacy → Cookies\n\nPlease note: Setting cookie controls to be too restrictive or declining essential cookies may affect your ability to use certain features of the FursaLink Africa Platform including:\n\n• Staying logged into your account\n• Accessing your youth or organisation dashboard\n• Submitting applications\n• Viewing your notifications\n\nIf you choose to delete or refuse cookies you will need to repeat this process if you use a different device or browser." }, |
| #533 | { title: "5. Cookie Consent", body: "When you first visit fursalinkafrica.com you will be shown a cookie consent banner. By continuing to use the Platform you consent to our use of cookies as described in this Policy.\n\nYou may withdraw your consent at any time by adjusting your browser settings or contacting us directly." }, |
| #534 | { title: "6. Data Collected Through Cookies", body: "Any personal data collected through cookies is handled in accordance with our Privacy Policy. We will not sell cookie data to third parties. Cookie data may be used to:\n\n• Improve Platform performance and features\n• Personalise your opportunity recommendations\n• Analyse usage patterns to improve user experience\n• Ensure Platform security and prevent fraud" }, |
| #535 | { title: "7. Changes to This Cookie Policy", body: "We may update this Cookie Policy from time to time to reflect changes in technology, legislation or our services. Any updates will be posted on the Platform. Your continued use of the Platform after changes are posted constitutes acceptance of the updated Policy." }, |
| #536 | { title: "8. Contact Us", body: "If you have any questions about our use of cookies please contact us:\n\nEmail: privacy@fursalinkafrica.com\nWhatsApp: +255 758 205 593\nWebsite: fursalinkafrica.com\n\nFor more information about how we handle your personal data please refer to our full Privacy Policy at fursalinkafrica.com/privacy" }, |
| #537 | ].map((section) => ( |
| #538 | <div key={section.title} style={{ marginBottom: "1.5rem" }}> |
| #539 | <h2 style={{ fontSize: "1.15rem", fontWeight: 700, marginBottom: "0.5rem" }}>{section.title}</h2> |
| #540 | <p style={{ lineHeight: 1.8, whiteSpace: "pre-wrap", color: "#374151" }}>{section.body}</p> |
| #541 | </div> |
| #542 | ))} |
| #543 | </div> |
| #544 | </div> |
| #545 | </PageTransition> |
| #546 | )} |
| #547 | |
| #548 | {page === "home" && ( |
| #549 | <PageTransition pageKey="home"> |
| #550 | <div className="app"> |
| #551 | {/* Hero */} |
| #552 | <header className="hero"> |
| #553 | <div className="hero-bg" /> |
| #554 | <div className="hero-content"> |
| #555 | <div className="hero-badge">Building the bridges that launch careers</div> |
| #556 | <h1 className="hero-title"> |
| #557 | Connecting Africa's youth to the experience |
| #558 | <span className="hero-highlight"> needed to launch their careers</span> |
| #559 | </h1> |
| #560 | <p className="hero-subtitle"> |
| #561 | FursaLink connects students, recent graduates, and organisations |
| #562 | through internships, volunteering, field placements, and |
| #563 | experiential learning opportunities across Africa. |
| #564 | </p> |
| #565 | <div className="hero-actions"> |
| #566 | <button |
| #567 | type="button" |
| #568 | className="btn btn-primary btn-lg" |
| #569 | onClick={() => setPage("register")} |
| #570 | > |
| #571 | Join as a Youth User |
| #572 | </button> |
| #573 | <button |
| #574 | type="button" |
| #575 | className="btn btn-outline btn-lg" |
| #576 | onClick={() => setPage("org-register")} |
| #577 | > |
| #578 | Post Opportunities |
| #579 | </button> |
| #580 | </div> |
| #581 | <div className="hero-stats"> |
| #582 | {stats.map((stat) => ( |
| #583 | <div key={stat.label} className="hero-stat"> |
| #584 | <span className="hero-stat-value"> |
| #585 | {statsLoading ? "..." : stat.value} |
| #586 | </span> |
| #587 | <span className="hero-stat-label">{stat.label}</span> |
| #588 | </div> |
| #589 | ))} |
| #590 | </div> |
| #591 | </div> |
| #592 | </header> |
| #593 | |
| #594 | {/* Problem Section */} |
| #595 | <section className="section section-dark"> |
| #596 | <div className="container"> |
| #597 | <div className="split"> |
| #598 | <div className="split-text"> |
| #599 | <span className="section-tag">The Challenge</span> |
| #600 | <h2 className="section-title"> |
| #601 | Millions of African youth lack access to practical experience |
| #602 | </h2> |
| #603 | <p className="section-desc"> |
| #604 | Despite Africa having one of the youngest populations in the |
| #605 | world, youth unemployment and underemployment persist. The gap |
| #606 | between academic learning and practical work experience remains a |
| #607 | major barrier to employability. |
| #608 | </p> |
| #609 | <ul className="challenge-list"> |
| #610 | <li>Fragmented and informal opportunity-sharing systems</li> |
| #611 | <li>Geographic inequality in access to opportunities</li> |
| #612 | <li>High levels of misinformation and fraudulent postings</li> |
| #613 | <li>Limited collaboration between universities and employers</li> |
| #614 | <li>Students from underserved communities face the highest barriers</li> |
| #615 | </ul> |
| #616 | </div> |
| #617 | <div className="split-visual"> |
| #618 | <div className="challenge-card"> |
| #619 | <h3>Academic Knowledge</h3> |
| #620 | <p>Theoretical foundation from universities</p> |
| #621 | <div className="challenge-arrow">↓</div> |
| #622 | <div className="challenge-gap">The Experience Gap</div> |
| #623 | <div className="challenge-arrow">↓</div> |
| #624 | <div className="challenge-bridge"> |
| #625 | <div className="challenge-bridge-title">FursaLink Bridges the Gap</div> |
| #626 | <div className="challenge-bridge-desc">Verified opportunities, trusted connections, real experience</div> |
| #627 | </div> |
| #628 | <div className="challenge-arrow">↓</div> |
| #629 | <h3>Career Readiness</h3> |
| #630 | <p>Practical skills employers demand</p> |
| #631 | </div> |
| #632 | </div> |
| #633 | </div> |
| #634 | </div> |
| #635 | </section> |
| #636 | |
| #637 | {/* Platform Features */} |
| #638 | <section className="section" id="features"> |
| #639 | <div className="container"> |
| #640 | <div className="section-header"> |
| #641 | <span className="section-tag">Platform Features</span> |
| #642 | <h2 className="section-title"> |
| #643 | Empowering Africa's next generation through opportunity access |
| #644 | </h2> |
| #645 | <p className="section-desc"> |
| #646 | FursaLink is built to bridge the gap between education and |
| #647 | employment, creating meaningful pathways for Africa's youth. |
| #648 | </p> |
| #649 | </div> |
| #650 | <div className="features-grid"> |
| #651 | {PLATFORM_FEATURES.map((f) => ( |
| #652 | <div key={f.title} className="feature-card"> |
| #653 | <div className="feature-icon-svg">{f.icon}</div> |
| #654 | <h3>{f.title}</h3> |
| #655 | <p>{f.desc}</p> |
| #656 | </div> |
| #657 | ))} |
| #658 | </div> |
| #659 | </div> |
| #660 | </section> |
| #661 | |
| #662 | {/* For Youth */} |
| #663 | <section className="section section-dark" id="for-youth"> |
| #664 | <div className="container"> |
| #665 | <div className="section-header"> |
| #666 | <span className="section-tag">For Youth</span> |
| #667 | <h2 className="section-title"> |
| #668 | Your gateway to internships, volunteering & field placements |
| #669 | </h2> |
| #670 | <p className="section-desc"> |
| #671 | Create your profile, discover opportunities across Africa, and |
| #672 | launch your career with meaningful practical experience. |
| #673 | </p> |
| #674 | </div> |
| #675 | <div className="features-grid features-grid-3"> |
| #676 | {YOUTH_FEATURES.map((f) => ( |
| #677 | <div key={f.title} className="feature-card"> |
| #678 | <div className="feature-icon-svg">{f.icon}</div> |
| #679 | <h3>{f.title}</h3> |
| #680 | <p>{f.desc}</p> |
| #681 | </div> |
| #682 | ))} |
| #683 | </div> |
| #684 | </div> |
| #685 | </section> |
| #686 | |
| #687 | {/* For Organisations */} |
| #688 | <section className="section" id="for-orgs"> |
| #689 | <div className="container"> |
| #690 | <div className="section-header"> |
| #691 | <span className="section-tag">For Organisations</span> |
| #692 | <h2 className="section-title"> |
| #693 | Find and manage Africa's emerging talent |
| #694 | </h2> |
| #695 | <p className="section-desc"> |
| #696 | Whether you're an NGO, startup, corporation, government body, or |
| #697 | research institution — FursaLink helps you reach qualified youth |
| #698 | efficiently. |
| #699 | </p> |
| #700 | </div> |
| #701 | <div className="features-grid"> |
| #702 | {ORG_FEATURES.map((f) => ( |
| #703 | <div key={f.title} className="feature-card"> |
| #704 | <div className="feature-icon-svg">{f.icon}</div> |
| #705 | <h3>{f.title}</h3> |
| #706 | <p>{f.desc}</p> |
| #707 | </div> |
| #708 | ))} |
| #709 | </div> |
| #710 | </div> |
| #711 | </section> |
| #712 | |
| #713 | {/* How It Works */} |
| #714 | <section className="section section-dark" id="how-it-works"> |
| #715 | <div className="container"> |
| #716 | <div className="section-header"> |
| #717 | <span className="section-tag">How It Works</span> |
| #718 | <h2 className="section-title">From sign-up to career launch</h2> |
| #719 | <p className="section-desc"> |
| #720 | Getting started on FursaLink is simple. Follow these steps to |
| #721 | begin your journey. |
| #722 | </p> |
| #723 | </div> |
| #724 | <div className="steps"> |
| #725 | {STEPS.map((step) => ( |
| #726 | <div key={step.num} className="step"> |
| #727 | <div className="step-num">{step.num}</div> |
| #728 | <h3 className="step-title">{step.title}</h3> |
| #729 | <p className="step-desc">{step.desc}</p> |
| #730 | </div> |
| #731 | ))} |
| #732 | </div> |
| #733 | </div> |
| #734 | </section> |
| #735 | |
| #736 | {/* Search Filters Showcase */} |
| #737 | <section className="section"> |
| #738 | <div className="container"> |
| #739 | <div className="split reverse"> |
| #740 | <div className="split-visual"> |
| #741 | <div className="filter-demo"> |
| #742 | <div className="filter-demo-header">Search Opportunities</div> |
| #743 | <div className="filter-row"> |
| #744 | <span className="filter-chip active">🌍 Country</span> |
| #745 | <span className="filter-chip">📚 Field of Study</span> |
| #746 | <span className="filter-chip">💰 Paid/Unpaid</span> |
| #747 | </div> |
| #748 | <div className="filter-row"> |
| #749 | <span className="filter-chip">⏱ Duration</span> |
| #750 | <span className="filter-chip active">📍 Remote/On-site</span> |
| #751 | <span className="filter-chip">🏢 Sector</span> |
| #752 | </div> |
| #753 | <div className="filter-results"> |
| #754 | <div className="filter-result-card"> |
| #755 | <div className="filter-result-badge">Verified</div> |
| #756 | <h4>Software Engineering Intern</h4> |
| #757 | <p>Nairobi, Kenya · 3 months · Paid</p> |
| #758 | </div> |
| #759 | <div className="filter-result-card"> |
| #760 | <div className="filter-result-badge">Verified</div> |
| #761 | <h4>Community Health Volunteer</h4> |
| #762 | <p>Accra, Ghana · 6 months · Stipend</p> |
| #763 | </div> |
| #764 | <div className="filter-result-card"> |
| #765 | <div className="filter-result-badge">Verified</div> |
| #766 | <h4>Research Field Placement</h4> |
| #767 | <p>Cape Town, SA · 4 months · Paid</p> |
| #768 | </div> |
| #769 | </div> |
| #770 | </div> |
| #771 | </div> |
| #772 | <div className="split-text"> |
| #773 | <span className="section-tag">Smart Search</span> |
| #774 | <h2 className="section-title"> |
| #775 | Find exactly what you're looking for |
| #776 | </h2> |
| #777 | <p className="section-desc"> |
| #778 | Our powerful filtering system lets you search opportunities by |
| #779 | country, field of study, paid or unpaid, duration, remote or |
| #780 | on-site, and sector — so you can find the perfect match for your |
| #781 | skills and goals. |
| #782 | </p> |
| #783 | </div> |
| #784 | </div> |
| #785 | </div> |
| #786 | </section> |
| #787 | |
| #788 | {/* CTA */} |
| #789 | <section className="section section-cta" id="cta"> |
| #790 | <div className="container"> |
| #791 | <div className="cta-content"> |
| #792 | <h2 className="cta-title"> |
| #793 | Ready to bridge the experience gap? |
| #794 | </h2> |
| #795 | <p className="cta-desc"> |
| #796 | Whether you're a student seeking your first internship or an |
| #797 | organisation looking for emerging talent, FursaLink connects you |
| #798 | with opportunities across Africa. |
| #799 | </p> |
| #800 | <div className="cta-actions"> |
| #801 | <button |
| #802 | type="button" |
| #803 | className="btn btn-white btn-lg" |
| #804 | onClick={() => setPage("register")} |
| #805 | > |
| #806 | Join as a Youth User |
| #807 | </button> |
| #808 | <button |
| #809 | type="button" |
| #810 | className="btn btn-outline-white btn-lg" |
| #811 | onClick={() => setPage("org-register")} |
| #812 | > |
| #813 | Register Your Organisation |
| #814 | </button> |
| #815 | </div> |
| #816 | <p className="cta-note"> |
| #817 | Free to join for all youth users across Africa |
| #818 | </p> |
| #819 | </div> |
| #820 | </div> |
| #821 | </section> |
| #822 | |
| #823 | {/* Footer */} |
| #824 | <footer className="footer"> |
| #825 | <div className="container"> |
| #826 | <div className="footer-grid"> |
| #827 | <div className="footer-brand"> |
| #828 | <a href="#" className="logo"> |
| #829 | <span className="logo-icon"><img src="https://i.imgur.com/UA4VQC3.png" alt="FursaLink" /></span> |
| #830 | <span className="logo-text"> |
| #831 | Fursa<span className="logo-highlight">Link</span> |
| #832 | </span> |
| #833 | </a> |
| #834 | <p className="footer-tagline"> |
| #835 | Africa's leading youth experiential learning and early-career |
| #836 | opportunity ecosystem. |
| #837 | </p> |
| #838 | </div> |
| #839 | <div className="footer-col"> |
| #840 | <h4>Platform</h4> |
| #841 | <a href="#features">Features</a> |
| #842 | <a href="#how-it-works">How It Works</a> |
| #843 | <a href="#for-youth">For Youth</a> |
| #844 | <a href="#for-orgs">For Organisations</a> |
| #845 | </div> |
| #846 | <div className="footer-col"> |
| #847 | <h4>Resources</h4> |
| #848 | <a href="#">Help Centre</a> |
| #849 | <a href="#">Blog</a> |
| #850 | <a href="#">Partner With Us</a> |
| #851 | <a href="#">Contact</a> |
| #852 | </div> |
| #853 | <div className="footer-col"> |
| #854 | <h4>Legal</h4> |
| #855 | <a href="#" onClick={(e) => { e.preventDefault(); setPage("privacy"); }}>Privacy Policy</a> |
| #856 | <a href="#" onClick={(e) => { e.preventDefault(); setPage("terms"); }}>Terms of Service</a> |
| #857 | <a href="#" onClick={(e) => { e.preventDefault(); setPage("cookies"); }}>Cookie Policy</a> |
| #858 | </div> |
| #859 | </div> |
| #860 | <div className="footer-bottom"> |
| #861 | <p>© 2026 FursaLink Africa. All rights reserved.</p> |
| #862 | <div className="footer-social"> |
| #863 | <a href="#" aria-label="Twitter">𝕏</a> |
| #864 | <a href="#" aria-label="LinkedIn">in</a> |
| #865 | <a href="#" aria-label="Instagram">📷</a> |
| #866 | </div> |
| #867 | </div> |
| #868 | </div> |
| #869 | </footer> |
| #870 | </div> |
| #871 | </PageTransition> |
| #872 | )} |
| #873 | </> |
| #874 | ); |
| #875 | } |
| #876 |