Skip to content
Merged
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
10 changes: 10 additions & 0 deletions src/app/groups/didattica/[school]/[level]/[course]/page.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
import { GroupsResult } from "@/components/groups/groups-result"

export default async function DidatticaGroupsResultPage({
params,
}: {
params: Promise<{ school: string; level: string; course: string }>
}) {
const { school, level, course } = await params
return <GroupsResult school={school} level={level} course={course} />
}
14 changes: 14 additions & 0 deletions src/app/groups/didattica/[school]/[level]/page.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
import { CourseStep } from "@/components/groups/course-step"
import type { CourseSearchParams } from "@/components/groups/types"

export default async function DidatticaCoursePage({
params,
searchParams,
}: {
params: Promise<{ school: string; level: string }>
searchParams: Promise<CourseSearchParams>
}) {
const { school, level } = await params
const { campus, lang } = await searchParams
return <CourseStep school={school} level={level} campus={campus} lang={lang} />
}
6 changes: 6 additions & 0 deletions src/app/groups/didattica/[school]/page.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
import { LevelStep } from "@/components/groups/level-step"

export default async function DidatticaLevelPage({ params }: { params: Promise<{ school: string }> }) {
const { school } = await params
return <LevelStep school={school} />
}
5 changes: 5 additions & 0 deletions src/app/groups/didattica/page.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
import { SchoolStep } from "@/components/groups/school-step"

export default function DidatticaWizard() {
return <SchoolStep />
}
5 changes: 5 additions & 0 deletions src/app/groups/extra/page.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
import { ExtraGroups } from "@/components/groups/extra-groups"

export default function ExtraGroupsPage() {
return <ExtraGroups />
}
51 changes: 51 additions & 0 deletions src/app/groups/page.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
import { FiBook, FiStar } from "react-icons/fi"
import { CardIcon } from "@/components/card-icon"
import { GroupSearch } from "@/components/home/group-search"

const groups = [
{
title: "Gruppi Didattici",
caption: "Ingegneria, Architettura, Design, e tutti i gruppi del tuo corso di studi.",
href: "/groups/didattica",
icon: FiBook,
cta: "Inizia",
},
{
title: "Gruppi Extra",
caption: "Affitti, mercatino, eventi, hobby e tutto ciò che riguarda la vita studentesca.",
href: "/groups/extra",
icon: FiStar,
cta: "Esplora",
},
] as const

export default function Home() {
return (
<main className="w-full">
<div className="flex min-h-svh flex-col items-center gap-16 px-6 py-64 md:gap-20 md:py-49">
<div className="flex w-full flex-col items-center gap-5 text-center">
<h2 className="typo-display-large md:typo-display-extralarge w-fit bg-linear-to-b from-text-primary to-text-secondary bg-clip-text py-4 text-transparent md:py-14">
Groups
</h2>
<GroupSearch />
</div>

<div className="flex w-full flex-col items-center justify-center gap-4 md:flex-row md:gap-13">
{groups.map((group) => (
<CardIcon
key={group.title}
title={group.title}
description={group.caption}
href={group.href}
icon={group.icon}
cta={group.cta}
align="start"
className="w-full max-w-108"
size="compact"
/>
))}
</div>
</div>
</main>
)
}
32 changes: 17 additions & 15 deletions src/components/button-icon.tsx
Original file line number Diff line number Diff line change
@@ -1,25 +1,27 @@
import type { ReactNode } from "react"
import type { ComponentProps } from "react"
import type { IconType } from "react-icons"
import { Button, type ButtonSizes } from "./ui/button"
import { Button } from "./ui/button"

type ButtonIconProps = ComponentProps<typeof Button> & {
icon: IconType
text?: string
iconPosition?: "left" | "right"
iconClassName?: string
}

export function ButtonIcon({
variant = "primary",
icon: Icon,
children,
text,
iconPosition = "left",
iconClassName,
size,
}: {
variant?: "primary" | "tertiary" | "tertiaryBlur"
icon: IconType
children: ReactNode
iconPosition?: "left" | "right"
size: ButtonSizes
}) {
...props
}: ButtonIconProps) {
return (
<Button variant={variant} size={size}>
{iconPosition === "left" && <Icon />}
{children}
{iconPosition === "right" && <Icon />}
<Button size={size ?? (text ? "lg" : "icon-lg")} {...props}>
{iconPosition === "left" && <Icon className={iconClassName} />}
{text}
{iconPosition === "right" && <Icon className={iconClassName} />}
</Button>
)
}
21 changes: 15 additions & 6 deletions src/components/card-course-group.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import { cn } from "@/lib/utils"
import { Card, CardAction, CardTitle } from "./ui/card"

