Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
20 commits
Select commit Hold shift + click to select a range
6d9974c
fix: :bug: hide navbar on desktop
phibkro Apr 10, 2025
472705f
Merge branch 'main' into vf-301-fix-desktop-navbar-showing-on-mobile
phibkro Apr 10, 2025
6d33931
fix: :bug: fix navbar flickering on mobile navigation
phibkro Apr 10, 2025
93b7e6a
docs: :memo: add docstring for cn
phibkro Apr 10, 2025
a1339f9
fix: :wheelchair: fix accessibility and html structure
phibkro Apr 10, 2025
2a66b2f
fix: :lipstick: fix breakpoint styling
phibkro Apr 10, 2025
60aa64d
Merge branch 'main' into vf-301-fix-desktop-navbar-showing-on-mobile
phibkro Apr 10, 2025
daaa6ac
refactor: :truck: move mock data to api folder
phibkro Apr 10, 2025
2e04d61
fix: :art: fix html and styling
phibkro Apr 10, 2025
72469af
fix: :bug: fix typo
phibkro Apr 10, 2025
b46a6ba
refactor: :recycle: use imports for file paths
phibkro Apr 10, 2025
e533632
refactor: :art: use import for img
phibkro Apr 10, 2025
379c5ea
refactor: :recycle: remove unnecessary classes for login button
phibkro Apr 10, 2025
04c3822
feat: :lipstick: rewrite index layout with grid
phibkro Apr 10, 2025
555174c
feat: :lipstick: rewrite NavBar styling for index grid layout
phibkro Apr 10, 2025
bf29c5b
feat: :lipstick: rewrite Footer styling for index grid layout
phibkro Apr 10, 2025
1d44dc8
Merge branch 'main' into vf-303-skriv-om-layout-med-grid-og-flex
phibkro Apr 10, 2025
b762fcc
fix: :lipstick: center layout children
phibkro Apr 10, 2025
b616874
feat: :lipstick: place content in the middle
phibkro Apr 10, 2025
3354af8
fix: :bug: fix gradient width
phibkro Apr 10, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
36 changes: 36 additions & 0 deletions src/api/main.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
import { type To, href } from "react-router";

interface Metric {
number: number;
title: string;
description: string;
link: {
path: To;
text: string;
};
}

export function getMetrics(): Array<Metric> {
return [
{
number: 2218,
title: "Assistenter",
description:
"Over 2218 studenter har hatt et verv som vektorassistent i Vektorprogrammet",
link: {
path: href("/assistenter"),
text: "Les mer om assistenter",
},
},
{
number: 608,
title: "I team",
description:
"Over 608 studenter har hatt et verv i et av Vektorprogrammets mange team",
link: {
path: href("/team"),
text: "Les mer om verv i team",
},
},
];
}
55 changes: 48 additions & 7 deletions src/api/sponsor.ts
Original file line number Diff line number Diff line change
@@ -1,29 +1,70 @@
import Abelprisen from "/images/mainPage/sponsor/Abelprisen.png";
import ksBergen from "/images/mainPage/sponsor/KSBergen.png";
import Matematikksenteret from "/images/mainPage/sponsor/Matematikksenteret.png";
import NTNUIE from "/images/mainPage/sponsor/NTNUIE.png";
import NTNUIV from "/images/mainPage/sponsor/NTNUIV.png";
import Samarbeidsforum from "/images/mainPage/sponsor/SamarbeidsForum.png";
import sparebankstiftelsenDnb from "/images/mainPage/sponsor/SparebankstiftelsenDNB.png";
import Tekna from "/images/mainPage/sponsor/Tekna.png";
import UiB from "/images/mainPage/sponsor/UIB.png";
import VisionTech from "/images/mainPage/sponsor/VisionTech.png";

export interface Sponsor {
name: string;
url: URL;
image?: string;
}

export function getMainSponsors(): Array<Sponsor> {
return [
{
name: "Abelprisen",
url: new URL("https://www.abelprisen.no/"),
image: Abelprisen,
},
{
name: "Sparebankstiftelsen DNB",
url: new URL("https://www.sparebankstiftelsendnb.no/"),
image: sparebankstiftelsenDnb,
},
];
}

