Skip to content

Commit

Permalink
WIP Event detail page (#886)
Browse files Browse the repository at this point in the history
- Continue work on event detail page
- Introduce fraunces font on h1 and h2 headings

---------

Co-authored-by: henrikskog <[email protected]>
  • Loading branch information
brage-andreas and henrikskog authored May 2, 2024
1 parent 48a67ee commit 78be80a
Show file tree
Hide file tree
Showing 9 changed files with 109 additions and 49 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ node_modules/
.next
# environment variables
.env
.envrc
.env.production
.envrc
!.env.example
Expand Down
47 changes: 32 additions & 15 deletions apps/web/src/app/events/[id]/page.tsx
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
"use client"

import { trpc } from "@/utils/trpc/client"
import type { Attendance, AttendancePool, Committee, Event } from "@dotkomonline/types"
import type { Attendance, AttendancePool, Committee, Company, Event } from "@dotkomonline/types"
import type { Session } from "next-auth"
import { useSession } from "next-auth/react"
import type { FC } from "react"
import { AttendanceBox } from "../components/AttendanceBox"
import { EventHeader } from "../components/EventHeader"
import { EventInfoBox } from "../components/EventInfoBox"
import { OrganizerBox } from "../components/OrganizerBox"
import TicketButton from "../components/TicketButton"
Expand Down Expand Up @@ -39,46 +40,62 @@ const EventDetailPageInner = ({ id }: { id: string }) => {
pools={event.pools}
event={event.event}
committees={event.eventCommittees}
companies={event.eventCompanies}
/>
)
}

return <EventDetailWithoutAttendancePage event={event.event} committees={event.eventCommittees} />
return (
<EventDetailWithoutAttendancePage
user={session?.data?.user}
event={event.event}
committees={event.eventCommittees}
companies={event.eventCompanies}
/>
)
}

