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
54 changes: 54 additions & 0 deletions src/app/chi-siamo/page.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
import type { Metadata } from "next"
import { AnswerSection } from "@/components/chi-siamo/answer-section"
import { HistorySection } from "@/components/chi-siamo/history-section"
import { NumbersSection } from "@/components/chi-siamo/numbers-section"
import { PathSection } from "@/components/chi-siamo/path-section"
import { ProblemSection } from "@/components/chi-siamo/problem-section"
import { SupportSection } from "@/components/chi-siamo/support-section"
import { VisionSection } from "@/components/chi-siamo/vision-section"
import {
ChiSiamoAnswerShapes,
ChiSiamoHistoryShapes,
ChiSiamoNumbersShapes,
ChiSiamoPathShapes,
ChiSiamoProblemShapes,
ChiSiamoVisionShapes,
} from "./shapes"

export const metadata: Metadata = {
title: "Su di noi",
description: "Rendiamo le informazioni sul PoliMi più accessibili, comprensibili e facili da trovare.",
}

export default function ChiSiamoPage() {
return (
// Narrower content column (1200px, as in Figma): `page-container` caps its padding on this variable
<main className="flex w-full flex-col gap-section pb-section [--container-page:75rem]">
<div className="relative">
<ChiSiamoVisionShapes />
<VisionSection />
</div>
<div className="relative">
<ChiSiamoProblemShapes />
<ProblemSection />
</div>
<div className="relative">
<ChiSiamoAnswerShapes />
<AnswerSection />
</div>
<div className="relative">
<ChiSiamoPathShapes />
<PathSection />
</div>
<div className="relative">
<ChiSiamoNumbersShapes />
<NumbersSection />
</div>
<div className="relative">
<ChiSiamoHistoryShapes />
<HistorySection />
</div>
<SupportSection />
</main>
)
}
88 changes: 88 additions & 0 deletions src/app/chi-siamo/shapes.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
import { Shape, ShapeLayer } from "@/components/shapes"

/**
* `left` offsets are `calc(50% + Npx)`, relative to the horizontal center of
* the 1728px (desktop) Figma frame — see src/components/home/shapes.tsx.
*
* Each section's shapes are `top`-anchored to that section's heading (the
* section's top edge): `top = figmaY - figmaHeadingY`. The vision shapes are
* instead anchored to the page top, since that section starts at the top of
* `<main>`, where page y = Figma y.
*
* The Figma file only has a desktop frame for this page, so there are no
* mobile shapes yet.
*/

export function ChiSiamoVisionShapes() {
return (
<ShapeLayer>
{/* Desktop Shapes */}
<Shape variant="big-teal" className="top-0 left-[calc(50%-1314px)] hidden size-243.5 md:block" />
<Shape variant="big-teal" className="top-0 left-[calc(50%+340px)] hidden size-243.5 md:block" />
<Shape
variant="looper"
className="-top-108.5 left-[calc(50%-1428px)] hidden h-[1881.13px] w-[1918.09px] md:block"
/>
<Shape
variant="looper"
className="-top-144.75 left-[calc(50%-472px)] hidden h-[2145.12px] w-[2164.32px] md:block"
/>
</ShapeLayer>
)
}

export function ChiSiamoProblemShapes() {
return (
<ShapeLayer>
{/* Desktop Shapes */}
<Shape
variant="looper"
className="-top-60.75 left-[calc(50%-959px)] hidden h-[1881.13px] w-[1918.09px] md:block"
/>
<Shape variant="big-teal" className="top-57 left-[calc(50%-487px)] hidden size-243.5 md:block" />
</ShapeLayer>
)
}

export function ChiSiamoAnswerShapes() {
return (
<ShapeLayer>
{/* Desktop Shapes */}
<Shape variant="big-blue" className="top-61.75 left-[calc(50%-294px)] hidden size-144.5 md:block" />
</ShapeLayer>
)
}

export function ChiSiamoPathShapes() {
return (
<ShapeLayer>
{/* Desktop Shapes */}
<Shape variant="big-blue" className="top-81.25 left-[calc(50%-50px)] hidden size-115 md:block" />
<Shape variant="big-teal" className="top-74.5 left-[calc(50%-801px)] hidden size-243.5 md:block" />
<Shape variant="looper" className="top-42 left-[calc(50%-1136px)] hidden h-[1560.48px] w-[1609.71px] md:block" />
</ShapeLayer>
)
}

export function ChiSiamoNumbersShapes() {
return (
<ShapeLayer>
{/* Desktop Shapes */}
<Shape
variant="big-blue"
className="top-[691.05px] left-[calc(50%-767.95px)] hidden size-115 rotate-[21.84deg] md:block"
/>
<Shape variant="big-teal" className="top-219.5 left-[calc(50%-41px)] hidden h-238 w-245.5 md:block" />
<Shape variant="looper" className="top-186 left-[calc(50%-395px)] hidden h-[1560.48px] w-[1609.71px] md:block" />
</ShapeLayer>
)
}

