Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
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
4 changes: 4 additions & 0 deletions apps/rpc/src/modules/event/event-repository.ts
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,7 @@ export interface EventRepository {
deleteEventHostingGroups(handle: DBHandle, eventId: EventId, hostingGroupIds: Set<GroupId>): Promise<void>
deleteEventCompanies(handle: DBHandle, eventId: EventId, companyIds: Set<CompanyId>): Promise<void>
updateEventAttendance(handle: DBHandle, eventId: EventId, attendanceId: AttendanceId): Promise<Event>
count(handle: DBHandle): Promise<number>
}

export function getEventRepository(): EventRepository {
Expand Down Expand Up @@ -292,5 +293,8 @@ export function getEventRepository(): EventRepository {
invariant(event !== null, "Event should exist within same transaction after updating attendance")
return event
},
async count(handle) {
return await handle.event.count()
},
}
}
5 changes: 5 additions & 0 deletions apps/rpc/src/modules/event/event-router.ts
Original file line number Diff line number Diff line change
Expand Up @@ -114,4 +114,9 @@ export const eventRouter = t.router({
return ctx.eventService.updateEventAttendance(handle, input.eventId, attendance.id)
})
}),
count: procedure.query(async ({ ctx }) => {
return ctx.executeTransaction(async (handle) => {
return await ctx.eventService.count(handle)
})
}),
})
4 changes: 4 additions & 0 deletions apps/rpc/src/modules/event/event-service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ export interface EventService {
*/
getEventById(handle: DBHandle, eventId: EventId): Promise<Event>
getByAttendance(handle: DBHandle, attendanceId: AttendanceId): Promise<Event>
count(handle: DBHandle): Promise<number>
}

export function getEventService(eventRepository: EventRepository): EventService {
Expand Down Expand Up @@ -91,5 +92,8 @@ export function getEventService(eventRepository: EventRepository): EventService
const event = await this.getEventById(handle, eventId)
return await eventRepository.updateEventAttendance(handle, event.id, attendanceId)
},
async count(handle) {
return await eventRepository.count(handle)
},
}
}
Binary file added apps/web/public/Hovedbygget-01.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added apps/web/public/OnlineStruktur.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
18 changes: 18 additions & 0 deletions apps/web/src/app/om-linjeforeningen/components/OurGoals.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
import { Divider, ImageCard, Text, Title } from "@dotkomonline/ui"

export const OurGoalsCard = () => {
return (
<ImageCard image="/Hovedbygget-01.jpg" alt="Hovedbygget på NTNU" imagePosition="right" className="bg-yellow-100">
<div className="flex flex-col items-center justify-center my-8 sm:my-24">
<Title size={"xxl"} className="pb-1 font-extrabold">
Vårt Mål
</Title>
<Divider className="w-2/3 sm:w-1/2 bg-yellow-300 h-3 rounded-full border-none" />
<Text className="m-4 max-sm:text-center w-2/3">
Online skal arbeide for å skape sterkere bånd mellom medlemmer på ulike årstrinn og være kontaktledd mellom
medlemmene og eksterne aktører.
</Text>
</div>
</ImageCard>
)
}
38 changes: 38 additions & 0 deletions apps/web/src/app/om-linjeforeningen/components/Statistics.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
import { Text } from "@dotkomonline/ui"