// TODO: This data should be fetched from backend later
export function getSponsors(): Array<Sponsor> {
return [
{ name: "Tekna", url: new URL("https://www.tekna.no/") },
{ name: "Tekna", url: new URL("https://www.tekna.no/"), image: Tekna },
{
name: "Nasjonalt senter for realfagsrekruttering",
url: new URL("https://www.realfagsrekruttering.no/"),
image: Matematikksenteret,
},
{ name: "NTNU IV", url: new URL("https://www.ntnu.no/iv") },
{ name: "NTNU IE", url: new URL("https://www.ntnu.no/ie") },
{ name: "NTNU IV", url: new URL("https://www.ntnu.no/iv"), image: NTNUIV },
{ name: "NTNU IE", url: new URL("https://www.ntnu.no/ie"), image: NTNUIE },
{ name: "NTNU IMF", url: new URL("https://www.ntnu.no/imf") },
{ name: "Samarbeidsforum", url: new URL("https://www.ntnu.no/nv/sf") },
{ name: "Abelprisen", url: new URL("https://www.abelprisen.no/") },
{ name: "VisionTech", url: new URL("https://www.visiontech.no/") },
{
name: "Samarbeidsforum",
url: new URL("https://www.ntnu.no/nv/sf"),
image: Samarbeidsforum,
},
{
name: "VisionTech",
url: new URL("https://www.visiontech.no/"),
image: VisionTech,
},
{
name: "Kulturstyret i Bergen",
url: new URL("https://www.vtvest.no/kulturstyret/"),
image: ksBergen,
},
{
name: "MN-faktultetet ved UiB",
url: new URL("https://www.uib.no/matnat"),
image: UiB,
},
];
}

// TODO: This data should be fetched from backend later
export function getAllSponsors(): Array<Sponsor> {
return [...getMainSponsors(), ...getSponsors()];
}
19 changes: 19 additions & 0 deletions src/lib/utils.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,25 @@
import { type ClassValue, clsx } from "clsx";
import { twMerge } from "tailwind-merge";

/**
* Merge and deduplicate Tailwind classes without style conflicts
*
* @param inputs - Class names to merge
* @returns A string of class names, merged and deduplicated
*/
export function cn(...inputs: Array<ClassValue>) {
return twMerge(clsx(inputs));
}

/**
* Size breakpoints in pixels based on Tailwind CSS defaults.
*
* https://tailwindcss.com/docs/responsive-design
*/
export const breakpointPixels = {
sm: 640,
md: 768,
lg: 1024,
xl: 1280,
"2xl": 1536,
} as const;
198 changes: 59 additions & 139 deletions src/routes/_home._index.tsx
Original file line number Diff line number Diff line change
@@ -1,134 +1,56 @@
import { buttonVariants } from "@/components/ui/button";
import { useInView, useMotionValue, useSpring } from "motion/react";
import { useEffect, useRef } from "react";
import { Link, type To, href } from "react-router";
import { Fragment, useEffect, useRef } from "react";
import { Link } from "react-router";
import { getMetrics } from "~/api/main";
import { getMainSponsors, getSponsors } from "~/api/sponsor";
import { Button } from "~/components/ui/button";
import Abelprisen from "/images/mainPage/sponsor/Abelprisen.png";
import ksBergen from "/images/mainPage/sponsor/KSBergen.png";
import Matematikksenteret from "/images/mainPage/sponsor/Matematikksenteret.png";
import NTNUIE from "/images/mainPage/sponsor/NTNUIE.png";
import NTNUIV from "/images/mainPage/sponsor/NTNUIV.png";
import Samarbeidsforum from "/images/mainPage/sponsor/SamarbeidsForum.png";
import sparebankstiftelsenDnb from "/images/mainPage/sponsor/SparebankstiftelsenDNB.png";
import Tekna from "/images/mainPage/sponsor/Tekna.png";
import UiB from "/images/mainPage/sponsor/UIB.png";
import VisionTech from "/images/mainPage/sponsor/VisionTech.png";
import { cn } from "~/lib/utils";
import vektorForsidebilde from "/images/mainPage/vektor-forsidebilde.png";
import vektorLogo from "/images/vektor-logo.svg";

const hovedsponsor = [
{
name: "Abelprisen",
image: Abelprisen,
},
{
name: "Sparebankstiftelsen DNB",
image: sparebankstiftelsenDnb,
},
];

const sponsorer = [
{
name: "Tekna",
image: Tekna,
},
{
name: "NTNU - Fakultet for ingeniørvitenskap",
image: NTNUIV,
},
{
name: "NTNU - Fakultet for informasjonsteknologi og elektronikk",
image: NTNUIE,
},
{
name: "Samarbeidsforum",
image: Samarbeidsforum,
},
{
name: "Universitetet i Bergen - Det matematisk-naturvitenskapelige fakultet",
image: UiB,
},
{
name: "Matematikksenteret",
image: Matematikksenteret,
},
{
name: "VisionTech",
image: VisionTech,
},
{
name: "Kulturstyret Bergen",
image: ksBergen,
},
];
interface MainPageProps {
number: number;
title: string;
text: string;
route: {
path: To;
text: string;
};
}

const cards: Array<MainPageProps> = [
{
number: 2218,
title: "Assistenter",
text: "Over 2218 studenter har hatt et verv som vektorassistent i Vektorprogrammet",
route: {
path: href("/assistenter"),
text: "Les mer om assistenter",
},
},
{
number: 608,
title: "I team",
text: "Over 608 studenter har hatt et verv i et av Vektorprogrammets mange team",
route: {
path: href("/team"),
text: "Les mer om verv i team",
},
},
];

