feat: certificates, landing pages, ai tutor, website update, compliance

This commit is contained in:
Rotimi Best
2026-05-18 03:47:22 +01:00
parent c31ad63955
commit ac3a2c14a7
644 changed files with 56050 additions and 5439 deletions
@@ -1,52 +1,172 @@
<script lang="ts">
import type { OrgLandingPageProps, OrgLandingPageTheme } from './types';
import type { OrgLandingPageFooterConfig, OrgLandingPageTheme } from './types';
import { getFooterTokens } from './landing-page-footer.tokens';
import FooterSocialIcon from './footer-social-icon.svelte';
import ArrowRightIcon from '@lucide/svelte/icons/arrow-right';
import { BlurFade } from '../animation/blurfade';
import EditableLandingSection from './editable-section.svelte';
interface Props {
orgName: string;
logoUrl?: string;
footerLinks: OrgLandingPageProps['footerLinks'];
footerText: string;
footer: OrgLandingPageFooterConfig;
variant: OrgLandingPageTheme;
}
let { orgName, logoUrl, footerLinks, footerText, variant }: Props = $props();
let { orgName, logoUrl, footer, variant }: Props = $props();
const tokens = $derived(getFooterTokens(variant));
const bottom = $derived(footer.bottom);
const bottomLinks = $derived(bottom?.links ?? []);
const bottomText = $derived((bottom?.text ?? '').trim());
function isGridMode(config: OrgLandingPageFooterConfig): boolean {
const tagline = (config.brand.tagline ?? '').trim();
const copyright = (config.brand.copyright ?? '').trim();
return config.columns.length > 0 || config.brand.socials.length > 0 || Boolean(tagline) || Boolean(copyright);
}
const showGrid = $derived(isGridMode(footer));
const showBottomRowInGrid = $derived(bottomText.length > 0 || bottomLinks.length > 0);
function hasCta(column: OrgLandingPageFooterConfig['columns'][number]): boolean {
const cta = column.cta;
if (!cta) {
return false;
}
return Boolean(cta.label.trim() && cta.href.trim());
}
</script>
{#if variant === 'minimal'}
<footer
class="ui:py-12 ui:px-8 ui:max-w-[1200px] ui:mx-auto ui:border-t ui:border-border/50 ui:flex ui:flex-col ui:md:flex-row ui:items-center ui:justify-between ui:gap-4 ui:text-sm ui:text-muted-foreground"
>
<a href="/" class="ui:font-semibold ui:text-xl ui:text-foreground ui:flex ui:items-center ui:gap-2 ui:no-underline">
{#if logoUrl}
<img src={logoUrl} alt={orgName} class="ui:h-8 ui:w-auto" />
{/if}
{orgName}
</a>
<div class="ui:flex ui:flex-wrap ui:justify-center ui:gap-8">
{#each footerLinks as link}
<a href={link.href} class="ui:hover:text-foreground ui:transition-colors">{link.label}</a>
{/each}
</div>
<p>{footerText}</p>
</footer>
{:else}
<footer class="ui:bg-foreground ui:text-background/60 ui:py-16 ui:px-6">
<div class="ui:max-w-7xl ui:mx-auto ui:flex ui:flex-col ui:md:flex-row ui:items-center ui:justify-between ui:gap-8">
<a
href="/"
class="ui:font-black ui:text-2xl ui:text-background ui:tracking-tighter ui:flex ui:items-center ui:gap-3 ui:no-underline"
>
{#if logoUrl}
<img src={logoUrl} alt={orgName} class="ui:h-8 ui:w-auto ui:grayscale ui:brightness-200" />
<EditableLandingSection sectionKey="footer">
<footer class={tokens.root}>
{#if variant === 'terminal'}
<div
class="ui:pointer-events-none ui:absolute ui:inset-x-[-10%] ui:bottom-[-50%] ui:h-[380px]"
style="
background:
radial-gradient(ellipse 60% 80% at 30% 50%, color-mix(in oklab, #f59e0b 35%, transparent) 0%, transparent 60%),
radial-gradient(ellipse 50% 60% at 70% 60%, color-mix(in oklab, #ef4444 30%, transparent) 0%, transparent 60%),
radial-gradient(ellipse 40% 50% at 50% 80%, color-mix(in oklab, #c026d3 22%, transparent) 0%, transparent 60%);
filter: blur(40px);
"
aria-hidden="true"
></div>
{/if}
<div class="ui:relative {tokens.container}">
{#if showGrid}
{#snippet gridInner()}
<div
class="ui:grid ui:grid-cols-1 ui:gap-y-10 ui:gap-x-8 ui:sm:grid-cols-2 ui:md:gap-x-12 ui:md:gap-y-12 ui:md:grid-cols-[minmax(0,1.4fr)_repeat(auto-fit,minmax(140px,1fr))]"
>
<div class="ui:sm:col-span-2 ui:md:col-span-1 ui:min-w-0">
<a href="/" class={tokens.brandName}>
{#if logoUrl}
<img src={logoUrl} alt="" class={tokens.logoImg} />
{/if}
<span class="ui:break-words">{orgName}</span>
</a>
{#if footer.brand.tagline?.trim()}
<p class={tokens.brandTagline}>{footer.brand.tagline}</p>
{/if}
{#if footer.brand.socials.length > 0}
<ul class={tokens.socialWrap}>
{#each footer.brand.socials as social (social.href + social.platform)}
<li class="ui:list-none">
<a
href={social.href}
class={tokens.socialIcon}
target="_blank"
rel="noreferrer noopener"
aria-label={social.platform}
>
<FooterSocialIcon platform={social.platform} class="ui:size-4 ui:md:size-[1.125rem]" />
</a>
</li>
{/each}
</ul>
{/if}
{#if footer.brand.copyright?.trim()}
<p class="{tokens.brandTagline} ui:mt-3">{footer.brand.copyright}</p>
{/if}
</div>
{#each footer.columns as column (column.id)}
<div class="ui:min-w-0">
{#if column.heading.trim()}
<h3 class={tokens.columnHeading}>{column.heading}</h3>
{/if}
<ul class="ui:list-none ui:m-0 ui:p-0 ui:space-y-1">
{#each column.links as link (link.id)}
<li>
<a href={link.href} class={tokens.columnLink}>{link.label}</a>
</li>
{/each}
</ul>
{#if hasCta(column)}
<a href={column.cta!.href} class={tokens.columnCta}>
{column.cta!.label}
<ArrowRightIcon class="ui:size-4 ui:shrink-0" aria-hidden="true" />
</a>
{/if}
</div>
{/each}
</div>
{/snippet}
{#if variant === 'minimal' || variant === 'bold' || variant === 'saas' || variant === 'tech' || variant === 'studio' || variant === 'corporate' || variant === 'terminal'}
<BlurFade delay={0} once={true}>
{#snippet children()}
{@render gridInner()}
{/snippet}
</BlurFade>
{:else}
{@render gridInner()}
{/if}
{orgName}
</a>
<div class="ui:flex ui:flex-wrap ui:justify-center ui:gap-8">
{#each footerLinks as link}
<a href={link.href} class="ui:hover:text-background ui:font-medium ui:transition-colors">{link.label}</a>
{/each}
</div>
<p class="ui:text-sm">{footerText}</p>
{#if showBottomRowInGrid}
{#if variant === 'classic' && tokens.bottomHairline}
<div class={tokens.bottomHairline} aria-hidden="true"></div>
{/if}
<div class={tokens.bottomRow}>
{#if bottomText}
<p class={tokens.bottomText}>{bottomText}</p>
{/if}
{#if bottomLinks.length > 0}
<div class={tokens.bottomLinksWrap}>
{#each bottomLinks as link (link.id)}
<a href={link.href} class={tokens.bottomLink}>{link.label}</a>
{/each}
</div>
{/if}
</div>
{/if}
{:else}
<div class={tokens.compactRow}>
<a href="/" class={tokens.brandName}>
{#if logoUrl}
<img src={logoUrl} alt="" class={tokens.logoImg} />
{/if}
<span class="ui:break-words">{orgName}</span>
</a>
{#if bottomLinks.length > 0}
<div
class="ui:flex ui:flex-wrap ui:justify-start ui:gap-6 ui:md:justify-center ui:md:gap-8 ui:w-full ui:md:w-auto"
>
{#each bottomLinks as link (link.id)}
<a href={link.href} class={tokens.bottomLink}>{link.label}</a>
{/each}
</div>
{/if}
{#if bottomText}
<p class="{tokens.bottomText} ui:w-full ui:md:w-auto ui:text-left ui:md:text-right">{bottomText}</p>
{/if}
</div>
{/if}
</div>
</footer>
{/if}
</EditableLandingSection>