export const cardCourseGroupVariants = cva(
"flex h-fit w-full flex-row items-center gap-5 px-7.5 py-6.25 font-normal leading-6 tracking-[0.03125rem]",
"flex h-fit w-full min-w-0 flex-1 flex-row items-center gap-3 px-5 py-4 font-normal leading-6 tracking-[0.03125rem] sm:gap-5 sm:px-7.5 sm:py-6.25",
{
variants: {
secondary: {
Expand All @@ -27,21 +27,30 @@ export function CardCourseGroup({
hasTelegram = true,
iconTelegram: IconTelegram = LiaTelegramPlane,
secondary = false,
stacked = false,
}: {
groupName: string
hasWhatsapp?: boolean
iconWhatsApp?: IconType
hasTelegram?: boolean
iconTelegram?: IconType
stacked?: boolean
} & VariantProps<typeof cardCourseGroupVariants>) {
const actionClassName = cn("rounded-full p-3.75", secondary ? "bg-[#51A2FF]" : "bg-[#74D4FF]")
const actionClassName = cn("rounded-full p-2 sm:p-3.75", secondary ? "bg-[#51A2FF]" : "bg-[#74D4FF]")
return (
<Card className={cn(cardCourseGroupVariants({ secondary }))}>
<CardTitle gradient={false} className="typo-headline-small grow">
<Card
className={cn(
cardCourseGroupVariants({ secondary }),
stacked && "h-auto flex-col items-start md:h-fit md:flex-row md:items-center"
)}
>
<CardTitle gradient={false} className="typo-body-medium md:typo-headline-small min-w-0 grow">
{groupName}
</CardTitle>
{hasWhatsapp && <CardAction gradient={false} className={actionClassName} icon={IconWhatsApp} iconSize="md" />}
{hasTelegram && <CardAction gradient={false} className={actionClassName} icon={IconTelegram} iconSize="md" />}
<div className={cn("flex items-center gap-3", stacked ? "md:contents" : "contents")}>
{hasWhatsapp && <CardAction gradient={false} className={actionClassName} icon={IconWhatsApp} iconSize="sm" />}
{hasTelegram && <CardAction gradient={false} className={actionClassName} icon={IconTelegram} iconSize="sm" />}
</div>
</Card>
)
}
34 changes: 18 additions & 16 deletions src/components/card-course.tsx
Original file line number Diff line number Diff line change
@@ -1,16 +1,14 @@
import type { IconType } from "react-icons"
import { CiGlobe } from "react-icons/ci"
import { FaAngleRight } from "react-icons/fa6"
import { IoLocationOutline } from "react-icons/io5"
import { FiChevronRight, FiGlobe, FiMapPin } from "react-icons/fi"
import { Card, CardAction, CardContent } from "./ui/card"

export function CardCourse({
courseName,
iconLocation: IconLocation = IoLocationOutline,
iconLocation: IconLocation = FiMapPin,
location = "Milano Leonardo",
iconLanguage: IconLanguage = CiGlobe,
iconLanguage: IconLanguage = FiGlobe,
language = "ITA",
iconSelect: IconSelect = FaAngleRight,
iconSelect: IconSelect = FiChevronRight,
}: {
courseName: string
iconLocation?: IconType
Expand All @@ -20,16 +18,20 @@ export function CardCourse({
iconSelect?: IconType
}) {
return (
<Card className="typo-body-large flex h-fit w-full flex-row px-5 py-3.75 font-normal leading-6 tracking-[0.03125rem]">
<CardContent className="basis-1/3 truncate">{courseName}</CardContent>
<CardContent className="flex basis-1/3 items-center gap-1.25">
<CardAction icon={IconLocation} iconSize="xs" /> {location}
</CardContent>
<CardContent className="flex basis-1/3 items-center gap-1.25">
<CardAction icon={IconLanguage} iconSize="xs" /> {language}
</CardContent>
<CardContent className="flex items-center">
<CardAction icon={IconSelect} iconSize="xs" />
<Card className="typo-body-large flex h-fit w-full flex-row items-center gap-2 px-5 py-3.75 font-normal leading-6 tracking-[0.03125rem] sm:gap-0">
<div className="flex min-w-0 flex-1 flex-col gap-1 sm:contents">
<CardContent className="min-w-0 truncate sm:basis-1/3">{courseName}</CardContent>
<div className="flex min-w-0 items-center gap-4 sm:contents">
<CardContent className="flex min-w-0 items-center gap-1.25 sm:basis-1/3">
<CardAction icon={IconLocation} iconSize="xs" /> <span className="truncate">{location}</span>
</CardContent>
<CardContent className="flex min-w-0 items-center gap-1.25 sm:basis-1/3">
<CardAction icon={IconLanguage} iconSize="xs" /> <span className="truncate">{language}</span>
</CardContent>
</div>
</div>
<CardContent className="flex shrink-0 items-center">
<IconSelect className="h-4 w-4 text-text-primary" strokeWidth={2} />
</CardContent>
</Card>
)
Expand Down
8 changes: 8 additions & 0 deletions src/components/card-icon/index.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { Glass } from "@/components/glass"
import { buttonVariants } from "@/components/ui/button"
import { cn } from "@/lib/utils"
import { BasicCardMedia } from "./basic-card-media"
import { DescriptionCardMedia } from "./description-card-media"
Expand All @@ -10,6 +11,7 @@ import { getAlignmentClasses, getCardPaddingClasses, getContentGapClasses, getTi
export function CardIcon(props: CardIconProps) {
const { title, icon, size = "md", href, hoverEffect = false, align = "center", className } = props
const description = "description" in props ? props.description : undefined
const cta = "cta" in props ? props.cta : undefined
const Root = href ? "a" : "div"
const isDescriptionCard = Boolean(description)
const isInlineAligned = align === "inline"
Expand Down Expand Up @@ -78,6 +80,12 @@ export function CardIcon(props: CardIconProps) {
</p>
)}
</div>

{cta && (
<div className="mt-auto flex w-full justify-end pt-4">
<span className={cn(buttonVariants({ variant: "tertiary", size: "lg" }))}>{cta}</span>
</div>
)}
</div>
)}
</Root>
Expand Down
1 change: 1 addition & 0 deletions src/components/card-icon/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,5 +27,6 @@ export type SharedCardProps = {
}

export type CardIconProps = SharedCardProps & {
cta?: string
description?: ReactNode
}
12 changes: 10 additions & 2 deletions src/components/card-path-selection.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,17 @@ import type { IconType } from "react-icons"
import { BsBook } from "react-icons/bs"
import { Card, CardAction, CardContent } from "./ui/card"

export function CardPathSelection({ caption, icon: Icon = BsBook }: { caption: string; icon?: IconType }) {
export function CardPathSelection({
caption,
icon: Icon = BsBook,
className,
}: {
caption: string
icon?: IconType
className?: string
}) {
return (
<Card className="h-fit w-136 px-10 py-7.5" hoverBackground>
<Card className={`h-fit w-136 px-10 py-7.5 ${className || ""}`} hoverBackground>
<CardContent className="typo-body-large flex flex-row items-center justify-center gap-1.25 whitespace-nowrap font-normal leading-6 tracking-[0.03125rem]">
<CardAction icon={Icon} iconSize="xs" /> {caption}
</CardContent>
Expand Down
44 changes: 44 additions & 0 deletions src/components/groups/constants.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
import type { Course, Level, School } from "@/components/groups/types"

export const SCHOOLS: School[] = [
{ slug: "architettura", name: "Scuola di Architettura" },
{ slug: "design", name: "Scuola di Design" },
{ slug: "ingegneria", name: "Scuole di Ingegneria" },
]

export const LEVELS: Level[] = [
{ slug: "triennale", name: "Triennale" },
{ slug: "magistrale", name: "Magistrale" },
]

export const COURSES: Record<string, Course[]> = {
"design/triennale": [
{ slug: "design-prodotto", name: "Design del Prodotto", location: "Milano Bovisa", language: "ITA" },
{ slug: "design-comunicazione", name: "Design della Comunicazione", location: "Milano Bovisa", language: "ITA" },
{ slug: "design-moda", name: "Design della Moda", location: "Milano Bovisa", language: "ITA" },
],
}

export function getSchool(slug: string) {
return SCHOOLS.find((school) => school.slug === slug)
}

export function getLevel(slug: string) {
return LEVELS.find((level) => level.slug === slug)
}

export function getCourses(school: string, level: string) {
return COURSES[`${school}/${level}`] ?? []
}

export function getCourse(school: string, level: string, slug: string) {
return getCourses(school, level).find((course) => course.slug === slug)
}

export function getCourseFilters(school: string, level: string) {
const courses = getCourses(school, level)
return {
campuses: [...new Set(courses.map((course) => course.location))],
languages: [...new Set(courses.map((course) => course.language))],
}
}
Loading
Loading