export function ChiSiamoHistoryShapes() {
return (
<ShapeLayer>
{/* Desktop Shapes */}
<Shape variant="big-blue" className="top-73.75 left-[calc(50%+42px)] hidden size-[770.77px] md:block" />
</ShapeLayer>
)
}
49 changes: 49 additions & 0 deletions src/components/chi-siamo/answer-section.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
import { FiAward, FiBookOpen, FiUsers } from "react-icons/fi"
import { CardIcon } from "@/components/card-icon"

const cards = [
{
title: "Community",
description:
"Gruppi Telegram e WhatsApp per corsi, scaglioni, sedi e interessi. Una rete moderata ogni giorno da admin volontari.",
icon: FiUsers,
},
{
title: "Strumenti",
description:
"Strumenti gratuiti e open source: graduatorie e simulazioni TOL, bot per trovare il tuo gruppo, appunti e temi d’esame.",
icon: FiBookOpen,
},
{
title: "Eventi",
description: "Eventi per incontrarsi e fare community. Collaborazioni che portano valore concreto agli studenti.",
icon: FiAward,
},
] as const

export function AnswerSection() {
return (
<section id="cosa-facciamo" className="page-container flex scroll-mt-32 flex-col gap-block">
<div className="flex flex-col gap-4">
<h2 className="typo-headline-medium md:typo-display-medium bg-linear-to-b from-text-primary to-text-secondary bg-clip-text text-transparent">
La nostra risposta
</h2>
<p className="typo-body-large sm:typo-headline-extrasmall max-w-200 text-pretty">
Costruiamo e manteniamo la rete di comunicazione studentesca del Politecnico di Milano.
</p>
</div>

<div className="grid gap-6 lg:grid-cols-3">
{cards.map((card) => (
<CardIcon
key={card.title}
{...card}
size="compact"
align="start"
className="h-full p-0 [&_h3]:text-balance"
/>
))}
</div>
</section>
)
}
44 changes: 44 additions & 0 deletions src/components/chi-siamo/history-section.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
import Link from "next/link"
import { FiArrowUpRight, FiClock, FiUsers } from "react-icons/fi"
import { Glass } from "@/components/glass"
import { GradientIcon } from "@/components/gradient-icon"
import { Button } from "@/components/ui/button"

const blocks = [
{
title: "Da dove veniamo",
description: "Dal primo gruppo Telegram, nel 2016, a una rete costruita dagli studenti, per gli studenti.",
icon: FiClock,
cta: "La nostra storia",
href: "/storia",
},
{
title: "Come siamo organizzati",
icon: FiUsers,
description: "Direttivo, team operativi, admin e soci. Guarda come funziona la macchina dall'interno.",
cta: "La nostra struttura",
href: "/about",
},
] as const

export function HistorySection() {
return (
<section className="page-container grid gap-6 md:grid-cols-2">
{blocks.map((block) => (
<Glass key={block.title} className="flex flex-col items-start gap-6 rounded-rectangles p-6 sm:p-8">
<GradientIcon icon={block.icon} className="size-10" />
<h2 className="typo-headline-medium text-balance bg-linear-to-b from-text-primary to-text-secondary bg-clip-text text-transparent">
{block.title}
</h2>
<p className="typo-body-large text-pretty">{block.description}</p>
<Button variant="primary" size="lg" className="mt-auto w-fit" asChild>
<Link href={block.href} className="flex items-center gap-2">
{block.cta}
<FiArrowUpRight aria-hidden />
</Link>
</Button>
</Glass>
))}
</section>
)
}
50 changes: 50 additions & 0 deletions src/components/chi-siamo/numbers-section.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
import { FiBook, FiBookOpen, FiHeadphones, FiSend, FiUser, FiUsers } from "react-icons/fi"
import { GradientIcon } from "@/components/gradient-icon"
import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card"

const stats = [
{ value: "500+", label: "gruppi Telegram e WhatsApp attivi", icon: FiSend },
{ value: "30+", label: "corsi di laurea coperti", icon: FiBook },
{ value: "45k+", label: "studenti raggiunti ogni anno", icon: FiUser },
{ value: "100+", label: "admin volontari su tutte le sedi", icon: FiUsers },
{ value: "5", label: "team operativi", icon: FiHeadphones },
{ value: "100%", label: "progetti tecnici rilasciati open source", icon: FiBookOpen },
] as const