// biome-ignore lint/style/noDefaultExport: Route Modules require default export https://reactrouter.com/start/framework/route-module
export default function mainPage() {
export default function MainPage() {
const mainSponsors = getMainSponsors();
const sponsors = getSponsors();
const metrics = getMetrics();

return (
<main className="flex-grow">
{/* Use component when the rendered component needs no props */}
{/* Getting the routes from the defined route file in pages */}
<div className="bg-vektor-index-blue md:flex md:h-[80vh] md:pt-14">
{/*Upper start*/}
<div className="flex w-full flex-col items-center text-center md:h-[26rem] md:w-1/2 md:p-8 lg:h-[31rem] xl:h-[35rem]">
<img
className="w-2/4 pt-12 pb-14 md:hidden"
src={vektorLogo}
alt="Vektorprogrammet"
/>
<img
className="mx-auto my-auto h-full w-full p-5 pt-14 md:mr-0 md:ml-auto md:w-auto md:pt-0"
src={vektorForsidebilde}
alt="Vektorprogrammet bildet"
/>
</div>
<div className="w-full p-6 text-center md:mt-24 md:mr-auto md:w-1/2 md:p-10 md:text-left">
<h1 className="mb-4 hidden font-bold text-4xl md:block dark:text-text-dark">
{"Vektorprogrammet"}
</h1>
<div className="mt-6 mb-4 flex justify-center md:block">
<p className="text-left text-md md:w-4/5 md:text-xl dark:text-text-dark">
{`- sender studenter til ungdomsskoler for å hjelpe til som lærerens
<main
className={cn(
// Depends on parent layout
"col-span-full",
)}
>
<header className="grid grid-cols-1 place-items-center gap-14 bg-vektor-index-blue pt-14 md:grid-cols-2 md:flex-row">
<img
className="w-2/4 max-w-prose md:hidden"
src={vektorLogo}
alt={"Logo til Vektorprogrammet"}
/>
<img
className="size-full max-w-prose object-contain"
src={vektorForsidebilde}
width={801}
height={765}
alt="Illustrasjon av assistenter fra Vektorprogrammet foran en tavle med matteformler"
/>
<div className="flex flex-col items-center gap-4 text-center md:items-start md:text-left">
<h1 className="text-wrap font-bold text-4xl">{"Vektorprogrammet"}</h1>
<p className="text-balance text-md">
{`- sender studenter til ungdomsskoler for å hjelpe til som lærerens
assistent i matematikkundervisningen`}
</p>
</div>
<Button variant="green">{"Les mer og bli assistent"}</Button>
</p>
<Button variant="green" className="max-w-fit">
{"Les mer og bli assistent"}
</Button>
</div>
</div>
</header>

{/*Upper end*/}
<div className="info-background mb-0 flex max-w-full flex-row flex-wrap items-center justify-center gap-24 pt-72 pb-72 text-center md:mt-20 md:gap-40">
{/*Middle start*/}
{cards.map(({ number, title, text, route }) => (
{metrics.map(({ number, title, description, link }) => (
<div
key={title}
className="flex max-w-96 flex-col gap-5 text-vektor-bg"
Expand All @@ -139,14 +61,16 @@ export default function mainPage() {
</div>
<p className="text-xl md:text-2xl">{title}</p>
</div>
<p className="max-w-80 text-sm md:max-w-96 md:text-xl">{text}</p>
<p className="max-w-80 text-sm md:max-w-96 md:text-xl">
{description}
</p>
<div>
<Link
to={route.path}
to={link.path}
className={buttonVariants({ variant: "green" })}
prefetch="intent"
>
{route.text}
{link.text}
</Link>
</div>
</div>
Expand All @@ -156,31 +80,27 @@ export default function mainPage() {
<div className="flex justify-center">
<div className="flex max-w-4xl flex-col md:gap-32">
<div className="flex flex-row flex-wrap justify-around md:justify-between">
{hovedsponsor.map((sponsor) => (
{mainSponsors.map(({ name, image }) => (
<div
className="flex h-72 w-72 items-center md:h-96 md:w-96"
key={sponsor.name}
key={name}
>
<img
className="h-auto w-auto"
src={sponsor.image}
alt={sponsor.name}
/>
<img className="h-auto w-auto" src={image} alt={name} />
</div>
))}
</div>
<div className="flex flex-row flex-wrap justify-around md:justify-between">
{sponsorer.map((sponsor) => (
<div
className="flex h-36 w-36 items-center md:h-64 md:w-64"
key={sponsor.name}
>
<img
className="h-auto w-auto"
src={sponsor.image}
alt={sponsor.name}
/>
</div>
{sponsors.map(({ name, image }) => (
<Fragment key={name}>
{image && (
<div
className="flex h-36 w-36 items-center md:h-64 md:w-64"
key={name}
>
<img className="h-auto w-auto" src={image} alt={name} />
</div>
)}
</Fragment>
))}
</div>
</div>
Expand Down
Loading