diff --git a/src/app/matricole/page.tsx b/src/app/matricole/page.tsx index 38f6395..9d1e36d 100644 --- a/src/app/matricole/page.tsx +++ b/src/app/matricole/page.tsx @@ -1,5 +1,6 @@ import type { Metadata } from "next" import { FAQsPage } from "@/components/matricole/faqs" +import { MatricoleGuides } from "@/components/matricole/guides" import { MatricoleIntro } from "@/components/matricole/intro" export const metadata: Metadata = { @@ -11,6 +12,7 @@ export default function MatricolePage() { return (
+
) diff --git a/src/components/card-group/header.tsx b/src/components/card-group/header.tsx new file mode 100644 index 0000000..a8fd10d --- /dev/null +++ b/src/components/card-group/header.tsx @@ -0,0 +1,26 @@ +import { cn } from "@/lib/utils" +import { GradientIcon } from "../gradient-icon" +import type { CardGroupProps } from "./types" + +export function CardGroupHeader({ + icon, + title, + description, + horizontal, +}: Pick) { + return ( +
+
+ {icon && } +

+ {title} +

+
+ {description && ( +

+ {description} +

+ )} +
+ ) +} diff --git a/src/components/card-group/index.tsx b/src/components/card-group/index.tsx new file mode 100644 index 0000000..84c994a --- /dev/null +++ b/src/components/card-group/index.tsx @@ -0,0 +1,22 @@ +import { Glass } from "@/components/glass" +import { cn } from "@/lib/utils" +import { CardGroupHeader } from "./header" +import type { CardGroupProps } from "./types" + +export function CardGroup({ icon, title, description, children, horizontal = false, className }: CardGroupProps) { + return ( + + {horizontal ? ( +
+ +
{children}
+
+ ) : ( + <> + +
{children}
+ + )} +
+ ) +} diff --git a/src/components/card-group/types.ts b/src/components/card-group/types.ts new file mode 100644 index 0000000..2ca0cf6 --- /dev/null +++ b/src/components/card-group/types.ts @@ -0,0 +1,11 @@ +import type { ReactNode } from "react" +import type { GradientIconType } from "../gradient-icon" + +export type CardGroupProps = { + icon?: GradientIconType + title: string + description?: string + children: ReactNode + horizontal?: boolean + className?: string +} diff --git a/src/components/card-icon/classes.ts b/src/components/card-icon/classes.ts index fb4256f..801eb48 100644 --- a/src/components/card-icon/classes.ts +++ b/src/components/card-icon/classes.ts @@ -6,6 +6,7 @@ export const ICON_SIZE_CLASSES: SizeClassMap = { sm: "h-14 w-14", md: "h-32 w-32", lg: "h-44 w-44", + inline: "h-6 w-6", } export const CARD_PADDING_WITHOUT_DESCRIPTION: SizeClassMap = { @@ -14,6 +15,7 @@ export const CARD_PADDING_WITHOUT_DESCRIPTION: SizeClassMap = { sm: "px-8 py-4", md: "p-8", lg: "p-8", + inline: "p-6", } export const CARD_PADDING_WITH_DESCRIPTION: SizeClassMap = { @@ -22,6 +24,7 @@ export const CARD_PADDING_WITH_DESCRIPTION: SizeClassMap = { sm: "p-8", md: "p-8", lg: "p-8", + inline: "p-6", } export const CONTENT_GAP_CLASSES: SizeClassMap = { @@ -30,6 +33,7 @@ export const CONTENT_GAP_CLASSES: SizeClassMap = { sm: "gap-2", md: "gap-6", lg: "gap-6", + inline: "gap-4", } export const TITLE_SIZE_CLASSES: SizeClassMap = { @@ -38,4 +42,14 @@ export const TITLE_SIZE_CLASSES: SizeClassMap = { sm: "typo-headline-medium", md: "typo-headline-medium", lg: "typo-headline-medium", + inline: "typo-title-large", +} + +export const INLINE_CONTAINER_SIZE_CLASSES: SizeClassMap = { + compact: "h-12 w-12", + xs: "h-10 w-10", + sm: "h-12 w-12", + md: "h-14 w-14", + lg: "h-16 w-16", + inline: "h-10 w-10", } diff --git a/src/components/card-icon/index.tsx b/src/components/card-icon/index.tsx index 1ad086c..a38598f 100644 --- a/src/components/card-icon/index.tsx +++ b/src/components/card-icon/index.tsx @@ -3,30 +3,18 @@ import { cn } from "@/lib/utils" import { BasicCardMedia } from "./basic-card-media" import { DescriptionCardMedia } from "./description-card-media" import { CardHoverBackground } from "./hover-background" +import { InlineCardMedia } from "./inline-card-media" import type { CardIconProps } from "./types" -import { getCardPaddingClasses, getContentGapClasses, getTitleSizeClasses } from "./utils" +import { getAlignmentClasses, getCardPaddingClasses, getContentGapClasses, getTitleSizeClasses } from "./utils" 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 Root = href ? "a" : "div" const isDescriptionCard = Boolean(description) - const isStartAligned = align === "start" + const isInlineAligned = align === "inline" const isCompactDescriptionCard = isDescriptionCard && size === "compact" - const contentAlignmentClass = isDescriptionCard - ? isStartAligned - ? "items-start justify-start text-left" - : "justify-between" - : isStartAligned - ? "items-start justify-center text-left" - : "items-center justify-center text-center" - const textAlignmentClass = isDescriptionCard - ? isStartAligned - ? "items-start gap-5 text-left" - : "gap-2 text-left" - : isStartAligned - ? "items-start text-left" - : "items-center text-center" + const { contentClass, textClass, iconWrapClass } = getAlignmentClasses(align, isDescriptionCard) return ( {hoverEffect && } -
-
- {isDescriptionCard ? ( - - ) : ( - - )} + {isInlineAligned ? ( +
+
+ +

+ {title} +

+
+ {description &&

{description}

}
- -
-

+
+ {isDescriptionCard ? ( + + ) : ( + )} - > - {title} -

- {description && ( -

+ +

+

- {description} -

- )} + {title} +

+ {description && ( +

+ {description} +

+ )} +
-
+ )} ) diff --git a/src/components/card-icon/inline-card-media.tsx b/src/components/card-icon/inline-card-media.tsx new file mode 100644 index 0000000..be18ca5 --- /dev/null +++ b/src/components/card-icon/inline-card-media.tsx @@ -0,0 +1,17 @@ +import { cn } from "@/lib/utils" +import type { GradientIconType } from "../gradient-icon" +import type { ResponsiveCardSize } from "./types" +import { getIconSizeClasses, getInlineContainerClasses } from "./utils" + +export function InlineCardMedia({ icon: Icon, size }: { icon: GradientIconType; size: ResponsiveCardSize }) { + return ( +
+ +
+ ) +} diff --git a/src/components/card-icon/types.ts b/src/components/card-icon/types.ts index 54a333f..1ac84a5 100644 --- a/src/components/card-icon/types.ts +++ b/src/components/card-icon/types.ts @@ -1,8 +1,8 @@ import type { GradientIconType } from "@/components/gradient-icon" -export type CardSize = "compact" | "xs" | "sm" | "md" | "lg" +export type CardSize = "compact" | "xs" | "sm" | "md" | "lg" | "inline" export type CardBreakpoint = "base" | "sm" | "md" | "lg" -export type CardAlign = "center" | "start" +export type CardAlign = "center" | "start" | "inline" export type SizeClassMap = Record diff --git a/src/components/card-icon/utils.ts b/src/components/card-icon/utils.ts index 156adac..25b75ba 100644 --- a/src/components/card-icon/utils.ts +++ b/src/components/card-icon/utils.ts @@ -3,10 +3,11 @@ import { CARD_PADDING_WITHOUT_DESCRIPTION, CONTENT_GAP_CLASSES, ICON_SIZE_CLASSES, + INLINE_CONTAINER_SIZE_CLASSES, TITLE_SIZE_CLASSES, } from "./classes" -import type { CardBreakpoint, ResponsiveCardSize, SizeClassMap } from "./types" +import type { CardAlign, CardBreakpoint, ResponsiveCardSize, SizeClassMap } from "./types" const BREAKPOINTS: CardBreakpoint[] = ["base", "sm", "md", "lg"] @@ -61,3 +62,27 @@ export function getContentGapClasses(size: ResponsiveCardSize) { export function getTitleSizeClasses(size: ResponsiveCardSize) { return resolveResponsiveClasses(size, TITLE_SIZE_CLASSES) } + +export function getInlineContainerClasses(size: ResponsiveCardSize) { + return resolveResponsiveClasses(size, INLINE_CONTAINER_SIZE_CLASSES) +} + +export function getAlignmentClasses(align: CardAlign, hasDescription: boolean) { + return { + center: { + contentClass: hasDescription ? "justify-between" : "items-center justify-center text-center", + textClass: hasDescription ? "gap-2 text-left" : "items-center text-center", + iconWrapClass: "justify-center", + }, + start: { + contentClass: hasDescription ? "items-start justify-start text-left" : "items-start justify-center text-left", + textClass: hasDescription ? "items-start gap-5 text-left" : "items-start text-left", + iconWrapClass: "justify-start", + }, + inline: { + contentClass: "", + textClass: "", + iconWrapClass: "", + }, + }[align] +} diff --git a/src/components/matricole/constants.ts b/src/components/matricole/constants.ts new file mode 100644 index 0000000..c26dfa4 --- /dev/null +++ b/src/components/matricole/constants.ts @@ -0,0 +1,169 @@ +import { + FiBarChart2, + FiBell, + FiBook, + FiCpu, + FiDollarSign, + FiFolder, + FiHome, + FiMap, + FiMonitor, + FiRadio, + FiRefreshCw, + FiRepeat, + FiShoppingCart, + FiUserCheck, + FiUsers, +} from "react-icons/fi" +import type { AccordionListItem } from "../accordion-list/types" + +export const resources = [ + { + title: "Graduatorie", + description: "Risultati storici e soglie di accesso per i vari corsi di laurea.", + icon: FiBarChart2, + href: "https://rankings.polinetwork.org/", + }, + { + title: "Progetto TOL", + description: "Informazioni sul test di ingresso (TOL) e su come prepararsi al meglio.", + icon: FiMonitor, + href: "https://tol.polinetwork.org/", + }, +] as const + +export const guides = [ + { + title: "Guida della matricola", + description: "Dalla prima iscrizione alla vita in campus: il manuale completo per ogni nuovo studente.", + icon: FiBook, + href: "/guides", + }, + { + title: "Mappa Microonde", + description: "Dove scaldare il pranzo nei vari campus.", + icon: FiMap, + }, + { + title: "Corsi a Scelta", + description: "Consigli su come comporre il Piano di Studi.", + icon: FiBook, + }, + { + title: "News", + description: "Le ultime novità dagli studenti del Politecnico.", + icon: FiRadio, + }, + { + title: "Borsa di Studio", + description: "Requisiti e scadenze per le agevolazioni.", + icon: FiDollarSign, + }, +] as const + +export const hub = { + title: "Telegram Hub", + description: + "Unisciti alla più grande rete di studenti del Poli su Telegram. Gruppi specifici per ogni esigenza, dai libri alla ricerca della casa.", + cards: [ + { + title: "Generale", + icon: FiBell, + href: "https://t.me/PoliGruppo", + }, + { + title: "Matricole", + icon: FiUserCheck, + href: "https://t.me/polimatricole", + }, + { + title: "Ripetizioni", + icon: FiUsers, + href: "https://t.me/joinchat/l10OF3vF6fEzOTRk", + }, + { + title: "PoliBook", + icon: FiBook, + href: "https://t.me/joinchat/6nmuXXhAOr1mYTJk", + }, + { + title: "DSU", + icon: FiDollarSign, + href: "https://t.me/joinchat/4kO9DtAiTVM0NTU0", + }, + { + title: "Mercatino", + icon: FiShoppingCart, + href: "https://t.me/mercatinopolimi", + }, + { + title: "Case", + icon: FiHome, + href: "https://t.me/joinchat/jmpNOitFNFw1MzJk", + }, + { + title: "Consigli PC", + icon: FiMonitor, + href: "https://t.me/joinchat/oD7NGpl0W6VjYmI0", + }, + ], +} + +export const materiali = { + title: "Materiali", + description: + "Il più grande archivio didattico creato dagli studenti per gli studenti del Politecnico di Milano. Migliaia di appunti e temi d’esame.", + icon: FiFolder, + href: "/materials", +} + +export const techTools = { + title: "Tech Tools", + description: "Una serie di Tools sviluppati dagli studenti del Politecnico di Milano.", + icon: FiCpu, + cards: [ + { + title: "Sync Orario", + icon: FiRepeat, + href: "https://bebora.github.io/polimi-schedule-js/", + }, + { + title: "WeBeep Sync", + icon: FiRefreshCw, + href: "https://github.com/toto04/webeep-sync", + }, + ], +} + +export const accordionItems: AccordionListItem[] = [ + { + value: "item-1", + trigger: "Le lezioni della prima settimana si tengono regolarmente?", + content: + "Spesso, la prima settimana, i Professori utilizzano le ore destinate alle esercitazioni per qualche ora di lezione in più: saranno quindi i docenti a specificare come verranno utilizzate queste ore. Dunque, le esercitazioni non sono da considerarsi annullate, salvo diversa comunicazione da parte del docente o dell'esercitatore.", + }, + { + value: "item-2", + trigger: "Come faccio ad accedere ai materiali del corso?", + content: + "I materiali dei corsi sono disponibili su Beep (il portale e-learning del Politecnico). Puoi accedervi con le tue credenziali di Ateneo (codice persona e password). Ogni docente carica le proprie slide, esercizi e risorse direttamente sulla pagina del corso.", + }, + { + value: "item-3", + trigger: "Come funziona la prenotazione agli esami?", + content: + "La prenotazione agli esami avviene tramite il portale Online Services (servizionline.polimi.it). Devi prenotarti entro la scadenza indicata per ogni appello. Ricordati di verificare i prerequisiti necessari prima di iscriverti a un esame.", + }, + { + value: "item-4", + trigger: "Cos'è il codice persona e dove lo trovo?", + content: + "Il codice persona è il tuo identificativo univoco al Politecnico, composto da 6 cifre. Lo trovi nella lettera di ammissione o nella mail di benvenuto ricevuta dopo l'immatricolazione. Serve per accedere a tutti i servizi online dell'Ateneo.", + }, + { + value: "item-5", + trigger: "Come posso contattare PoliNetwork?", + content: + "Puoi contattare PoliNetwork tramite i nostri canali Telegram o attraverso il sito ufficiale. Siamo un'associazione studentesca e offriamo supporto, risorse e una community per tutti gli studenti del Politecnico.", + }, +] diff --git a/src/components/matricole/faqs.tsx b/src/components/matricole/faqs.tsx index 56d5569..9643cab 100644 --- a/src/components/matricole/faqs.tsx +++ b/src/components/matricole/faqs.tsx @@ -1,43 +1,10 @@ "use client" import AccordionList from "@/components/accordion-list" -import type { AccordionListItem } from "@/components/accordion-list/types" - -const accordionItems: AccordionListItem[] = [ - { - value: "item-1", - trigger: "Le lezioni della prima settimana si tengono regolarmente?", - content: - "Spesso, la prima settimana, i Professori utilizzano le ore destinate alle esercitazioni per qualche ora di lezione in più: saranno quindi i docenti a specificare come verranno utilizzate queste ore. Dunque, le esercitazioni non sono da considerarsi annullate, salvo diversa comunicazione da parte del docente o dell'esercitatore.", - }, - { - value: "item-2", - trigger: "Come faccio ad accedere ai materiali del corso?", - content: - "I materiali dei corsi sono disponibili su Beep (il portale e-learning del Politecnico). Puoi accedervi con le tue credenziali di Ateneo (codice persona e password). Ogni docente carica le proprie slide, esercizi e risorse direttamente sulla pagina del corso.", - }, - { - value: "item-3", - trigger: "Come funziona la prenotazione agli esami?", - content: - "La prenotazione agli esami avviene tramite il portale Online Services (servizionline.polimi.it). Devi prenotarti entro la scadenza indicata per ogni appello. Ricordati di verificare i prerequisiti necessari prima di iscriverti a un esame.", - }, - { - value: "item-4", - trigger: "Cos'è il codice persona e dove lo trovo?", - content: - "Il codice persona è il tuo identificativo univoco al Politecnico, composto da 6 cifre. Lo trovi nella lettera di ammissione o nella mail di benvenuto ricevuta dopo l'immatricolazione. Serve per accedere a tutti i servizi online dell'Ateneo.", - }, - { - value: "item-5", - trigger: "Come posso contattare PoliNetwork?", - content: - "Puoi contattare PoliNetwork tramite i nostri canali Telegram o attraverso il sito ufficiale. Siamo un'associazione studentesca e offriamo supporto, risorse e una community per tutti gli studenti del Politecnico.", - }, -] +import { accordionItems } from "./constants" export function FAQsPage() { return ( -
+

Domande Frequenti tra le Matricole

diff --git a/src/components/matricole/guides.tsx b/src/components/matricole/guides.tsx new file mode 100644 index 0000000..d952b32 --- /dev/null +++ b/src/components/matricole/guides.tsx @@ -0,0 +1,61 @@ +import { CardIcon } from "@/components/card-icon" +import { CardGroup } from "../card-group" +import { guides, hub, materiali, techTools } from "./constants" + +export function MatricoleGuides() { + return ( +
+
+

Guide e Utility

+ +
+ {/* Hidden in mobile */} + +
+ {guides.slice(1).map((guide) => ( + + ))} +
+
+ + +
+ {hub.cards.map((card) => ( + + ))} +
+
+ +
+ {/* hidden in mobile */} + + +
+ {techTools.cards.map((card) => ( + + ))} +
+
+
+
+
+ ) +} diff --git a/src/components/matricole/intro.tsx b/src/components/matricole/intro.tsx index e8fa720..a0c7363 100644 --- a/src/components/matricole/intro.tsx +++ b/src/components/matricole/intro.tsx @@ -1,22 +1,9 @@ -import { FiBarChart2, FiMonitor } from "react-icons/fi" import { CardIcon } from "@/components/card-icon" - -const resources = [ - { - title: "Graduatorie", - description: "Risultati storici e soglie di accesso per i vari corsi di laurea.", - icon: FiBarChart2, - }, - { - title: "Progetto TOL", - description: "Informazioni sul test di ingresso (TOL) e su come prepararsi al meglio.", - icon: FiMonitor, - }, -] as const +import { resources } from "./constants" export function MatricoleIntro() { return ( -
+

@@ -27,7 +14,7 @@ export function MatricoleIntro() {

-
+
{resources.map((resource) => ( ))}