Initial React project

This commit is contained in:
Johan
2026-03-13 00:37:38 +01:00
parent 39f3381467
commit 051b73653d
36 changed files with 411 additions and 240 deletions

BIN
dist/assets/aiagent-iphone-B5AHfCb7.png vendored Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 614 KiB

BIN
dist/assets/aiagent-mac-DhPX0EH7.png vendored Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.0 MiB

BIN
dist/assets/cv-iphone-hV3HpnNw.png vendored Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 409 KiB

BIN
dist/assets/cv-mac-Ck2635qe.png vendored Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.4 MiB

18
dist/assets/index-BVCTZizG.js vendored Normal file

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

Binary file not shown.

After

Width:  |  Height:  |  Size: 880 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 401 KiB

BIN
dist/assets/jobsearch-mac-LE-XqbqC.png vendored Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.0 MiB

BIN
dist/assets/once-click-mac-t90QYs8F.png vendored Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.2 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 301 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 MiB

BIN
dist/assets/simulator-mac-l_jb8Lal.png vendored Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.8 MiB

4
dist/index.html vendored
View File

@@ -7,8 +7,8 @@
<title>arbejd-react</title>
<script src="https://cdn.tailwindcss.com"></script>
<script src="https://code.iconify.design/iconify-icon/1.0.7/iconify-icon.min.js"></script>
<script type="module" crossorigin src="/assets/index-C7d5krmc.js"></script>
<link rel="stylesheet" crossorigin href="/assets/index-nOCYJhc8.css">
<script type="module" crossorigin src="/assets/index-BVCTZizG.js"></script>
<link rel="stylesheet" crossorigin href="/assets/index-BelhbTgc.css">
</head>
<body>
<div id="root"></div>

File diff suppressed because one or more lines are too long

View File