export const Statistics = async () => {
const memberCount = roundToLowestN(600, 50) // This could be fetched from the server, but stays relatively constant
const hobbyGroups = roundToLowestN(30, 5) // This could also be fetched from the server, but does not change as often
const eventCount = roundToLowestN(2500, 50) // Fetching the event count from the server

const StatisticsNumber = ({ number, title }: { number: number; title: string }) => {
return (
<div className="flex flex-col items-center">
<Text className="text-5xl font-extrabold">{number}+</Text>
<Text className="text-md">{title}</Text>
</div>
)
}
return (
<>
<Text className="mx-8">
Linjeforeningen startet som en liten gruppe studenter høsten 1985, og har siden den gang vokst til å bli en av
NTNU's større linjeforeninger innen teknologi, med over {memberCount} medlemmer. Foreningen drives av et stort
antall frivillige som legger ned betydelig innsats for å skape et variert og engasjerende tilbud for medlemmene.
Gjennom årene har Online arrangert mer enn {eventCount} aktiviteter inkludert faglige kurs,
bedriftspresentasjoner og sosiale sammenkomster, som til sammen bidrar til å styrke både det faglige og det
sosiale fellesskapet. Denne kombinasjonen av profesjonelle arrangementer og sosiale møteplasser har gjort Online
til en sentral arena for kompetanseutvikling, nettverksbygging og trivsel blant medlemmene.
</Text>
<div className="flex flex-col sm:flex-row justify-around items-center gap-8">
<StatisticsNumber number={memberCount} title="Aktive Medlemmer" />
<StatisticsNumber number={eventCount} title="Arrangerte aktiviteter" />
<StatisticsNumber number={hobbyGroups} title="Interessegrupper" />
</div>
</>
)
}

const roundToLowestN = (num: number, n: number) => {
return Math.floor(num / n) * n
}
43 changes: 43 additions & 0 deletions apps/web/src/app/om-linjeforeningen/components/Structure.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
import { Text, Title } from "@dotkomonline/ui"
import Image from "next/image"
import Link from "next/link"

export const Structure = () => {
return (
<section className="flex flex-col">
<Title size={"xxl"} className="pb-1 font-extrabold">
Struktur
</Title>
<div className="flex flex-col gap-4 space-y-4">
<Text>
Generalforsamlingen utgjør den øverste besluttende myndighet i Online, og kan sammenlignes med et
stortingsvalg for en ny regjering. Mellom generalforsamlingene ivaretas den daglige driften av linjeforeningen
av hovedstyret og komiteene. Disse komiteene har spesifikke ansvarsområder, som spenner fra sosiale
arrangementer til faglige kurs. Dette gir medlemmene muligheten til å engasjere seg i sine interessefelt,
samtidig som det sikrer at foreningen kan tilby et variert spekter av aktiviteter og tjenester.
</Text>
<Text>
Online har også tilknytning til flere andre grupper og organisasjoner som bidrar til å styrke miljøet rundt
linjeforeningen. Disse samarbeidene kan være både sosiale og organisatoriske, og gir medlemmene flere
muligheter for nettverksbygging, kompetanseutvikling og deltakelse i ulike arrangementer.
</Text>
<Text>
Ønsker du å vite mer om hvordan Online er organisert og hvilke grupper vi samarbeider med, kan du lese mer på{" "}
<Link href={"https://wiki.online.ntnu.no"} target="_blank" className="text-blue-900 underline">
Online Wiki
</Link>
</Text>
<>
<Image
src="/OnlineStruktur.png"
alt="Online Organizational Structure map"
width={0}
height={0}
className="w-full sm:w-1/2 self-center"
/>
<Text className="text-center text-sm mt-2">Online Organisasjonskart</Text>
</>
</div>
</section>
)
}
18 changes: 18 additions & 0 deletions apps/web/src/app/om-linjeforeningen/components/WhoAreWeCard.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
import { Divider, ImageCard, Text, Title } from "@dotkomonline/ui"