interface WithoutAttendanceProps {
interface EventDetailProps {
user: NonNullable<Session["user"]> | undefined
event: Event
committees: Committee[]
companies: Company[]
}
const EventDetailWithoutAttendancePage: FC<WithoutAttendanceProps> = ({ event, committees }) => {
const EventDetailWithoutAttendancePage: FC<EventDetailProps> = ({ user, event, committees, companies }) => {
return (
<div>
<div className="mt-8 flex flex-col gap-16">
<EventHeader event={event} />
<div className="flex w-full">
<EventInfoBox event={event} />
<EventInfoBox event={event} committees={committees} companies={companies} />
</div>
</div>
)
}

interface WithAttendanceProps {
user?: Session["user"]
interface EventDetailWithAttendanceProps extends EventDetailProps {
attendance: Attendance
pools: AttendancePool[]
event: Event
committees: Committee[]
}

const EventDetailWithAttendancePage: FC<WithAttendanceProps> = ({ user, attendance, pools, event, committees }) => {
const EventDetailWithAttendancePage: FC<EventDetailWithAttendanceProps> = ({
user,
attendance,
pools,
event,
committees,
companies,
}) => {
const { data: attendee } = useGetAttendee({
attendanceId: attendance.id,
userId: user?.id,
})

return (
<div>
<div className="flex w-full">
<EventInfoBox event={event} />
<div className="flex flex-1 flex-col">
<div className="mt-8 flex flex-col gap-8">
<EventHeader event={event} />
<div className="flex w-full flex-col md:flex-row">
<EventInfoBox event={event} committees={committees} companies={companies} />
<div className="flex-1 flex-col">
<AttendanceBox sessionUser={user} attendance={attendance} pools={pools} event={event} />
{attendee && user && <TicketButton userId={user.id} />}
{committees.length && <OrganizerBox committees={committees} />}
Expand Down
26 changes: 26 additions & 0 deletions apps/web/src/app/events/components/EventHeader.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
import type { Event } from "@dotkomonline/types"
import Image from "next/image"
import type { FC } from "react"

interface Props {
event: Event
}

export const EventHeader: FC<Props> = ({ event }) => {
const imageUrl = event.imageUrl || "https://via.placeholder.com/1920x1080"

return (
<div className="flex flex-col gap-8">
<Image
src={imageUrl}
alt="Banner"
width="0"
height="0"
sizes="100%"
style={{ objectFit: "cover" }}
className="h-[30rem] w-full rounded-2xl"
/>
<h1>{event.title}</h1>
</div>
)
}
23 changes: 18 additions & 5 deletions apps/web/src/app/events/components/EventInfoBox.tsx
Original file line number Diff line number Diff line change
@@ -1,15 +1,28 @@
import type { Event } from "@dotkomonline/types"
import type { Committee, Company, Event } from "@dotkomonline/types"
import Image from "next/image"
import type { FC } from "react"

interface Props {
event: Event
committees: Committee[]
companies: Company[]
}

export const EventInfoBox: FC<Props> = ({ event }) => {
const mapToImageAndName = (item: Committee | Company) => (
<div key={item.name} className="flex flex-row gap-2 items-center">
{item.image && <Image src={item.image} alt={item.name} width={25} height={25} />}
<p>{item.name}</p>
</div>
)

export const EventInfoBox: FC<Props> = ({ event, committees, companies }) => {
const committeeList = committees.map(mapToImageAndName)
const companyList = companies.map(mapToImageAndName)

return (
<div className="mr-10 w-[60%]">
<h2>{event.title}</h2>
<p>{event.description}</p>
<div className="mr-10 w-full flex flex-col gap-8 md:w-[60%]">
<div className="flex flex-row gap-8">{[...committeeList, ...companyList]}</div>
<p className="bg-slate-2 p-5 text-[18px] rounded-2xl">{event.description}</p>
</div>
)
}
5 changes: 3 additions & 2 deletions apps/web/src/app/layout.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import MainLayout from "@/components/layout/MainLayout"
import { QueryProvider } from "@/utils/trpc/QueryProvider"
import "@dotkomonline/config/tailwind.css"
import { cn } from "@dotkomonline/ui"
import { Poppins } from "next/font/google"
import { Fraunces, Poppins } from "next/font/google"
import type { PropsWithChildren } from "react"
import "../styles/globals.css"

Expand All @@ -12,11 +12,12 @@ export const metadata = {
}

const poppins = Poppins({ subsets: ["latin"], weight: ["400", "500", "600", "700"], variable: "--font-poppins" })
const fraunces = Fraunces({ subsets: ["latin"], weight: ["400", "500", "600", "700"], variable: "--font-fraunces" })

export default function RootLayout({ children }: PropsWithChildren) {
return (
<html lang="en">
<body className={cn(poppins.variable, "h-full w-full")}>
<body className={cn(fraunces.variable, poppins.variable, "h-full w-full")}>
<QueryProvider>
<MainLayout>{children}</MainLayout>
</QueryProvider>
Expand Down
1 change: 1 addition & 0 deletions packages/config/tailwind-preset.js
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ module.exports = {
},
extend: {
fontFamily: {
fraunces: ["var(--font-fraunces, 'Fraunces')"],
poppins: ["var(--font-poppins, 'Poppins')"],
mono: ["Roboto Mono", "monospace"],
sans: ['"Inter var"', "sans-serif"],
Expand Down
12 changes: 2 additions & 10 deletions packages/config/typography.css
Original file line number Diff line number Diff line change
@@ -1,30 +1,22 @@

@tailwind base;
@tailwind components;
@tailwind utilities;

/* Reason for important: https://github.com/withastro/astro/issues/3844 */
@layer base {
h1 {
@apply scroll-m-20 text-4xl font-extrabold tracking-tight lg:text-5xl !important;
@apply font-fraunces scroll-m-20 text-4xl font-extrabold tracking-tight lg:text-5xl !important;
}

h2 {
@apply border-b-slate-7 mt-10 scroll-m-20 border-b pb-1 text-3xl font-semibold tracking-tight transition-colors first:mt-0 !important;
@apply font-fraunces border-b-slate-7 mt-10 scroll-m-20 border-b pb-1 text-3xl font-semibold tracking-tight transition-colors first:mt-0 !important;
}

h3 {
@apply mt-8 scroll-m-20 text-2xl font-semibold tracking-tight !important;
}

h4 {
@apply mt-8 scroll-m-20 text-xl font-semibold tracking-tight !important;
}

blockquote {
@apply border-slate-7 text-slate-1 mt-6 border-l-2 pl-6 italic !important;
}

code {
@apply bg-slate-2 text-slate-11 relative rounded px-[0.3rem] py-[0.2rem] font-mono text-sm font-semibold !important;
}
Expand Down
5 changes: 3 additions & 2 deletions packages/core/src/modules/core.ts
Original file line number Diff line number Diff line change
Expand Up @@ -187,15 +187,16 @@ export const createServiceLayer = async ({ db }: ServerLayerOptions) => {
attendeeService
)

const eventCompanyService: EventCompanyService = new EventCompanyServiceImpl(eventCompanyRepository)
const eventService: EventService = new EventServiceImpl(
eventRepository,
attendanceService,
attendancePoolService,
eventCommitteeService
eventCommitteeService,
eventCompanyService
)
const companyService: CompanyService = new CompanyServiceImpl(companyRepository)
const companyEventService: CompanyEventService = new CompanyEventServiceImpl(companyEventRepository)
const eventCompanyService: EventCompanyService = new EventCompanyServiceImpl(eventCompanyRepository)
const productService: ProductService = new ProductServiceImpl(productRepository)
const paymentService: PaymentService = new PaymentServiceImpl(
paymentRepository,
Expand Down
38 changes: 23 additions & 15 deletions packages/core/src/modules/event/event-service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import type {
AttendancePool,
AttendanceWrite,
Committee,
Company,
Event,
EventId,
EventWrite,
Expand All @@ -12,6 +13,7 @@ import { AttendanceNotFound } from "../attendance/attendance-error"
import type { AttendancePoolService } from "../attendance/attendance-pool-service"
import type { AttendanceService } from "../attendance/attendance-service"
import type { EventCommitteeService } from "./event-committee-service"
import type { EventCompanyService } from "./event-company-service.js"
import { EventNotFoundError } from "./event-error"
import type { EventRepository } from "./event-repository.js"

Expand All @@ -28,13 +30,15 @@ type WebEventDetail =
hasAttendance: false
event: Event
eventCommittees: Committee[]
eventCompanies: Company[]
}
| {
hasAttendance: true
event: Event
eventCommittees: Committee[]
attendance: Attendance
pools: AttendancePool[]
eventCompanies: Company[]
}

export interface EventService {
Expand All @@ -54,7 +58,8 @@ export class EventServiceImpl implements EventService {
private readonly eventRepository: EventRepository,
private readonly attendanceService: AttendanceService,
private readonly attendancePoolService: AttendancePoolService,
private readonly eventCommitteeService: EventCommitteeService
private readonly eventCommitteeService: EventCommitteeService,
private readonly eventCompanyService: EventCompanyService
) {}

async addAttendance(eventId: EventId, obj: AttendanceWrite) {
Expand Down Expand Up @@ -135,28 +140,31 @@ export class EventServiceImpl implements EventService {
async getWebDetail(id: EventId): Promise<WebEventDetail> {
const event = await this.getEventById(id)
const eventCommittees = await this.eventCommitteeService.getCommitteesForEvent(event.id)
const eventCompanies = await this.eventCompanyService.getCompaniesByEventId(event.id, 999)

if (event.attendanceId !== null) {
const attendance = await this.attendanceService.getById(event.attendanceId)
if (!attendance) {
throw new Error("Attendance not found")
}

const pools = await this.attendancePoolService.getByAttendanceId(attendance.id)

if (!event.attendanceId) {
return {
hasAttendance: true,
hasAttendance: false,
event,
eventCommittees,
attendance,
pools,
eventCommittees: eventCommittees,
eventCompanies,
}
}

const attendance = await this.attendanceService.getById(event.attendanceId)
if (!attendance) {
throw new Error("Attendance not found")
}

const pools = await this.attendancePoolService.getByAttendanceId(attendance.id)

return {
hasAttendance: false,
hasAttendance: true,
event,
eventCommittees: eventCommittees,
eventCommittees,
attendance,
pools,
eventCompanies,
}
}
}

0 comments on commit 78be80a

Please sign in to comment.