Initial React project
This commit is contained in:
273
src/presentation/stories/pages/StoriesPage.tsx
Normal file
273
src/presentation/stories/pages/StoriesPage.tsx
Normal file
@@ -0,0 +1,273 @@
|
||||
import { useEffect, useState, type CSSProperties } from 'react';
|
||||
import './stories.css';
|
||||
import { SiteFooter } from '../../shared/components/SiteFooter';
|
||||
|
||||
interface IconifyIconProps {
|
||||
className?: string;
|
||||
icon: string;
|
||||
style?: CSSProperties;
|
||||
}
|
||||
|
||||
function IconifyIcon({ className, icon, style }: IconifyIconProps) {
|
||||
return <iconify-icon className={className} icon={icon} style={style} />;
|
||||
}
|
||||
|
||||
function Logo({ nav = true }: { nav?: boolean }) {
|
||||
const idPrefix = nav ? 'storiesNav' : 'storiesFooter';
|
||||
|
||||
return (
|
||||
<svg viewBox="0 0 100 100" className={nav ? 'w-8 h-8 rounded-lg shadow-[0_4px_15px_rgba(49,103,201,0.2)] group-hover:shadow-[0_6px_20px_rgba(49,103,201,0.3)] transition-all group-hover:scale-105' : 'w-8 h-8 rounded-lg shadow-sm transition-transform group-hover:scale-105'}>
|
||||
<defs>
|
||||
<linearGradient id={`${idPrefix}Bg`} x1="0%" y1="100%" x2="100%" y2="0%">
|
||||
<stop offset="0%" stopColor="#1A9A75" />
|
||||
<stop offset="100%" stopColor="#3167C9" />
|
||||
</linearGradient>
|
||||
<linearGradient id={`${idPrefix}Fg`} x1="0%" y1="0%" x2="100%" y2="100%">
|
||||
<stop offset="0%" stopColor="#6ACEEB" />
|
||||
<stop offset="100%" stopColor="#46D3B6" />
|
||||
</linearGradient>
|
||||
</defs>
|
||||
<rect width="100" height="100" fill={`url(#${idPrefix}Bg)`} />
|
||||
<path fillRule="evenodd" clipRule="evenodd" d="M 60 15 L 72 15 L 72 85 L 60 85 L 60 72.98 A 28 28 0 1 1 60 27.02 Z M 44 34 A 16 16 0 1 0 44 66 A 16 16 0 1 0 44 34 Z" fill={`url(#${idPrefix}Fg)`} />
|
||||
</svg>
|
||||
);
|
||||
}
|
||||
|
||||
const seriesCards = [
|
||||
{ image: 'https://images.unsplash.com/photo-1600880292203-757bb62b4baf?w=600&q=80', audience: 'For jobansøgere', episodes: '2 Episoder', tone: 'teal' },
|
||||
{ image: 'https://images.unsplash.com/photo-1542744173-8e7e53415bb0?w=600&q=80', audience: 'For jobansøgere', episodes: '8 Episoder', tone: 'teal' },
|
||||
{ image: 'https://images.unsplash.com/photo-1517245386807-bb43f82c33c4?w=600&q=80', audience: 'For jobansøgere', episodes: '4 Episoder', tone: 'teal' },
|
||||
{ image: 'https://images.unsplash.com/photo-1552664730-d307ca884978?w=600&q=80', audience: 'For virksomheder', episodes: '4 Episoder', tone: 'amber' },
|
||||
{ image: 'https://images.unsplash.com/photo-1553877522-43269d4ea984?w=600&q=80', audience: 'For virksomheder', episodes: '3 Episoder', tone: 'amber' },
|
||||
{ image: 'https://images.unsplash.com/photo-1557804506-669a67965ba0?w=600&q=80', audience: 'For virksomheder', episodes: '3 Episoder', tone: 'amber' },
|
||||
{ image: 'https://images.unsplash.com/photo-1543269664-56d74c658cce?w=600&q=80', audience: 'For virksomheder', episodes: '5 Episoder', tone: 'amber' },
|
||||
{ image: 'https://images.unsplash.com/photo-1522071820081-009f0129c71c?w=600&q=80', audience: 'For virksomheder', episodes: '3 Episoder', tone: 'amber' },
|
||||
] as const;
|
||||
|
||||
export function StoriesPage() {
|
||||
const [isNavOpen, setIsNavOpen] = useState(false);
|
||||
const [isTipsOpen, setIsTipsOpen] = useState(false);
|
||||
const [isHowOpen, setIsHowOpen] = useState(false);
|
||||
|
||||
useEffect(() => {
|
||||
if (!isNavOpen) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
const previousOverflow = document.body.style.overflow;
|
||||
document.body.style.overflow = 'hidden';
|
||||
|
||||
function handleEscape(event: KeyboardEvent) {
|
||||
if (event.key === 'Escape') {
|
||||
setIsNavOpen(false);
|
||||
}
|
||||
}
|
||||
|
||||
window.addEventListener('keydown', handleEscape);
|
||||
return () => {
|
||||
document.body.style.overflow = previousOverflow;
|
||||
window.removeEventListener('keydown', handleEscape);
|
||||
};
|
||||
}, [isNavOpen]);
|
||||
|
||||
useEffect(() => {
|
||||
function handleResize() {
|
||||
if (window.innerWidth > 990) {
|
||||
setIsNavOpen(false);
|
||||
}
|
||||
}
|
||||
|
||||
window.addEventListener('resize', handleResize);
|
||||
return () => window.removeEventListener('resize', handleResize);
|
||||
}, []);
|
||||
|
||||
useEffect(() => {
|
||||
function handleClickOutside(event: MouseEvent) {
|
||||
const target = event.target as HTMLElement | null;
|
||||
if (!target?.closest('.stories-how-dropdown')) {
|
||||
setIsHowOpen(false);
|
||||
}
|
||||
if (!target?.closest('.stories-tips-dropdown')) {
|
||||
setIsTipsOpen(false);
|
||||
}
|
||||
}
|
||||
|
||||
document.addEventListener('click', handleClickOutside);
|
||||
return () => document.removeEventListener('click', handleClickOutside);
|
||||
}, []);
|
||||
|
||||
return (
|
||||
<div className="stories-react-root scroll-smooth bg-[#f8fafc] relative min-h-screen text-gray-600 selection:bg-teal-100 selection:text-teal-900 overflow-x-hidden flex flex-col font-normal custom-scrollbar">
|
||||
<div className="fixed top-[-15%] left-[-10%] w-[60vw] h-[60vw] rounded-full bg-gradient-to-br from-teal-400/30 to-emerald-300/10 blur-[140px] pointer-events-none z-0" />
|
||||
<div className="fixed bottom-[-15%] right-[-10%] w-[70vw] h-[70vw] rounded-full bg-gradient-to-tl from-indigo-500/20 to-purple-400/10 blur-[160px] pointer-events-none z-0" />
|
||||
<div className="fixed top-[20%] right-[15%] w-[40vw] h-[40vw] rounded-full bg-gradient-to-tr from-cyan-400/20 to-blue-300/10 blur-[130px] pointer-events-none z-0" />
|
||||
|
||||
<nav className="stories-nav fixed top-0 inset-x-0 z-50 h-16 bg-white/20 backdrop-blur-2xl border-b border-white/50 shadow-[0_4px_30px_rgba(0,0,0,0.03)] flex items-center justify-between px-6 lg:px-12 transition-all">
|
||||
<a href="/home" className="flex items-center gap-2 group outline-none">
|
||||
<Logo nav />
|
||||
<span className="text-xl font-normal tracking-tight text-gray-900 uppercase">ARBEJD</span>
|
||||
</a>
|
||||
|
||||
<div className="stories-nav-links">
|
||||
<a href="/pricing" className="text-base font-normal text-gray-600 hover:text-gray-900 transition-colors outline-none drop-shadow-sm">Priser</a>
|
||||
<div className="stories-how-dropdown">
|
||||
<button
|
||||
type="button"
|
||||
className="stories-how-trigger text-base font-normal text-gray-600 hover:text-gray-900 transition-colors outline-none drop-shadow-sm"
|
||||
onClick={() => {
|
||||
setIsHowOpen((current) => !current);
|
||||
setIsTipsOpen(false);
|
||||
}}
|
||||
aria-expanded={isHowOpen}
|
||||
>
|
||||
Sådan virker det
|
||||
<IconifyIcon icon="solar:alt-arrow-down-linear" className={`text-base transition-transform ${isHowOpen ? 'rotate-180' : ''}`} style={{ strokeWidth: 1.5 }} />
|
||||
</button>
|
||||
<div className={isHowOpen ? 'stories-how-menu open' : 'stories-how-menu'}>
|
||||
<a href="#" onClick={() => setIsHowOpen(false)}>For virksomheder</a>
|
||||
<a href="#" onClick={() => setIsHowOpen(false)}>For jobsøgere</a>
|
||||
<a href="/pricing" onClick={() => setIsHowOpen(false)}>Priser</a>
|
||||
<a href="#" onClick={() => setIsHowOpen(false)}>FAQ</a>
|
||||
<a href="#" onClick={() => setIsHowOpen(false)}>Nyhedsbrev</a>
|
||||
</div>
|
||||
</div>
|
||||
<div className="stories-tips-dropdown">
|
||||
<button
|
||||
type="button"
|
||||
className="stories-tips-trigger text-base font-normal text-gray-900 transition-colors outline-none drop-shadow-sm border-b-2 border-teal-500 pb-0.5"
|
||||
onClick={() => {
|
||||
setIsTipsOpen((current) => !current);
|
||||
setIsHowOpen(false);
|
||||
}}
|
||||
aria-expanded={isTipsOpen}
|
||||
>
|
||||
Tips og tricks
|
||||
<IconifyIcon icon="solar:alt-arrow-down-linear" className={`text-base transition-transform ${isTipsOpen ? 'rotate-180' : ''}`} style={{ strokeWidth: 1.5 }} />
|
||||
</button>
|
||||
<div className={isTipsOpen ? 'stories-tips-menu open' : 'stories-tips-menu'}>
|
||||
<a href="/stories" className="active" onClick={() => setIsTipsOpen(false)}>Stories</a>
|
||||
<a href="/jobordbogen" onClick={() => setIsTipsOpen(false)}>Jobordbogen</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="stories-nav-actions">
|
||||
<a href="#" className="hidden sm:block text-base font-normal text-gray-700 hover:text-gray-900 transition-colors outline-none drop-shadow-sm">Log ind</a>
|
||||
<a href="#" className="text-base font-normal text-white bg-gradient-to-r from-gray-900 to-gray-800 hover:from-gray-800 hover:to-gray-700 px-5 py-2.5 rounded-full transition-all shadow-[0_4px_15px_rgba(0,0,0,0.1)] outline-none border border-gray-700">Opret dig</a>
|
||||
</div>
|
||||
|
||||
<button type="button" className="stories-nav-hamburger" aria-expanded={isNavOpen} aria-label={isNavOpen ? 'Luk menu' : 'Åbn menu'} onClick={() => setIsNavOpen((current) => !current)}>
|
||||
<IconifyIcon icon={isNavOpen ? 'solar:close-circle-linear' : 'solar:hamburger-menu-linear'} className="text-xl text-gray-800" style={{ strokeWidth: 1.8 }} />
|
||||
</button>
|
||||
|
||||
<div className={isNavOpen ? 'stories-nav-popup open' : 'stories-nav-popup'}>
|
||||
<a href="/pricing" onClick={() => setIsNavOpen(false)}>Priser</a>
|
||||
<a href="#" onClick={() => setIsNavOpen(false)}>Sådan virker det: For virksomheder</a>
|
||||
<a href="#" onClick={() => setIsNavOpen(false)}>Sådan virker det: For jobsøgere</a>
|
||||
<a href="#" onClick={() => setIsNavOpen(false)}>Sådan virker det: FAQ</a>
|
||||
<a href="#" onClick={() => setIsNavOpen(false)}>Sådan virker det: Nyhedsbrev</a>
|
||||
<a href="/stories" onClick={() => setIsNavOpen(false)}>Tips og tricks: Stories</a>
|
||||
<a href="/jobordbogen" onClick={() => setIsNavOpen(false)}>Tips og tricks: Jobordbogen</a>
|
||||
<a href="#" onClick={() => setIsNavOpen(false)}>Log ind</a>
|
||||
<a href="#" className="stories-nav-popup-cta" onClick={() => setIsNavOpen(false)}>Opret dig</a>
|
||||
</div>
|
||||
</nav>
|
||||
|
||||
<main className="flex-1 relative z-10 pt-16">
|
||||
<section className="relative pt-24 pb-20 px-6 lg:px-12 max-w-7xl mx-auto flex flex-col items-center text-center min-h-[500px]">
|
||||
<div className="hidden md:flex absolute top-20 left-[10%] px-5 py-2.5 rounded-full bg-white/60 backdrop-blur-xl border border-white/80 shadow-[0_8px_20px_rgba(0,0,0,0.04)] text-sm text-gray-800 font-medium rotate-[-3deg] animate-float-slow z-20 items-center gap-2"><span className="w-2 h-2 rounded-full bg-teal-400" />Byggebranchen</div>
|
||||
<div className="hidden md:flex absolute top-40 right-[10%] lg:right-[15%] px-5 py-2.5 rounded-full bg-white/60 backdrop-blur-xl border border-white/80 shadow-[0_8px_20px_rgba(0,0,0,0.04)] text-sm text-gray-800 font-medium rotate-[4deg] animate-float-medium z-20 items-center gap-2"><span className="w-2 h-2 rounded-full bg-indigo-400" />Milennials</div>
|
||||
<div className="hidden lg:flex absolute top-32 right-[32%] px-5 py-2.5 rounded-full bg-white/60 backdrop-blur-xl border border-white/80 shadow-[0_8px_20px_rgba(0,0,0,0.04)] text-sm text-gray-800 font-medium rotate-[-6deg] animate-float-slow z-20 items-center gap-2"><span className="w-2 h-2 rounded-full bg-amber-400" />Ledelse</div>
|
||||
<div className="hidden md:flex absolute bottom-12 left-[18%] px-5 py-2.5 rounded-full bg-white/60 backdrop-blur-xl border border-white/80 shadow-[0_8px_20px_rgba(0,0,0,0.04)] text-sm text-gray-800 font-medium rotate-[5deg] animate-float-fast z-20 items-center gap-2"><span className="w-2 h-2 rounded-full bg-rose-400" />IT & Tech</div>
|
||||
<div className="hidden lg:flex absolute top-52 left-[25%] px-5 py-2.5 rounded-full bg-white/60 backdrop-blur-xl border border-white/80 shadow-[0_8px_20px_rgba(0,0,0,0.04)] text-sm text-gray-800 font-medium rotate-[8deg] animate-float-fast z-20 items-center gap-2"><span className="w-2 h-2 rounded-full bg-blue-400" />Iværksætteri</div>
|
||||
<div className="hidden md:flex absolute bottom-24 right-[12%] px-5 py-2.5 rounded-full bg-white/60 backdrop-blur-xl border border-white/80 shadow-[0_8px_20px_rgba(0,0,0,0.04)] text-sm text-gray-800 font-medium rotate-[-2deg] animate-float-medium z-20 items-center gap-2"><span className="w-2 h-2 rounded-full bg-emerald-400" />Gen Z</div>
|
||||
<div className="absolute top-1/3 left-[5%] w-14 h-14 rounded-2xl bg-gradient-to-br from-white/80 to-white/30 backdrop-blur-xl border border-white shadow-xl flex items-center justify-center animate-float-fast z-20 rotate-[-10deg]"><IconifyIcon icon="solar:chat-round-dots-linear" className="text-3xl text-blue-500" style={{ strokeWidth: 1.5 }} /></div>
|
||||
<div className="absolute bottom-16 right-[5%] w-14 h-14 rounded-2xl bg-gradient-to-br from-white/80 to-white/30 backdrop-blur-xl border border-white shadow-xl flex items-center justify-center animate-float-medium z-20 rotate-[15deg]"><IconifyIcon icon="solar:bolt-linear" className="text-3xl text-amber-500" style={{ strokeWidth: 1.5 }} /></div>
|
||||
<div className="absolute top-1/2 left-1/2 -translate-x-1/2 -translate-y-1/2 w-full max-w-4xl aspect-[2/1] bg-gradient-to-tr from-white/40 via-white/10 to-teal-50/30 backdrop-blur-3xl border border-white/60 rounded-[3rem] shadow-[0_8px_40px_rgba(0,0,0,0.06)] -z-10 animate-float-slow" />
|
||||
|
||||
<div className="inline-flex items-center gap-2 px-4 py-2 rounded-full bg-gradient-to-r from-white/80 to-white/40 backdrop-blur-xl border border-white/80 text-gray-800 text-xs font-medium uppercase tracking-wider mb-8 shadow-sm relative z-30">
|
||||
<IconifyIcon icon="solar:play-linear" className="text-base text-teal-600" style={{ strokeWidth: 1.5 }} />
|
||||
Nye korte og inspirerende videoer hver uge
|
||||
</div>
|
||||
|
||||
<h1 className="text-5xl md:text-6xl lg:text-7xl font-medium tracking-tight text-gradient mb-8 leading-tight max-w-4xl drop-shadow-sm relative z-30">Succeshistorier</h1>
|
||||
<p className="text-xl md:text-2xl text-gray-600 max-w-3xl font-normal leading-relaxed drop-shadow-sm relative z-30">
|
||||
Få klar besked fra mennesker der har stået i samme situation som dig. I snack-sized videoer guider vi dig i jagten på dit drømmejob eller din virksomheds talentfulde nye profil.
|
||||
</p>
|
||||
</section>
|
||||
|
||||
<section className="max-w-6xl mx-auto px-6 lg:px-12 relative z-20 pb-24 border-b border-white/40">
|
||||
<div className="grid grid-cols-1 md:grid-cols-2 gap-8">
|
||||
<div className="group relative aspect-video rounded-3xl overflow-hidden shadow-[0_15px_40px_rgba(0,0,0,0.12)] cursor-pointer">
|
||||
<img src="https://images.unsplash.com/photo-1556761175-5973dc0f32d7?w=1000&q=80" alt="Man behind title" className="absolute inset-0 w-full h-full object-cover transform group-hover:scale-105 transition-transform duration-700" />
|
||||
<div className="absolute inset-0 bg-gradient-to-t from-gray-900/90 via-gray-900/40 to-transparent flex flex-col justify-end p-8">
|
||||
<div className="absolute top-1/2 left-1/2 -translate-x-1/2 -translate-y-1/2">
|
||||
<button type="button" className="w-16 h-16 rounded-full bg-white/20 backdrop-blur-md border border-white/40 shadow-2xl flex items-center justify-center text-white group-hover:bg-white/40 group-hover:scale-110 transition-all outline-none">
|
||||
<IconifyIcon icon="solar:play-linear" className="text-3xl ml-1" style={{ strokeWidth: 1.5 }} />
|
||||
</button>
|
||||
</div>
|
||||
<h2 className="text-2xl md:text-3xl font-medium text-white tracking-tight leading-snug drop-shadow-lg max-w-md relative z-10">"Which things about a resume can catch your attention?"</h2>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="group relative aspect-video rounded-3xl overflow-hidden shadow-[0_15px_40px_rgba(0,0,0,0.12)] cursor-pointer">
|
||||
<img src="https://images.unsplash.com/photo-1573497019940-1c28c88b4f3e?w=1000&q=80" alt="Woman behind title" className="absolute inset-0 w-full h-full object-cover transform group-hover:scale-105 transition-transform duration-700" />
|
||||
<div className="absolute inset-0 bg-gradient-to-t from-gray-900/90 via-gray-900/40 to-transparent flex flex-col justify-end p-8">
|
||||
<div className="absolute top-1/2 left-1/2 -translate-x-1/2 -translate-y-1/2">
|
||||
<button type="button" className="w-16 h-16 rounded-full bg-white/20 backdrop-blur-md border border-white/40 shadow-2xl flex items-center justify-center text-white group-hover:bg-white/40 group-hover:scale-110 transition-all outline-none">
|
||||
<IconifyIcon icon="solar:play-linear" className="text-3xl ml-1" style={{ strokeWidth: 1.5 }} />
|
||||
</button>
|
||||
</div>
|
||||
<h2 className="text-2xl md:text-3xl font-medium text-white tracking-tight leading-snug drop-shadow-lg max-w-md relative z-10">"What do you wish to see in a motivated application?"</h2>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section className="pt-24 pb-12 px-6 lg:px-12 max-w-7xl mx-auto text-center relative z-10">
|
||||
<div className="inline-flex items-center justify-center w-16 h-16 rounded-2xl bg-gradient-to-br from-amber-50 to-amber-100/50 border border-amber-200/50 shadow-sm mb-6">
|
||||
<IconifyIcon icon="solar:bolt-linear" className="text-3xl text-amber-500" style={{ strokeWidth: 1.5 }} />
|
||||
</div>
|
||||
<h2 className="text-3xl md:text-4xl font-medium tracking-tight text-gradient-subtle mb-4">Autentiske råd</h2>
|
||||
<p className="text-lg text-gray-600 max-w-2xl mx-auto font-normal drop-shadow-sm">
|
||||
Snack-sized videoer direkte fra inspirerende arbejdsgivere og jobsøgende Danmark over
|
||||
</p>
|
||||
</section>
|
||||
|
||||
<section className="pb-32 px-6 lg:px-12 max-w-7xl mx-auto relative z-10">
|
||||
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-4 gap-6">
|
||||
{seriesCards.map((card, index) => (
|
||||
<div key={`${card.image}-${index}`} className="bg-gradient-to-br from-white/60 to-white/20 backdrop-blur-2xl border border-white/60 rounded-3xl overflow-hidden shadow-[0_8px_30px_rgba(0,0,0,0.04)] hover:shadow-[0_15px_40px_rgba(0,0,0,0.08)] transition-all group flex flex-col">
|
||||
<div className="aspect-video bg-gray-100 relative overflow-hidden">
|
||||
<img src={card.image} alt="Video cover" className="w-full h-full object-cover opacity-90 group-hover:scale-105 transition-transform duration-700" />
|
||||
<div className="absolute inset-0 bg-gradient-to-t from-gray-900/50 to-transparent flex items-center justify-center">
|
||||
<button type="button" className="w-12 h-12 rounded-full bg-white/30 backdrop-blur-md border border-white/60 shadow-xl flex items-center justify-center text-white hover:scale-110 hover:bg-white/50 transition-all outline-none">
|
||||
<IconifyIcon icon="solar:play-linear" className="text-xl ml-1" style={{ strokeWidth: 1.5 }} />
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
<div className="p-6 relative flex flex-col flex-1">
|
||||
<div className="mb-3">
|
||||
<span className={`px-2.5 py-1 text-[10px] font-medium rounded-full uppercase tracking-widest border ${card.tone === 'teal' ? 'text-teal-700 bg-teal-100/80 border-teal-200/50' : 'text-amber-700 bg-amber-100/80 border-amber-200/50'}`}>Helt ny serie</span>
|
||||
</div>
|
||||
<h3 className="text-xl font-medium text-gray-900 tracking-tight mb-6">The motivated application</h3>
|
||||
<div className="mt-auto space-y-3">
|
||||
<div className="flex items-center gap-3 text-sm text-gray-600 font-normal">
|
||||
<IconifyIcon icon="solar:magnifer-linear" className="text-lg text-indigo-500" style={{ strokeWidth: 1.5 }} />
|
||||
{card.audience}
|
||||
</div>
|
||||
<div className="flex items-center gap-3 text-sm text-gray-600 font-normal">
|
||||
<IconifyIcon icon="solar:clapperboard-play-linear" className="text-lg text-cyan-500" style={{ strokeWidth: 1.5 }} />
|
||||
{card.episodes}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
</section>
|
||||
</main>
|
||||
<SiteFooter />
|
||||
</div>
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user