export const WhoAreWeCard = () => {
return (
<ImageCard image="/online-logo-o.svg" alt="Online logo" imagePosition="left" className="bg-blue-100">
<div className="flex flex-col items-center justify-center my-8 sm:my-24">
<Title size={"xxl"} className="pb-1 font-extrabold">
Hvem er vi?
</Title>
<Divider className="w-2/3 sm:w-1/2 bg-blue-300 h-3 rounded-full border-none " />
<Text className="m-4 max-sm:text-center sm:w-2/3">
Online er linjeforeningen for informatikkstudenter ved NTNU i Trondheim. Linjeforeningens oppgave er å
forbedre studiemiljøet ved å fremme sosialt samvær, faglig kompetanse og kontakt med næringslivet.
</Text>
</div>
</ImageCard>
)
}
130 changes: 9 additions & 121 deletions apps/web/src/app/om-linjeforeningen/page.tsx
Original file line number Diff line number Diff line change
@@ -1,127 +1,15 @@
import { OnlineIcon } from "@/components/atoms/OnlineIcon"
import { server } from "@/utils/trpc/server"
import type { Group } from "@dotkomonline/types"
import { Text, Title } from "@dotkomonline/ui"
import Image from "next/image"
import Link from "next/link"
import type { FC } from "react"
import { OurGoalsCard } from "./components/OurGoals"
import { Statistics } from "./components/Statistics"
import { Structure } from "./components/Structure"
import { WhoAreWeCard } from "./components/WhoAreWeCard"

export default async function AboutOnlinePage() {
const nodeCommittees = await server.group.allByType.query("NODE_COMMITTEE")
const committees = await server.group.allByType.query("COMMITTEE")

return (
<div>
<div className="flex flex-col items-center sm:text-center rounded-xl bg-blue-200 dark:bg-transparent p-8">
<Title size="xl" element="h1" className="mb-10">
Bli kjent med{" "}
<span className="relative inline-block">
Online linjeforening
<span className="absolute left-0 -bottom-6 h-4 w-full bg-blue-600 dark:bg-blue-700 rounded-2xl" />
</span>
</Title>
<Text>
Nysjerrig på hva de ulike delene av Online <em>egentlig</em> er?
<br />
Har du noen gang lurt på hvordan alt henger sammen?
<br />
Her får du et innblikk til linjeforeningens struktur - komiteer, grupper og hovedstyret!
</Text>
</div>
<div className="flex flex-col items-center text-center mt-7">
<Title size={"lg"} element="h2" className="border-b border-gray-500 pb-1 w-full mb-4">
Generalforsamlingen
</Title>

<div className="flex flex-col md:flex-row w-full justify-center sm:px-12 items-center">
<div className="w-full md:w-1/2 max-w-md md:mr-10">
<Image
src="/genfors-banner.jpeg"
alt="Genfors banner"
className="object-contain rounded-2xl w-full h-auto"
width={600}
height={300}
/>
</div>
<div className="text-left max-w-md mt-4 md:mt-0">
<Text>
<Link href="https://wiki.online.ntnu.no/generalforsamlinger/" className="hover:underline text-blue-700">
Generalforsamlingen
</Link>{" "}
er den høyeste besluttende myndighet i Online.
</Text>
<Text className="mt-3">
Det betyr at den største beslutningsevnen ligger i hendene på alle våre kjære Onlinere.
</Text>
</div>
</div>
</div>
<div className="flex flex-col items-center text-center mt-7">
<Title size={"lg"} element="h2" className="border-b border-gray-500 pb-1 w-full mb-4">
Komiteer
</Title>
<Text className="md:w-2/3 lg:w-1/2 sm:mx-12 text-left md:text-center">
Foreningen har et bredt spekter av komiteer som tar for seg alt fra det sosiale til det faglige. Her er en
oversikt over noen av komiteene som bidrar til å skape et levende studentmiljø for informatikkstudentene:
</Text>
<GroupList groups={committees} />
</div>
<div className="flex flex-col items-center text-center mt-7">
<Title size={"lg"} element="h2" className="border-b border-gray-500 pb-1 w-full mb-4">
Nodekomiteer
</Title>
<Text className="md:w-2/3 lg:w-1/2 sm:mx-12 text-left md:text-center">
Nodekomiteer er underkomiteer til kjernekomiteene i Online, eller direkte underlagt Hovedstyret.
</Text>
<GroupList groups={nodeCommittees} />
</div>
<div className="flex flex-col gap-24">
<WhoAreWeCard />
<Statistics />
<OurGoalsCard />
<Structure />
</div>
)
}