@@ -17,6 +17,7 @@ import { StoriesPage } from './presentation/stories/pages/StoriesPage';
import { NewsletterPage } from './presentation/newsletter/pages/NewsletterPage';
import { ForVirksomhederPage } from './presentation/companies/pages/ForVirksomhederPage';
import { JobSearchersPage } from './presentation/jobseekers/pages/JobSearchersPage';
import { ContactPage } from './presentation/contact/pages/ContactPage';
import {
SimulatorPage,
type SimulatorEvaluationSelection,
@@ -39,6 +40,7 @@ function App() {
const isNewsletterRoute = useMemo(() => window.location.pathname === '/newsletter', []);
const isCompaniesRoute = useMemo(() => window.location.pathname === '/for-virksomheder' || window.location.pathname === '/virksomheder', []);
const isJobseekersRoute = useMemo(() => window.location.pathname === '/for-jobsogere' || window.location.pathname === '/jobsearchers', []);
const isContactRoute = useMemo(() => window.location.pathname === '/kontakt' || window.location.pathname === '/contact', []);
const isJobordbogenEntryRoute = useMemo(() => window.location.pathname.startsWith('/jobordbogen/') && window.location.pathname !== '/jobordbogen/', []);
const isJobordbogenRoute = useMemo(() => window.location.pathname === '/jobordbogen' || window.location.pathname === '/academy', []);
const initialAuthenticated = useMemo(() => Boolean(window.localStorage.getItem('token')), []);
@@ -125,6 +127,10 @@ function App() {
return <JobSearchersPage />;
}
if (isContactRoute) {
return <ContactPage />;
}
if (isJobordbogenEntryRoute) {
return <JobordbogenEntryPage />;
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 614 KiB

BIN
src/assets/aiagent-mac.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.0 MiB

BIN
src/assets/cv-iphone.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 409 KiB

BIN
src/assets/cv-mac.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.4 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 880 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 401 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.0 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.2 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 301 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.8 MiB

View File

@@ -0,0 +1,167 @@
import { type CSSProperties } from 'react';
import './contact.css';
import { SiteFooter } from '../../shared/components/SiteFooter';
import { SiteNavbar } from '../../shared/components/SiteNavbar';
interface IconifyIconProps {
className?: string;
icon: string;
style?: CSSProperties;
}
function IconifyIcon({ className, icon, style }: IconifyIconProps) {
return <iconify-icon className={className} icon={icon} style={style} />;
}
const contactSubjects = [
'Priser',
'Premium',
'CV-optimering',
'Jobsøgning',
'Match-algoritme',
'Interviewtræning',
'AI-agent',
'Jobnotifikationer',
'Virksomhedsprofil',
'Annonceoprettelse',
'Ansøgerflow',
'Integrationer',
'API-adgang',
'Data & sikkerhed',
'GDPR',
'Brugeradgang',
'Onboarding',
'Opsigelse',
'Faktura',
'Betaling',
'Support',
'Bug rapport',
'Feature-ønske',
'Partnerskab',
'Presse',
'Nyhedsbrev',
'Teknisk hjælp',
'Skift plan',
'Demo',
'Andet',
];
const floatingSubjects = contactSubjects.map((label, index) => {
const row = Math.floor(index / 5);
const col = index % 5;
const top = Math.min(90, Math.max(8, 12 + row * 14 + ((index * 11) % 8) - 3));
const left = Math.min(92, Math.max(8, 10 + col * 18 + ((index * 17) % 10) - 4));
return {
label,
top,
left,
duration: 4.8 + (index % 5) * 0.7,
delay: -(index % 7) * 0.65,
};
});
export function ContactPage() {
return (
<div className="contact-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 contact-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" />
<SiteNavbar />
<main className="flex-1 relative z-10 pt-16">
<section className="pt-24 pb-12 px-6 lg:px-12 max-w-7xl mx-auto text-center">
<h1 className="text-4xl md:text-6xl font-medium tracking-tight text-gradient-subtle mb-5">
Kontakt os
</h1>
<p className="text-lg md:text-xl text-gray-600 max-w-3xl mx-auto leading-relaxed">
Har du spørgsmål om platformen, priser eller samarbejde? Send os en besked, vender vi hurtigt tilbage.
</p>
</section>
<section className="pb-24 px-6 lg:px-12 max-w-7xl mx-auto w-full">
<div className="contact-grid-shell grid grid-cols-1 lg:grid-cols-2 gap-8">
<div className="relative h-full min-h-[520px] rounded-[2.5rem] bg-gradient-to-br from-white/65 to-white/20 border border-white/70 backdrop-blur-2xl shadow-[0_12px_40px_rgba(0,0,0,0.05)] overflow-hidden">
<div className="absolute -top-20 -left-16 w-56 h-56 rounded-full bg-teal-300/25 blur-[70px] pointer-events-none" />
<div className="absolute -bottom-20 -right-16 w-64 h-64 rounded-full bg-indigo-300/20 blur-[80px] pointer-events-none" />
<div className="absolute inset-0 pl-[5px]">
{floatingSubjects.map((subject, index) => (
<div
key={`${subject.label}-${index}`}
className="absolute contact-floating-pill"
style={{
top: `${subject.top}%`,
left: `${subject.left}%`,
animationDuration: `${subject.duration}s`,
animationDelay: `${subject.delay}s`,
}}
>
<div className="relative -translate-x-1/2 -translate-y-1/2">
<span className="inline-flex items-center px-3 py-1.5 rounded-full bg-white/75 backdrop-blur-xl border border-white/80 text-xs md:text-sm text-gray-700 shadow-[0_10px_25px_rgba(15,23,42,0.12)] whitespace-nowrap">
{subject.label}
</span>
</div>
</div>
))}
</div>
</div>
<div className="h-full rounded-[2.5rem] p-8 md:p-10 bg-gradient-to-br from-white/75 to-white/35 backdrop-blur-2xl border border-white/80 shadow-[0_12px_40px_rgba(0,0,0,0.05)]">
<div className="mb-8">
<h2 className="text-2xl md:text-3xl font-medium text-gray-900 tracking-tight mb-3">Send en besked</h2>
<p className="text-base text-gray-600">
Fortæl os kort, hvad du har brug for hjælp til.
</p>
</div>
<form className="space-y-5">
<div>
<label htmlFor="contact-name" className="block text-sm font-medium text-gray-700 mb-2">Navn</label>
<input
id="contact-name"
type="text"
placeholder="Dit navn"
className="w-full px-4 py-3 rounded-2xl bg-white/80 border border-white/90 text-gray-900 placeholder:text-gray-500 focus:outline-none focus:ring-2 focus:ring-teal-300 focus:border-teal-200 shadow-sm"
/>
</div>
<div>
<label htmlFor="contact-email" className="block text-sm font-medium text-gray-700 mb-2">E-mail</label>
<input
id="contact-email"
type="email"
placeholder="navn@eksempel.dk"
className="w-full px-4 py-3 rounded-2xl bg-white/80 border border-white/90 text-gray-900 placeholder:text-gray-500 focus:outline-none focus:ring-2 focus:ring-teal-300 focus:border-teal-200 shadow-sm"
/>
</div>
<div>
<label htmlFor="contact-message" className="block text-sm font-medium text-gray-700 mb-2">Besked</label>
<textarea
id="contact-message"
rows={7}
placeholder="Skriv din besked her..."
className="w-full px-4 py-3 rounded-2xl bg-white/80 border border-white/90 text-gray-900 placeholder:text-gray-500 focus:outline-none focus:ring-2 focus:ring-teal-300 focus:border-teal-200 shadow-sm resize-none"
/>
</div>
<button
type="submit"
className="inline-flex items-center justify-center gap-2 px-7 py-3.5 rounded-2xl bg-gradient-to-r from-gray-900 via-gray-800 to-gray-900 text-white font-medium border border-gray-700 hover:from-gray-800 hover:to-gray-700 transition-all shadow-[0_8px_20px_rgba(17,24,39,0.2)]"
>
Send besked
<IconifyIcon icon="solar:arrow-right-linear" className="text-lg" style={{ strokeWidth: 1.5 }} />
</button>
</form>
</div>
</div>
</section>
</main>
<SiteFooter />
</div>
);
}

View File

@@ -0,0 +1,30 @@
.contact-react-root {
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Helvetica, Arial, sans-serif, 'Apple Color Emoji', 'Segoe UI Emoji', 'Segoe UI Symbol';
}
.contact-scrollbar::-webkit-scrollbar { width: 6px; }
.contact-scrollbar::-webkit-scrollbar-track { background: transparent; }
.contact-scrollbar::-webkit-scrollbar-thumb { background-color: rgba(20, 184, 166, 0.2); border-radius: 20px; }
.contact-scrollbar::-webkit-scrollbar-thumb:hover { background-color: rgba(20, 184, 166, 0.4); }
@keyframes float-subject {
0%, 100% { transform: translateY(0) scale(1); }
50% { transform: translateY(-10px) scale(1.02); }
}
.contact-floating-pill {
animation: float-subject 6s ease-in-out infinite;
}
.contact-grid-shell {
min-height: 520px;
}
.text-gradient-subtle {
display: inline-block;
line-height: 1.1;
padding-bottom: 0.08em;
background: linear-gradient(135deg, #1f2937 0%, #4b5563 100%);
-webkit-background-clip: text;
-webkit-text-fill-color: transparent;
}

View File

@@ -79,7 +79,7 @@ export function HomePage() {
<div className="inline-flex items-center gap-2 px-4 py-2 rounded-full bg-gradient-to-r from-white/60 to-white/30 backdrop-blur-xl border border-white/80 text-teal-800 text-sm font-medium uppercase tracking-wider mb-8 shadow-[0_4px_20px_rgba(20,184,166,0.1)]">
<IconifyIcon icon="solar:magic-stick-3-linear" className="text-base" style={{ strokeWidth: 1.5 }} />
Fremtidens rekruttering
FREMTIDENS JOBSØGNING
</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">
@@ -522,14 +522,6 @@ export function HomePage() {
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-8 relative z-10">
<div 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">
<div className="aspect-video bg-gray-100 relative overflow-hidden">
<img src="https://images.unsplash.com/photo-1522071820081-009f0129c71c?w=800&q=80" alt="Team" className="w-full h-full object-cover opacity-80 group-hover:scale-105 transition-transform duration-700" />
<div className="absolute inset-0 bg-gradient-to-t from-gray-900/40 to-transparent flex items-center justify-center">
<button type="button" className="w-14 h-14 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-2xl ml-1" style={{ strokeWidth: 1.5 }} />
</button>
</div>
</div>
<div className="p-6 relative">
<p className="text-base text-gray-700 italic mb-6 leading-relaxed">"Simulatoren var en gamechanger. Jeg var super nervøs for min samtale, men feedbacken gav mig roen til at performe 100%."</p>
<div className="flex items-center gap-3">
@@ -543,14 +535,6 @@ export function HomePage() {
</div>
<div 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">
<div className="aspect-video bg-gray-100 relative overflow-hidden">
<img src="https://images.unsplash.com/photo-1552664730-d307ca884978?w=800&q=80" alt="Meeting" className="w-full h-full object-cover opacity-80 group-hover:scale-105 transition-transform duration-700" />
<div className="absolute inset-0 bg-gradient-to-t from-gray-900/40 to-transparent flex items-center justify-center">
<button type="button" className="w-14 h-14 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-2xl ml-1" style={{ strokeWidth: 1.5 }} />
</button>
</div>
</div>
<div className="p-6">
<p className="text-base text-gray-700 italic mb-6 leading-relaxed">"AI-ansøgningerne sparede mig timevis af arbejde. Det ramte den professionelle tone perfekt fra første forsøg."</p>
<div className="flex items-center gap-3">
@@ -564,14 +548,6 @@ export function HomePage() {
</div>
<div 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 md:col-span-2 lg:col-span-1">
<div className="aspect-video bg-gray-100 relative overflow-hidden">
<img src="https://images.unsplash.com/photo-1573496359142-b8d87734a5a2?w=800&q=80" alt="Success" className="w-full h-full object-cover opacity-80 group-hover:scale-105 transition-transform duration-700" />
<div className="absolute inset-0 bg-gradient-to-t from-gray-900/40 to-transparent flex items-center justify-center">
<button type="button" className="w-14 h-14 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-2xl ml-1" style={{ strokeWidth: 1.5 }} />
</button>
</div>
</div>
<div className="p-6">
<p className="text-base text-gray-700 italic mb-6 leading-relaxed">"Agenten fandt et job jeg aldrig selv ville have søgt på. Det viste sig at være det helt rigtige match for mig."</p>
<div className="flex items-center gap-3">
@@ -673,8 +649,9 @@ export function HomePage() {
<div className="bg-gradient-to-br from-white/60 to-white/10 backdrop-blur-3xl border border-white/60 rounded-[2rem] p-8 shadow-[0_8px_30px_rgba(0,0,0,0.04)] flex flex-col relative overflow-hidden">
<h3 className="text-2xl font-medium text-gray-900 tracking-tight mb-2">30 dage</h3>
<p className="text-base text-gray-600 mb-6">Perfekt til at komme hurtigt i gang.</p>
<div className="mb-8">
<div className="mb-8 flex items-center gap-3">
<span className="text-5xl font-medium text-gray-900 tracking-tight">49 kr</span>
<span className="inline-flex items-center px-2.5 py-1 rounded-full text-xs font-medium bg-teal-50 text-teal-700 border border-teal-200">1,63 kr/dag</span>
</div>
<ul className="space-y-4 mb-8 flex-1">
@@ -697,8 +674,9 @@ export function HomePage() {
<span className="px-3 py-1.5 text-xs font-medium text-teal-900 bg-gradient-to-r from-teal-300 to-emerald-300 rounded-lg uppercase tracking-wider shadow-[0_0_15px_rgba(45,212,191,0.3)]">Mest populær</span>
</div>
<p className="text-base text-gray-400 mb-6 relative z-10">Ideelt til den dedikerede jobsøgende.</p>
<div className="mb-8 relative z-10">
<div className="mb-8 relative z-10 flex items-center gap-3">
<span className="text-5xl font-medium text-white tracking-tight drop-shadow-md">129 kr</span>
<span className="inline-flex items-center px-2.5 py-1 rounded-full text-xs font-medium bg-white/15 text-teal-200 border border-white/20">1,43 kr/dag</span>
</div>
<ul className="space-y-4 mb-8 flex-1 relative z-10">
@@ -802,46 +780,14 @@ export function HomePage() {
<p className="text-xl text-gray-700 mb-10 font-normal leading-relaxed drop-shadow-sm">
Lad ikke de bedste muligheder til andre. Tilslut dig tusindvis af ambitiøse jobsøgere, der allerede bruger fremtidens værktøjer Arbejd.com. Din næste store chance venter.
</p>
<button type="button" className="inline-flex items-center gap-2 px-8 py-4 bg-gradient-to-r from-gray-900 via-gray-800 to-gray-900 border border-gray-700 hover:border-gray-600 text-white rounded-full font-normal text-lg transition-all shadow-[0_8px_25px_rgba(17,24,39,0.2)] outline-none hover:-translate-y-0.5">
<a href="https://app.arbejd.com" className="inline-flex items-center gap-2 px-8 py-4 bg-gradient-to-r from-gray-900 via-gray-800 to-gray-900 border border-gray-700 hover:border-gray-600 text-white rounded-full font-normal text-lg transition-all shadow-[0_8px_25px_rgba(17,24,39,0.2)] outline-none hover:-translate-y-0.5">
Tilmeld dig Arbejd.com i dag
<IconifyIcon icon="solar:arrow-right-linear" className="text-xl" style={{ strokeWidth: 1.5 }} />
</button>
</a>
</div>
</div>
</section>
<section className="pb-24 px-6 lg:px-12 max-w-7xl mx-auto relative z-10">
<div className="max-w-3xl mx-auto bg-gradient-to-br from-white/70 to-white/30 backdrop-blur-2xl border border-white/70 rounded-[2.25rem] p-8 md:p-10 shadow-[0_12px_40px_rgba(0,0,0,0.05)]">
<div className="text-center mb-8">
<h2 className="text-2xl md:text-3xl font-medium tracking-tight text-gradient-subtle mb-3"> nyt fra Arbejd.com</h2>
<p className="text-base md:text-lg text-gray-600 font-normal">
Tilmeld dig nyhedsbrevet og tips, produktnyheder og nye jobmuligheder direkte i din indbakke.
</p>
</div>
<form className="flex flex-col sm:flex-row gap-3 sm:gap-4">
<label htmlFor="newsletter-email" className="sr-only">E-mail</label>
<input
id="newsletter-email"
type="email"
required
placeholder="Din e-mail"
className="w-full px-5 py-3.5 rounded-2xl bg-white/70 border border-white/80 text-gray-900 placeholder:text-gray-500 focus:outline-none focus:ring-2 focus:ring-teal-300 focus:border-teal-200 shadow-sm"
/>
<button
type="submit"
className="inline-flex items-center justify-center gap-2 px-6 py-3.5 rounded-2xl bg-gradient-to-r from-gray-900 via-gray-800 to-gray-900 text-white font-medium border border-gray-700 hover:from-gray-800 hover:to-gray-700 transition-all shadow-[0_8px_20px_rgba(17,24,39,0.2)]"
>
Tilmeld
<IconifyIcon icon="solar:arrow-right-linear" className="text-lg" style={{ strokeWidth: 1.5 }} />
</button>
</form>
<p className="text-xs text-gray-500 mt-4 text-center">
Du kan altid afmelde dig igen med ét klik.
</p>
</div>
</section>
</main>
<SiteFooter />
</div>

View File

@@ -1,9 +1,18 @@
import { type CSSProperties, type ReactNode } from 'react';
import { useState, type CSSProperties, type ReactNode } from 'react';
import './jobseekers.css';
import { SiteFooter } from '../../shared/components/SiteFooter';
import { SiteNavbar } from '../../shared/components/SiteNavbar';
import screen1Image from '../../../assets/screen1.png';
import screen2Image from '../../../assets/screen2.png';
import aiAgentIphoneImage from '../../../assets/aiagent-iphone.png';
import aiAgentMacImage from '../../../assets/aiagent-mac.png';
import cvIphoneImage from '../../../assets/cv-iphone.png';
import cvMacImage from '../../../assets/cv-mac.png';
import jobAnsogningIphoneImage from '../../../assets/jobansogning-iphone.png';
import jobSearchIphoneImage from '../../../assets/jobsearch-iphone.png';
import jobSearchMacImage from '../../../assets/jobsearch-mac.png';
import oneClickIphoneImage from '../../../assets/one-click-iphone.png';
import oneClickMacImage from '../../../assets/once-click-mac.png';
import simulatorIphoneImage from '../../../assets/simulatior-iphone.png';
import simulatorMacImage from '../../../assets/simulator-mac.png';
interface IconifyIconProps {
className?: string;
@@ -44,6 +53,43 @@ function PhoneMock({
);
}
function DesktopMock({
image,
alt,
animatedClass,
}: {
image: string;
alt: string;
animatedClass?: string;
}) {
return (
<div className="relative w-full max-w-[560px] mx-auto">
<div className="hidden sm:block absolute top-2 left-[8%] w-20 h-20 rounded-full bg-gradient-to-tr from-white/40 via-white/10 to-teal-50/30 backdrop-blur-xl border border-white/60 shadow-[0_8px_40px_rgba(0,0,0,0.06)] z-0 animate-float-ambient" />
<div className="hidden sm:block absolute bottom-6 right-[8%] w-24 h-24 rounded-[2rem] rotate-12 bg-gradient-to-tr from-white/40 via-white/10 to-indigo-50/30 backdrop-blur-xl border border-white/60 shadow-[0_8px_40px_rgba(0,0,0,0.06)] z-0 animate-float-ambient [animation-delay:2s]" />
<div className={`relative shrink-0 flex flex-col items-center ${animatedClass ?? 'animate-float-desktop'} z-10`}>
<div className="jobseekers-glass-glare relative w-[320px] h-[230px] sm:w-[460px] sm:h-[310px] md:w-[520px] md:h-[350px] rounded-[2rem] p-3 sm:p-4 bg-gradient-to-br from-white/30 to-white/5 backdrop-blur-2xl border border-white/40 shadow-[0_20px_50px_rgba(0,0,0,0.1),inset_0_0_20px_rgba(255,255,255,0.4)] z-10 flex flex-col">
<div
className="relative w-full flex-grow rounded-[1.2rem] sm:rounded-[1.4rem] bg-gray-900 overflow-hidden isolate"
style={{ WebkitMaskImage: '-webkit-radial-gradient(white, black)' }}
>
<img src={image} alt={alt} className="absolute inset-0 w-full h-full object-cover object-center z-0" />
</div>
<div className="w-full h-10 sm:h-14 shrink-0 flex items-center justify-center">
<div className="w-6 h-6 sm:w-8 sm:h-8 rounded-full bg-white/20 border border-white/30 flex items-center justify-center shadow-[inset_0_0_10px_rgba(255,255,255,0.2)]">
<div className="w-2 h-2 sm:w-3 sm:h-3 bg-white/40 rounded-full blur-[1px]" />
</div>
</div>
</div>
<div className="jobseekers-imac-stand-leg relative w-20 sm:w-28 h-14 sm:h-20 -mt-4 bg-gradient-to-b from-white/30 to-white/10 backdrop-blur-md border-x border-white/40 shadow-[0_10px_30px_rgba(0,0,0,0.1)] z-0" />
<div className="w-28 sm:w-40 h-2 sm:h-2.5 rounded-full bg-white/40 backdrop-blur-md border border-white/50 shadow-[0_5px_15px_rgba(0,0,0,0.1)] z-0" />
</div>
</div>
);
}
type Pill = {
icon: string;
label: string;
@@ -53,7 +99,8 @@ type Pill = {
type FeatureSection = {
description: string;
image: string;
mobileImage: string;
desktopImage: string;
pills?: Pill[];
title: string;
};
@@ -63,13 +110,15 @@ const featureSections: FeatureSection[] = [
title: 'Job Search',
description:
'Appen viser de stillinger, der matcher dig bedst, baseret på dit CV, dine kompetencer, ønsket geografi, arbejdstid, branche og de filtre, du selv vælger. Resultaterne bliver løbende forbedret, når du interagerer med opslag og opdaterer dine præferencer.',
image: screen1Image,
mobileImage: jobSearchIphoneImage,
desktopImage: jobSearchMacImage,
},
{
title: 'CV Management',
description:
'Tilføj erfaring, uddannelse, kvalifikationer, certifikater, sprog og kørekort i ét samlet flow. Når din profil er komplet, bliver du lettere fundet af relevante arbejdsgivere, og dine ansøgninger står stærkere i match-processen.',
image: screen2Image,
mobileImage: cvIphoneImage,
desktopImage: cvMacImage,
pills: [
{ icon: 'solar:case-linear', label: 'Erfaring', position: '-top-3 -left-12', tone: 'text-teal-700 bg-teal-50 border-teal-200' },
{ icon: 'solar:diploma-linear', label: 'Uddannelse', position: 'top-20 -right-14', tone: 'text-indigo-700 bg-indigo-50 border-indigo-200' },
@@ -83,7 +132,8 @@ const featureSections: FeatureSection[] = [
title: 'AI-agenter',
description:
'Dine AI-agenter søger hver dag efter de bedste jobmatches, sender dig relevante notifikationer og giver konkrete anbefalinger til forbedringer i dit CV. Det gør din jobsøgning mere målrettet, uden at du selv skal overvåge alle nye opslag.',
image: screen1Image,
mobileImage: aiAgentIphoneImage,
desktopImage: aiAgentMacImage,
pills: [
{ icon: 'solar:bell-bing-linear', label: 'Nyt match: Elektriker', position: '-top-4 -left-16', tone: 'text-teal-700 bg-teal-50 border-teal-200' },
{ icon: 'solar:document-add-linear', label: 'CV-tip: Tilføj certifikat', position: 'top-24 -right-24', tone: 'text-indigo-700 bg-indigo-50 border-indigo-200' },
@@ -95,19 +145,22 @@ const featureSections: FeatureSection[] = [
title: 'Simulator',
description:
'Simulatoren hjælper dig med at træne jobsamtaler i realistiske scenarier. Efter hver session får du en tydelig evaluering med forbedringspunkter til svar, struktur, gennemslagskraft og forberedelse til den konkrete stilling.',
image: screen2Image,
mobileImage: simulatorIphoneImage,
desktopImage: simulatorMacImage,
},
{
title: 'Generér jobansøgning',
description:
'Generér en målrettet ansøgning ud fra stillingsopslag, din profil og dine erfaringer. Du får et stærkt første udkast, som er let at tilpasse, så du hurtigere går fra interessant job til klar ansøgning.',
image: screen1Image,
mobileImage: jobAnsogningIphoneImage,
desktopImage: oneClickMacImage,
},
{
title: 'Ansøg med ét klik',
description:
'Når din profil er sat op, kan du søge relevante stillinger med minimal friktion og følge hele processen ét sted. Du får overblik over gemte jobs, ansøgninger, svar og næste skridt direkte i appen.',
image: screen2Image,
mobileImage: oneClickIphoneImage,
desktopImage: oneClickMacImage,
},
];
@@ -145,6 +198,8 @@ const experienceCards = [
];
export function JobSearchersPage() {
const [platformView, setPlatformView] = useState<'mobile' | 'desktop'>('mobile');
return (
<div className="jobseekers-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" />
@@ -186,10 +241,34 @@ export function JobSearchersPage() {
</div>
<div className="relative flex justify-center">
<PhoneMock image={screen1Image} alt="Arbejd.com app showing a list of jobs" animatedClass="animate-float-phone" />
<div className="absolute -bottom-6 right-0 w-20 h-20 rounded-2xl bg-white/80 border border-white/80 shadow-lg flex items-center justify-center animate-float-soft">
<IconifyIcon icon="solar:case-minimalistic-linear" className="text-4xl text-teal-600" style={{ strokeWidth: 1.5 }} />
<div className={`transition-[opacity,transform,filter] duration-700 ease-[cubic-bezier(0.22,1,0.36,1)] will-change-[opacity,transform,filter] ${platformView === 'mobile' ? 'relative opacity-100 translate-y-0 scale-100 blur-0' : 'absolute inset-0 opacity-0 translate-y-3 scale-[0.985] blur-[1px] pointer-events-none'}`}>
<PhoneMock image={jobSearchIphoneImage} alt="Arbejd.com app showing a list of jobs" animatedClass="animate-float-phone" />
<div className="absolute -bottom-6 right-0 w-20 h-20 rounded-2xl bg-white/80 border border-white/80 shadow-lg flex items-center justify-center animate-float-soft">
<IconifyIcon icon="solar:case-minimalistic-linear" className="text-4xl text-teal-600" style={{ strokeWidth: 1.5 }} />
</div>
</div>
<div className={`transition-[opacity,transform,filter] duration-700 ease-[cubic-bezier(0.22,1,0.36,1)] will-change-[opacity,transform,filter] ${platformView === 'desktop' ? 'relative opacity-100 translate-y-0 scale-100 blur-0' : 'absolute inset-0 opacity-0 translate-y-3 scale-[0.985] blur-[1px] pointer-events-none'}`}>
<DesktopMock image={jobSearchMacImage} alt="Arbejd.com desktopoplevelse" />
</div>
</div>
</div>
<div className="mt-10 flex justify-center">
<div className="inline-flex p-1.5 bg-white/40 backdrop-blur-xl border border-white/80 rounded-full shadow-[0_4px_20px_rgba(0,0,0,0.03)]">
<button
type="button"
className={`px-6 py-2.5 text-sm md:text-base font-medium rounded-full transition-all outline-none ${platformView === 'mobile' ? 'text-gray-900 bg-white shadow-sm border border-gray-100' : 'text-gray-500 hover:text-gray-900'}`}
onClick={() => setPlatformView('mobile')}
>
Mobil
</button>
<button
type="button"
className={`px-6 py-2.5 text-sm md:text-base font-medium rounded-full transition-all outline-none ${platformView === 'desktop' ? 'text-gray-900 bg-white shadow-sm border border-gray-100' : 'text-gray-500 hover:text-gray-900'}`}
onClick={() => setPlatformView('desktop')}
>
Desktop
</button>
</div>
</div>
</section>
@@ -209,17 +288,22 @@ export function JobSearchersPage() {
<div className={reverse ? 'order-1 lg:order-1 flex justify-center lg:justify-start' : 'order-1 lg:order-2 flex justify-center lg:justify-end'}>
<div className="relative">
<PhoneMock image={section.image} alt={section.title} animatedClass={phoneFloatClass}>
{section.pills?.map((pill) => (
<div
key={pill.label}
className={`hidden sm:flex absolute ${pill.position} px-3 py-1.5 rounded-full border bg-white/90 backdrop-blur-md shadow-md items-center gap-1.5 text-xs font-medium ${pill.tone} animate-float-soft`}
>
<IconifyIcon icon={pill.icon} className="text-sm" style={{ strokeWidth: 1.5 }} />
<span>{pill.label}</span>
</div>
))}
</PhoneMock>
<div className={`transition-[opacity,transform,filter] duration-700 ease-[cubic-bezier(0.22,1,0.36,1)] will-change-[opacity,transform,filter] ${platformView === 'mobile' ? 'relative opacity-100 translate-y-0 scale-100 blur-0' : 'absolute inset-0 opacity-0 translate-y-3 scale-[0.985] blur-[1px] pointer-events-none'}`}>
<PhoneMock image={section.mobileImage} alt={section.title} animatedClass={phoneFloatClass}>
{section.pills?.map((pill) => (
<div
key={pill.label}
className={`hidden sm:flex absolute ${pill.position} px-3 py-1.5 rounded-full border bg-white/90 backdrop-blur-md shadow-md items-center gap-1.5 text-xs font-medium ${pill.tone} animate-float-soft`}
>
<IconifyIcon icon={pill.icon} className="text-sm" style={{ strokeWidth: 1.5 }} />
<span>{pill.label}</span>
</div>
))}
</PhoneMock>
</div>
<div className={`transition-[opacity,transform,filter] duration-700 ease-[cubic-bezier(0.22,1,0.36,1)] will-change-[opacity,transform,filter] ${platformView === 'desktop' ? 'relative opacity-100 translate-y-0 scale-100 blur-0' : 'absolute inset-0 opacity-0 translate-y-3 scale-[0.985] blur-[1px] pointer-events-none'}`}>
<DesktopMock image={section.desktopImage} alt={`${section.title} desktop visning`} />
</div>
</div>
</div>
</div>

View File

@@ -22,9 +22,44 @@
50% { transform: translateY(-7px); }
}
@keyframes float-desktop {
0%, 100% { transform: translateY(20px) rotate(4deg) scale(0.95); }
50% { transform: translateY(-4px) rotate(2deg) scale(0.95); }
}
@keyframes float-ambient {
0%, 100% { transform: translateY(0) rotate(0deg); }
50% { transform: translateY(-15px) rotate(5deg); }
}
@keyframes glare {
0% { left: -50%; }
20%, 100% { left: 150%; }
}
.animate-float-phone { animation: float-phone 8s ease-in-out infinite; }
.animate-float-phone-alt { animation: float-phone-alt 10s ease-in-out infinite; }
.animate-float-soft { animation: float-soft 6s ease-in-out infinite; }
.animate-float-desktop { animation: float-desktop 10s ease-in-out infinite; }
.animate-float-ambient { animation: float-ambient 12s ease-in-out infinite; }
.jobseekers-glass-glare::before {
content: '';
position: absolute;
top: 0;
left: -50%;
width: 50%;
height: 100%;
background: linear-gradient(to right, rgba(255, 255, 255, 0) 0%, rgba(255, 255, 255, 0.3) 50%, rgba(255, 255, 255, 0) 100%);
transform: skewX(-25deg);
animation: glare 6s infinite;
pointer-events: none;
z-index: 50;
}
.jobseekers-imac-stand-leg {
clip-path: polygon(20% 0, 80% 0, 100% 100%, 0% 100%);
}
.text-gradient-subtle {
display: inline-block;

View File

@@ -1,4 +1,4 @@
import { useMemo, useState, type CSSProperties } from 'react';
import { useState, type CSSProperties } from 'react';
import './pricing.css';
import { SiteFooter } from '../../shared/components/SiteFooter';
import { SiteNavbar } from '../../shared/components/SiteNavbar';
@@ -47,9 +47,7 @@ function CheckItem({ children, dark = false, small = false, circle = false }: Ch
}
export function PricingPage() {
const pathname = useMemo(() => window.location.pathname, []);
const initialAudience: PricingAudience = pathname.includes('virksomhed') ? 'companies' : 'jobseekers';
const [audience, setAudience] = useState<PricingAudience>(initialAudience);
const [audience] = useState<PricingAudience>('jobseekers');
const isJobseekers = audience === 'jobseekers';
@@ -83,15 +81,7 @@ export function PricingPage() {
<div className={`inline-flex p-1.5 bg-white/40 backdrop-blur-xl border border-white/80 rounded-full shadow-[0_4px_20px_rgba(0,0,0,0.03)] relative ${isJobseekers ? 'mb-12' : 'mb-4'}`}>
<button
type="button"
className={`relative z-10 px-8 py-3 text-sm md:text-base font-medium rounded-full transition-all outline-none ${!isJobseekers ? 'text-gray-900 bg-white shadow-sm border border-gray-100' : 'text-gray-500 hover:text-gray-900'}`}
onClick={() => setAudience('companies')}
>
For virksomheder
</button>
<button
type="button"
className={`relative z-10 px-8 py-3 text-sm md:text-base font-medium rounded-full transition-all outline-none ${isJobseekers ? 'text-gray-900 bg-white shadow-sm border border-gray-100' : 'text-gray-500 hover:text-gray-900'}`}
onClick={() => setAudience('jobseekers')}
className="relative z-10 px-8 py-3 text-sm md:text-base font-medium rounded-full transition-all outline-none text-gray-900 bg-white shadow-sm border border-gray-100"
>
For jobsøgere
</button>
@@ -133,7 +123,7 @@ export function PricingPage() {
<CheckItem>Notifikationer med matches</CheckItem>
<CheckItem>Øget synlighed bliv fundet af virksomheder</CheckItem>
</ul>
<button type="button" className="w-full py-4 rounded-2xl bg-gray-100 hover:bg-gray-200 text-gray-900 font-medium text-lg transition-colors shadow-sm border border-gray-200/50 outline-none mt-auto">Opret Gratis</button>
<a href="https://app.arbejd.com" className="w-full py-4 rounded-2xl bg-gray-100 hover:bg-gray-200 text-gray-900 font-medium text-lg transition-colors shadow-sm border border-gray-200/50 outline-none mt-auto inline-flex items-center justify-center">Opret Gratis</a>
</div>
<div className="bg-gradient-to-br from-gray-900 to-gray-800 backdrop-blur-3xl border border-gray-700/80 rounded-[2.5rem] p-10 shadow-[0_20px_50px_rgba(0,0,0,0.2)] flex flex-col relative overflow-hidden transition-transform hover:-translate-y-1 duration-300 md:-translate-y-4">
@@ -162,7 +152,7 @@ export function PricingPage() {
<CheckItem dark>Karriereagent - personlige anbefalinger til opkvalificering, videreuddannelse og skræddersyede jobveje</CheckItem>
<CheckItem dark>Systemet genererer både CV og ansøgning til din jobsøgning klar til brug og tilpasning.</CheckItem>
</ul>
<button type="button" className="w-full py-4 rounded-2xl bg-gradient-to-r from-white to-gray-100 text-gray-900 font-medium text-lg hover:from-gray-50 hover:to-white transition-all shadow-[0_4px_20px_rgba(255,255,255,0.15)] outline-none relative z-10 mt-auto hover:-translate-y-0.5">Opret Premium</button>
<a href="https://app.arbejd.com" className="w-full py-4 rounded-2xl bg-gradient-to-r from-white to-gray-100 text-gray-900 font-medium text-lg hover:from-gray-50 hover:to-white transition-all shadow-[0_4px_20px_rgba(255,255,255,0.15)] outline-none relative z-10 mt-auto hover:-translate-y-0.5 inline-flex items-center justify-center">Opret Premium</a>
</div>
</div>
</section>
@@ -177,8 +167,9 @@ export function PricingPage() {
<div className="bg-gradient-to-br from-white/60 to-white/10 backdrop-blur-3xl border border-white/60 rounded-[2rem] p-8 shadow-[0_8px_30px_rgba(0,0,0,0.04)] flex flex-col relative overflow-hidden hover:-translate-y-1 transition-transform duration-300">
<h3 className="text-2xl font-medium text-gray-900 tracking-tight mb-2">30 dage</h3>
<p className="text-base text-gray-600 mb-6">Perfekt til at komme hurtigt i gang.</p>
<div className="mb-8">
<div className="mb-8 flex items-center gap-3">
<span className="text-5xl font-medium text-gray-900 tracking-tight">49 kr</span>
<span className="inline-flex items-center px-2.5 py-1 rounded-full text-xs font-medium bg-teal-50 text-teal-700 border border-teal-200">1,63 kr/dag</span>
</div>
<ul className="space-y-4 mb-8 flex-1">
@@ -187,7 +178,7 @@ export function PricingPage() {
<CheckItem small circle>Karriereagent med personlige anbefalinger</CheckItem>
<CheckItem small circle>Job simulatoren træn til din jobsamtale</CheckItem>
</ul>
<button type="button" className="w-full py-3 rounded-xl bg-white/60 backdrop-blur-md border border-white hover:bg-white/90 text-gray-900 font-medium text-base transition-colors shadow-sm outline-none mt-auto">Vælg 30 dage</button>
<a href="https://app.arbejd.com" className="w-full py-3 rounded-xl bg-white/60 backdrop-blur-md border border-white hover:bg-white/90 text-gray-900 font-medium text-base transition-colors shadow-sm outline-none mt-auto inline-flex items-center justify-center">Vælg 30 dage</a>
</div>
<div className="bg-gradient-to-br from-gray-900 to-gray-800 backdrop-blur-3xl border border-gray-700/50 rounded-[2rem] p-8 shadow-[0_20px_50px_rgba(0,0,0,0.2)] flex flex-col relative overflow-hidden transform hover:-translate-y-2 transition-transform duration-300">
@@ -199,8 +190,9 @@ export function PricingPage() {
<span className="px-3 py-1.5 text-xs font-medium text-teal-900 bg-gradient-to-r from-teal-300 to-emerald-300 rounded-lg uppercase tracking-wider shadow-[0_0_15px_rgba(45,212,191,0.3)]">Mest populær</span>
</div>
<p className="text-base text-gray-400 mb-6 relative z-10">Ideelt til den dedikerede jobsøgende.</p>
<div className="mb-8 relative z-10">
<div className="mb-8 relative z-10 flex items-center gap-3">
<span className="text-5xl font-medium text-white tracking-tight drop-shadow-md">129 kr</span>
<span className="inline-flex items-center px-2.5 py-1 rounded-full text-xs font-medium bg-white/15 text-teal-200 border border-white/20">1,43 kr/dag</span>
</div>
<ul className="space-y-4 mb-8 flex-1 relative z-10">
@@ -210,7 +202,7 @@ export function PricingPage() {
<CheckItem small dark circle>Job simulatoren træn til din jobsamtale</CheckItem>
<CheckItem small dark circle>Spar 18 kr. i forhold til 30 dage</CheckItem>
</ul>
<button type="button" className="w-full py-3 rounded-xl bg-gradient-to-r from-white to-gray-100 text-gray-900 font-medium text-base hover:from-gray-50 hover:to-white transition-all shadow-[0_4px_15px_rgba(255,255,255,0.1)] outline-none relative z-10 mt-auto">Vælg 90 dage</button>
<a href="https://app.arbejd.com" className="w-full py-3 rounded-xl bg-gradient-to-r from-white to-gray-100 text-gray-900 font-medium text-base hover:from-gray-50 hover:to-white transition-all shadow-[0_4px_15px_rgba(255,255,255,0.1)] outline-none relative z-10 mt-auto inline-flex items-center justify-center">Vælg 90 dage</a>
</div>
<div className="bg-gradient-to-br from-white/60 to-white/10 backdrop-blur-3xl border border-white/60 rounded-[2rem] p-8 shadow-[0_8px_30px_rgba(0,0,0,0.04)] flex flex-col relative overflow-hidden hover:-translate-y-1 transition-transform duration-300">
@@ -238,7 +230,7 @@ export function PricingPage() {
<CheckItem small circle>Karriereagent med personlige anbefalinger</CheckItem>
<CheckItem small circle>Job simulatoren træn til din jobsamtale</CheckItem>
</ul>
<button type="button" className="w-full py-3 rounded-xl bg-white/60 backdrop-blur-md border border-white hover:bg-white/90 text-gray-900 font-medium text-base transition-colors shadow-sm outline-none mt-auto">Vælg 365 dage</button>
<a href="https://app.arbejd.com" className="w-full py-3 rounded-xl bg-white/60 backdrop-blur-md border border-white hover:bg-white/90 text-gray-900 font-medium text-base transition-colors shadow-sm outline-none mt-auto inline-flex items-center justify-center">Vælg 365 dage</a>
</div>
</div>
</section>
@@ -347,7 +339,7 @@ export function PricingPage() {
<li className="flex items-start gap-3 text-base text-gray-700 leading-snug"><div className="w-6 h-6 rounded-full bg-purple-100 flex items-center justify-center flex-shrink-0 mt-0.5 shadow-sm"><IconifyIcon icon="solar:check-read-linear" className="text-sm text-purple-600" style={{ strokeWidth: 2 }} /></div><span>SaaS-løsning til afslag- og beskedsystem</span></li>
</ul>
<div className="mt-auto">
<button type="button" className="w-full py-4 rounded-2xl bg-gray-100 hover:bg-gray-200 text-gray-900 font-medium text-lg transition-colors shadow-sm border border-gray-200/50 outline-none">Opret Gratis</button>
<a href="https://app.arbejd.com" className="w-full py-4 rounded-2xl bg-gray-100 hover:bg-gray-200 text-gray-900 font-medium text-lg transition-colors shadow-sm border border-gray-200/50 outline-none inline-flex items-center justify-center">Opret Gratis</a>
<p className="text-xs text-center text-gray-500 mt-3">Kræver ikke kreditkort.</p>
</div>
</div>
@@ -371,7 +363,7 @@ export function PricingPage() {
<CheckItem dark>SaaS-løsning til afslag- og beskedsystem</CheckItem>
</ul>
<div className="mt-auto relative z-10">
<button type="button" className="w-full py-4 rounded-2xl bg-gradient-to-r from-white to-gray-100 text-gray-900 font-medium text-lg hover:from-gray-50 hover:to-white transition-all shadow-[0_4px_20px_rgba(255,255,255,0.15)] outline-none hover:-translate-y-0.5">Opret Gratis</button>
<a href="https://app.arbejd.com" className="w-full py-4 rounded-2xl bg-gradient-to-r from-white to-gray-100 text-gray-900 font-medium text-lg hover:from-gray-50 hover:to-white transition-all shadow-[0_4px_20px_rgba(255,255,255,0.15)] outline-none hover:-translate-y-0.5 inline-flex items-center justify-center">Opret Gratis</a>
<p className="text-xs text-center text-gray-400 mt-3">Kræver ikke kreditkort.</p>
</div>
</div>
@@ -393,7 +385,7 @@ export function PricingPage() {
<li className="flex items-start gap-3 text-base text-gray-700 leading-snug"><div className="w-6 h-6 rounded-full bg-purple-100 flex items-center justify-center flex-shrink-0 mt-0.5 shadow-sm"><IconifyIcon icon="solar:check-read-linear" className="text-sm text-purple-600" style={{ strokeWidth: 2 }} /></div><span>SaaS-løsning til afslag- og beskedsystem</span></li>
</ul>
<div className="mt-auto">
<button type="button" className="w-full py-4 rounded-2xl bg-white hover:bg-gray-50 text-gray-900 font-medium text-lg transition-colors shadow-sm border border-gray-200 outline-none">Kontakt os</button>
<a href="https://app.arbejd.com" className="w-full py-4 rounded-2xl bg-white hover:bg-gray-50 text-gray-900 font-medium text-lg transition-colors shadow-sm border border-gray-200 outline-none inline-flex items-center justify-center">Kontakt os</a>
</div>
</div>
</div>

View File

@@ -4,8 +4,8 @@ export function SiteFooter() {
return (
<footer className="bg-white/60 backdrop-blur-xl border-t border-white/80 mt-10 pt-16 pb-12 relative z-10 shadow-[0_-10px_40px_rgba(0,0,0,0.02)]">
<div className="max-w-7xl mx-auto px-6 lg:px-12">
<div className="grid grid-cols-2 md:grid-cols-4 lg:grid-cols-4 gap-10 mb-16">
<div className="col-span-2 lg:col-span-2">
<div className="mb-16">
<div>
<a href="/home" className="flex items-center gap-2 mb-6 group outline-none inline-flex">
<svg viewBox="0 0 100 100" className="w-8 h-8 rounded-lg shadow-sm transition-transform group-hover:scale-105">
<defs>
@@ -28,21 +28,27 @@ export function SiteFooter() {
</p>
<div className="flex items-center gap-3">
<a
href="#"
href="https://www.facebook.com/arbejd.com1/"
target="_blank"
rel="noopener noreferrer"
aria-label="Facebook"
className="w-10 h-10 rounded-xl bg-white/70 border border-white/90 text-gray-500 hover:text-gray-900 hover:bg-white transition-colors inline-flex items-center justify-center shadow-sm"
>
<Facebook size={18} strokeWidth={1.8} />
</a>
<a
href="#"
href="https://www.instagram.com/arbejd.com1/"
target="_blank"
rel="noopener noreferrer"
aria-label="Instagram"
className="w-10 h-10 rounded-xl bg-white/70 border border-white/90 text-gray-500 hover:text-gray-900 hover:bg-white transition-colors inline-flex items-center justify-center shadow-sm"
>
<Instagram size={18} strokeWidth={1.8} />
</a>
<a
href="#"
href="https://www.linkedin.com/company/arbejd-com/posts/?feedView=all"
target="_blank"
rel="noopener noreferrer"
aria-label="LinkedIn"
className="w-10 h-10 rounded-xl bg-white/70 border border-white/90 text-gray-500 hover:text-gray-900 hover:bg-white transition-colors inline-flex items-center justify-center shadow-sm"
>
@@ -50,27 +56,6 @@ export function SiteFooter() {
</a>
</div>
</div>
<div>
<h4 className="text-base font-medium text-gray-900 mb-5">Sådan virker det</h4>
<ul className="space-y-3">
<li><a href="#" className="text-base text-gray-500 hover:text-gray-900 transition-colors font-normal">For virksomheder</a></li>
<li><a href="#" className="text-base text-gray-500 hover:text-gray-900 transition-colors font-normal">For jobsøgere</a></li>
<li><a href="/pricing" className="text-base text-gray-500 hover:text-gray-900 transition-colors font-normal">Priser</a></li>
<li><a href="#" className="text-base text-gray-500 hover:text-gray-900 transition-colors font-normal">FAQ</a></li>
<li><a href="#" className="text-base text-gray-500 hover:text-gray-900 transition-colors font-normal">Nyhedsbrev</a></li>
</ul>
</div>
<div>
<h4 className="text-base font-medium text-gray-900 mb-5">Opret dig</h4>
<ul className="space-y-3">
<li><a href="#" className="text-base text-gray-500 hover:text-gray-900 transition-colors font-normal">Opret virksomhed</a></li>
<li><a href="#" className="text-base text-gray-500 hover:text-gray-900 transition-colors font-normal">Opret jobsøger</a></li>
<li><a href="#" className="text-base text-gray-500 hover:text-gray-900 transition-colors font-normal flex items-center gap-2">Download app <span className="px-2 py-0.5 bg-gradient-to-r from-gray-100 to-gray-50 border border-gray-200 text-xs font-medium text-gray-600 rounded">Snart</span></a></li>
</ul>
</div>
</div>
<div className="pt-8 border-t border-gray-200/60 flex flex-col md:flex-row justify-between items-center gap-4">

View File

@@ -17,10 +17,6 @@ export function SiteNavbar({
activeTipsItem = null,
}: SiteNavbarProps) {
const [isNavOpen, setIsNavOpen] = useState(false);
const [isHowOpen, setIsHowOpen] = useState(false);
const [isTipsOpen, setIsTipsOpen] = useState(false);
const [isMobileHowOpen, setIsMobileHowOpen] = useState(false);
const [isMobileTipsOpen, setIsMobileTipsOpen] = useState(false);
useEffect(() => {
if (!isNavOpen) return undefined;
@@ -44,8 +40,6 @@ export function SiteNavbar({
function handleResize() {
if (window.innerWidth > 990) {
setIsNavOpen(false);
setIsMobileHowOpen(false);
setIsMobileTipsOpen(false);
}
}
@@ -53,23 +47,8 @@ export function SiteNavbar({
return () => window.removeEventListener('resize', handleResize);
}, []);
useEffect(() => {
function handleClickOutside(event: MouseEvent) {
const target = event.target as HTMLElement | null;
if (!target?.closest('.site-navbar-how')) {
setIsHowOpen(false);
}
if (!target?.closest('.site-navbar-tips')) {
setIsTipsOpen(false);
}
}
document.addEventListener('click', handleClickOutside);
return () => document.removeEventListener('click', handleClickOutside);
}, []);
const topLinkBase = 'text-base font-normal transition-colors outline-none drop-shadow-sm';
const activeTop = `${topLinkBase} text-gray-900 border-b border-gray-900 pb-0.5`;
const activeTop = `${topLinkBase} text-gray-900`;
const inactiveTop = `${topLinkBase} text-gray-600 hover:text-gray-900`;
return (
@@ -86,46 +65,14 @@ export function SiteNavbar({
</a>
<div className="hidden md:flex items-center gap-8">
<a
href="/for-jobsogere"
className={(activeTab === 'how' || activeHowItem === 'jobseekers') ? activeTop : inactiveTop}
>
For jobsøgere
</a>
<a href="/pricing" className={activeTab === 'pricing' ? activeTop : inactiveTop}>Priser</a>
<div className="site-navbar-how relative">
<button
type="button"
className={activeTab === 'how' ? activeTop : inactiveTop}
onClick={() => {
setIsHowOpen((current) => !current);
setIsTipsOpen(false);
}}
aria-expanded={isHowOpen}
>
Sådan virker det
</button>
<div className={`${isHowOpen ? 'block' : 'hidden'} absolute top-[calc(100%+0.65rem)] left-0 min-w-[220px] rounded-2xl border border-white/75 bg-gradient-to-br from-white/90 to-white/70 backdrop-blur-2xl shadow-[0_20px_45px_rgba(0,0,0,0.1)] p-2`}>
<div className={`flex items-center justify-between gap-2 px-3 py-2.5 rounded-xl text-sm cursor-default ${activeHowItem === 'companies' ? 'bg-white text-gray-900' : 'text-gray-600'}`}>
<span>For virksomheder</span>
<span className="inline-flex items-center px-1.5 py-0.5 rounded-full text-[9px] font-semibold whitespace-nowrap bg-amber-100 text-amber-700 border border-amber-200">Kommer snart</span>
</div>
<a href="/for-jobsogere" onClick={() => setIsHowOpen(false)} className={`block px-3 py-2.5 rounded-xl text-sm ${activeHowItem === 'jobseekers' ? 'bg-white text-gray-900' : 'text-gray-600 hover:bg-white/70 hover:text-gray-900'}`}>For jobsøgere</a>
</div>
</div>
<div className="site-navbar-tips relative">
<button
type="button"
className={activeTab === 'tips' ? activeTop : inactiveTop}
onClick={() => {
setIsTipsOpen((current) => !current);
setIsHowOpen(false);
}}
aria-expanded={isTipsOpen}
>
Tips og tricks
</button>
<div className={`${isTipsOpen ? 'block' : 'hidden'} absolute top-[calc(100%+0.65rem)] left-0 min-w-[190px] rounded-2xl border border-white/75 bg-gradient-to-br from-white/90 to-white/70 backdrop-blur-2xl shadow-[0_20px_45px_rgba(0,0,0,0.1)] p-2`}>
<a href="/stories" onClick={() => setIsTipsOpen(false)} className={`block px-3 py-2.5 rounded-xl text-sm ${activeTipsItem === 'stories' ? 'bg-white text-gray-900' : 'text-gray-600 hover:bg-white/70 hover:text-gray-900'}`}>Stories</a>
<a href="/jobordbogen" onClick={() => setIsTipsOpen(false)} className={`block px-3 py-2.5 rounded-xl text-sm ${activeTipsItem === 'jobordbogen' ? 'bg-white text-gray-900' : 'text-gray-600 hover:bg-white/70 hover:text-gray-900'}`}>Jobordbogen</a>
</div>
</div>
<a href="/kontakt" className={inactiveTop}>Kontakt</a>
</div>
<div className="hidden md:flex items-center gap-4">
@@ -145,30 +92,9 @@ export function SiteNavbar({
{isNavOpen ? (
<div className="md:hidden absolute top-full right-4 mt-2 w-[min(320px,calc(100vw-2rem))] rounded-2xl border border-white/80 bg-gradient-to-br from-white/92 to-white/70 backdrop-blur-2xl shadow-[0_20px_45px_rgba(0,0,0,0.1)] p-2 flex flex-col gap-1">
<a href="/for-jobsogere" className="px-3 py-2.5 rounded-xl hover:bg-white text-gray-700">For jobsøgere</a>
<a href="/pricing" className="px-3 py-2.5 rounded-xl hover:bg-white text-gray-700">Priser</a>
<button type="button" className="px-3 py-2.5 rounded-xl text-left text-gray-700 hover:bg-white flex items-center justify-between" onClick={() => { setIsMobileHowOpen((c) => !c); setIsMobileTipsOpen(false); }} aria-expanded={isMobileHowOpen}>
Sådan virker det
<iconify-icon icon="solar:alt-arrow-down-linear" className={`${isMobileHowOpen ? 'rotate-180' : ''} transition-transform`} />
</button>
{isMobileHowOpen ? (
<div className="pl-2 flex flex-col gap-1">
<div className="px-3 py-2 rounded-lg text-sm text-gray-700 flex items-center justify-between gap-2 cursor-default">
<span>For virksomheder</span>
<span className="inline-flex items-center px-1.5 py-0.5 rounded-full text-[9px] font-semibold whitespace-nowrap bg-amber-100 text-amber-700 border border-amber-200">Kommer snart</span>
</div>
<a href="/for-jobsogere" className="px-3 py-2 rounded-lg text-sm text-gray-700 hover:bg-white">For jobsøgere</a>
</div>
) : null}
<button type="button" className="px-3 py-2.5 rounded-xl text-left text-gray-700 hover:bg-white flex items-center justify-between" onClick={() => { setIsMobileTipsOpen((c) => !c); setIsMobileHowOpen(false); }} aria-expanded={isMobileTipsOpen}>
Tips og tricks
<iconify-icon icon="solar:alt-arrow-down-linear" className={`${isMobileTipsOpen ? 'rotate-180' : ''} transition-transform`} />
</button>
{isMobileTipsOpen ? (
<div className="pl-2 flex flex-col gap-1">
<a href="/stories" className="px-3 py-2 rounded-lg text-sm text-gray-700 hover:bg-white">Stories</a>
<a href="/jobordbogen" className="px-3 py-2 rounded-lg text-sm text-gray-700 hover:bg-white">Jobordbogen</a>
</div>
) : null}
<a href="/kontakt" className="px-3 py-2.5 rounded-xl hover:bg-white text-gray-700">Kontakt</a>
<a href="https://app.arbejd.com/" className="px-3 py-2.5 rounded-xl hover:bg-white text-gray-700">Log ind</a>
<a href="https://app.arbejd.com/welcome" className="px-3 py-2.5 rounded-xl bg-gray-900 text-white">Opret dig</a>
</div>