Press n or j to go to the next uncovered block, b, p or k for the previous block.
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 | 2x 2x 2x 2x 2x 18x 16x 14x 56x 112x | // src/components/layout/Footer.tsx
import type {ReactElement} from 'react';
import {Link as RouterLink} from 'react-router-dom';
import {Box, Container, Divider, Link, Stack, Typography} from '@mui/material';
import {LEGAL_DOC_LIST} from '../../content/legal';
// ============================================================================
// Constants
// ============================================================================
const SUPPORT_EMAIL = 'admin@flowstatecapital.ai';
// Calendar year for the copyright line. Computed once at module load — the
// value only needs to be correct to the year, so a render-time Date is overkill
// and would churn on every paint.
const COPYRIGHT_YEAR = new Date().getFullYear();
const COMPLIANCE_TEXT =
'FlowState is a financial technology platform and is not a bank or registered investment adviser. ' +
'Any credit product is subject to onboarding, KYB/KYC, underwriting, collateral eligibility, ' +
'documentation, ongoing compliance, and approval. Services may not be available in all jurisdictions. ' +
'Nothing herein constitutes legal, tax, investment, or accounting advice, or an offer, solicitation, ' +
'or recommendation to buy or sell any security or financial instrument.';
interface FooterLink {
label: string;
to?: string;
href?: string;
}
const FOOTER_LINKS: FooterLink[] = [
{label: 'Privacy Policy', to: '/privacy'},
{label: 'Terms & Conditions', to: '/terms'},
{label: 'FAQ', to: '/faq'},
{label: 'Support', href: `mailto:${SUPPORT_EMAIL}`}
];
// Secondary row of policy/disclosure pages (generated content, FSC-80/90/91
// cluster). Privacy lives in the primary row above, so it's excluded here.
const POLICY_LINKS: {label: string; to: string}[] = LEGAL_DOC_LIST
.filter((doc) => doc.slug !== 'privacy')
.map((doc) => ({label: doc.title, to: `/${doc.slug}`}));
// ============================================================================
// Footer Component
// ============================================================================
/**
* Site-wide footer (FSC-62 / FSC-80 / FSC-91). Renders the legal/support link
* row, a copyright line, and the standing compliance disclaimer. Used inside
* the authenticated app shell and on public legal pages.
*/
export default function Footer(): ReactElement {
return (
<Box
component="footer"
sx={{
mt: 6,
pt: 3,
pb: 4,
borderTop: 1,
borderColor: 'divider'
}}
>
<Container maxWidth="lg" disableGutters>
<Stack
direction={{xs: 'column', sm: 'row'}}
spacing={{xs: 1.5, sm: 2}}
sx={{
alignItems: {xs: 'flex-start', sm: 'center'},
justifyContent: 'space-between',
mb: 2
}}
>
<Typography variant="body2" sx={{color: 'text.secondary'}}>
© {COPYRIGHT_YEAR} FlowState Capital. All rights reserved.
</Typography>
<Stack
direction="row"
spacing={2}
sx={{flexWrap: 'wrap', rowGap: 1}}
divider={<Divider orientation="vertical" flexItem/>}
>
{FOOTER_LINKS.map((link) => (
<Link
key={link.label}
component={link.to !== undefined ? RouterLink : 'a'}
to={link.to}
href={link.href}
underline="hover"
variant="body2"
sx={{color: 'text.secondary', '&:hover': {color: 'primary.main'}}}
>
{link.label}
</Link>
))}
</Stack>
</Stack>
<Stack
direction="row"
spacing={1.5}
sx={{flexWrap: 'wrap', rowGap: 0.5, mb: 2}}
divider={<Divider orientation="vertical" flexItem/>}
>
{POLICY_LINKS.map((link) => (
<Link
key={link.label}
component={RouterLink}
to={link.to}
underline="hover"
variant="caption"
sx={{color: 'text.disabled', '&:hover': {color: 'primary.main'}}}
>
{link.label}
</Link>
))}
</Stack>
<Typography variant="caption" sx={{color: 'text.disabled', display: 'block', lineHeight: 1.6}}>
{COMPLIANCE_TEXT}
</Typography>
</Container>
</Box>
);
}
|