type GroupListProps = {
groups: Group[]
}

const GroupList: FC<GroupListProps> = ({ groups }: GroupListProps) => {
return (
<ul className="grid grid-cols-1 md:grid-cols-2 gap-x-16 gap-y-6 sm:px-12 pt-8">
{groups.map(
(group) =>
group.imageUrl && (
<Card key={group.slug} imageUrl={group.imageUrl} title={group.abbreviation} description={group.about} />
)
)}
</ul>
)
}

type CardProps = {
imageUrl: string | null
title: string
description: string
}

const Card: FC<CardProps> = ({ imageUrl, title, description }: CardProps) => {
return (
<li className="flex items-center text-left">
<div className="w-[150px] mr-4 shrink-0">
{imageUrl ? (
<Image
src={imageUrl}
alt={title}
className="object-contain h-auto rounded-full dark:invert"
width={150}
height={150}
/>
) : (
<OnlineIcon width={150} height={150} />
)}
</div>
<div className="flex-1">
<Title>{title}</Title>
<Text className="line-clamp-4">{description}</Text>
</div>
</li>
)
}
21 changes: 21 additions & 0 deletions packages/ui/src/atoms/Divider/Divider.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import type React from "react"
import { forwardRef } from "react"
import { cn } from "../../utils"

interface DividerProps extends React.HTMLAttributes<HTMLDivElement> {
vertical?: boolean
}

export const Divider = forwardRef<HTMLDivElement, DividerProps>(({ vertical, ...props }, ref) => {
return (
<div
ref={ref}
{...props}
className={cn(
"border-gray-200",
vertical ? "w-2 border-r-1 mr-2" : "w-full border-t-1 h-2 mx-1 self-center",
props.className
)}
/>
)
})
45 changes: 45 additions & 0 deletions packages/ui/src/atoms/ImageCard/ImageCard.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
import { forwardRef } from "react"
import { cn } from "../../utils"

interface ImageCardProps extends React.HTMLAttributes<HTMLDivElement> {
imagePosition: "left" | "right" | "top"
image: string
alt: string
children?: React.ReactNode
}
export const ImageCard = forwardRef<HTMLDivElement, ImageCardProps>(
({ image, imagePosition, alt, children, ...props }, ref) => {
return (
<div
ref={ref}
{...props}
className={cn(
props.className,
"relative flex overflow-hidden rounded-2xl max-sm:flex-col ",
imagePosition === "left" ? " justify-end" : "justify-start"
)}
>
<img
src={image}
alt={alt}
className={cn(
"object-cover max-sm:h-44 max-sm:w-full",
imagePosition === "right" && "sm:hidden",
imagePosition === "left" &&
"sm:absolute sm:left-0 sm:top-0 sm:h-full sm:w-2/5 sm:[clip-path:polygon(0%_0%,_100%_0%,_85%_100%,_0%_100%)]"
)}
/>
<div className="sm:w-3/5">{children}</div>
{imagePosition === "right" && (
<img
src={image}
alt={alt}
className={cn(
"absolute right-0 top-0 h-full w-2/5 object-cover max-sm:hidden [clip-path:polygon(15%_0%,_100%_0%,_100%_100%,_0%_100%)]"
)}
/>
)}
</div>
)
}
)
2 changes: 2 additions & 0 deletions packages/ui/src/atoms/Typography/Title.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,8 @@ const title = cva("text-inherit font-title font-bold", {
md: "text-xl font-semibold",
lg: "text-2xl font-semibold",
xl: "text-3xl",
xxl: "text-4xl",
xxxl: "text-5xl",
},
},
defaultVariants: {
Expand Down
Loading
Loading