export function NumbersSection() {
return (
<section className="page-container flex flex-col gap-block">
<div className="flex flex-col gap-4">
<h2 className="typo-headline-medium md:typo-display-medium bg-linear-to-b from-text-primary to-text-secondary bg-clip-text text-transparent">
I numeri
</h2>
<p className="typo-body-large sm:typo-headline-extrasmall max-w-160 text-pretty">
Un network in continua crescita, costruito dagli studenti, per gli studenti.
</p>
</div>

<div className="flex flex-col gap-8">
<div className="grid gap-6 sm:grid-cols-2 xl:grid-cols-3">
{stats.map((stat) => (
<Card key={stat.label} className="h-auto w-full gap-4 p-6 sm:p-8">
<CardHeader className="flex flex-row items-center justify-between gap-4">
<CardTitle
gradient={false}
className="typo-display-small sm:typo-display-medium text-blue-secondary tabular-nums"
>
{stat.value}
</CardTitle>
<GradientIcon icon={stat.icon} className="size-8 shrink-0" />
</CardHeader>
<CardContent className="typo-body-large text-pretty">{stat.label}</CardContent>
</Card>
))}
</div>

<p className="typo-body-large text-center">
Dal <span className="text-blue-secondary">2016</span> al fianco degli studenti del PoliMi
</p>
</div>
</section>
)
}
56 changes: 56 additions & 0 deletions src/components/chi-siamo/path-section.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
import { FiBook, FiClipboard, FiFileText, FiGift, FiUser, FiUserCheck } from "react-icons/fi"
import { Glass } from "@/components/glass"
import { GradientIcon } from "@/components/gradient-icon"
import { cn } from "@/lib/utils"

const steps = [
{ title: "TOL", description: "Simulazioni, guide e consigli per affrontarlo al meglio.", icon: FiBook },
{ title: "Ammissione", description: "Graduatorie, scadenze e tutto ciò che serve per iniziare.", icon: FiClipboard },
{ title: "Primo anno", description: "Orientamento, gruppi, risorse e supporto tra studenti.", icon: FiUser },
{ title: "Esami", description: "Appunti, temi, consigli e strumenti per prepararti meglio.", icon: FiFileText },
{
title: "Scelta del percorso",
description: "Informazioni chiare per decidere il tuo futuro al PoliMi.",
icon: FiUserCheck,
},
{ title: "Laurea", description: "Fino al traguardo, insieme.", icon: FiGift },
] as const

export function PathSection() {
return (
<section className="page-container flex flex-col gap-block">
<h2 className="typo-headline-medium md:typo-display-medium text-balance bg-linear-to-b from-text-primary to-text-secondary bg-clip-text text-center text-transparent md:text-start">
Il tuo percorso, sempre al tuo fianco
</h2>

<ol className="grid gap-10 lg:grid-cols-6 lg:gap-6">
{steps.map((step, index) => (
<li
key={step.title}
className={cn(
"relative flex items-start gap-4 lg:flex-col lg:items-center lg:text-center",
index < steps.length - 1 &&
"after:-bottom-10 after:absolute after:top-21 after:left-10.25 after:w-0.5 after:bg-blue-primary/40 after:content-[''] lg:after:top-10.25 lg:after:bottom-auto lg:after:left-[calc(50%+2.625rem)] lg:after:h-0.5 lg:after:w-[calc(100%-3.75rem)]"
)}
>
<Glass className="flex size-21 shrink-0 items-center justify-center rounded-rectangles border-white/50 bg-background-blur p-0">
<GradientIcon icon={step.icon} className="size-14" />
</Glass>
<div className="flex flex-col gap-2 pt-2 lg:pt-0">
<h3 className="typo-title-large text-balance bg-linear-to-b from-blue-secondary to-blue-primary bg-clip-text text-transparent">
{step.title}
</h3>
<p className="typo-body-medium">{step.description}</p>
</div>
</li>
))}
</ol>

<p className="typo-body-large sm:typo-headline-extrasmall mx-auto max-w-215 text-balance text-center">
Dalla prima simulazione del TOL fino alla laurea, ogni studente ha sempre{" "}
<span className="text-blue-secondary">una risposta</span> a portata di mano e{" "}
<span className="text-blue-secondary">qualcuno</span> a cui chiederla.
</p>
</section>
)
}
31 changes: 31 additions & 0 deletions src/components/chi-siamo/problem-section.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
import { FiEdit, FiFileText, FiUsers } from "react-icons/fi"
import { Card, CardAction, CardContent } from "@/components/ui/card"

const questions = [
{ text: "Dove trovo il gruppo del mio corso?", icon: FiUsers },
{ text: "Come funziona il piano degli studi?", icon: FiFileText },
{ text: "Cosa succede se non passo l’OFA di inglese?", icon: FiEdit },
] as const

export function ProblemSection() {
return (
<section className="page-container grid items-center gap-10 lg:grid-cols-2 lg:gap-16">
<div className="flex min-w-0 flex-col gap-6">
<h2 className="typo-headline-medium sm:typo-display-medium text-balance bg-linear-to-b from-text-primary to-text-secondary bg-clip-text text-transparent">
Il problema
</h2>
<p className="typo-body-large sm:typo-headline-extrasmall text-pretty">
Il PoliMi è complesso. Le informazioni non dovrebbero esserlo.
</p>
</div>
<div className="grid min-w-0 gap-4">
{questions.map((question) => (
<Card key={question.text} className="h-auto w-full flex-row items-center justify-between gap-6 p-6">
<CardContent className="typo-body-large text-pretty">{question.text}</CardContent>
<CardAction icon={question.icon} className="shrink-0" />
</Card>
))}
</div>
</section>
)
}
Loading
Loading