Merge pull request #23 from Compagnia-d-Arme-del-Santo-Luca/feat/pages/activities

✨ feat: add activities page
This commit is contained in:
2026-04-11 16:39:35 +02:00
committed by GitHub
20 changed files with 314 additions and 28 deletions
Binary file not shown.

After

Width:  |  Height:  |  Size: 314 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 149 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 312 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 225 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 19 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 202 KiB

Before

Width:  |  Height:  |  Size: 2.5 MiB

After

Width:  |  Height:  |  Size: 2.5 MiB

+9
View File
@@ -7,6 +7,7 @@ import Loading from 'components/molecules/LoadingScreen/index.js'
const MainPage = React.lazy(() => import('components/pages/MainPage/index.js')) const MainPage = React.lazy(() => import('components/pages/MainPage/index.js'))
const PeoplePage = React.lazy(() => import('components/pages/PeoplePage/index.js')) const PeoplePage = React.lazy(() => import('components/pages/PeoplePage/index.js'))
const ActivitiesPage = React.lazy(() => import('components/pages/ActivitiesPage/index.js'))
const ContactPage = React.lazy(() => import('components/pages/ContactPage/index.js')) const ContactPage = React.lazy(() => import('components/pages/ContactPage/index.js'))
const PrivacyPage = React.lazy(() => import('components/pages/PrivacyPage/index.js')) const PrivacyPage = React.lazy(() => import('components/pages/PrivacyPage/index.js'))
const BusinessCardPage = React.lazy(() => import('components/pages/BusinessCardPage/index.js')) const BusinessCardPage = React.lazy(() => import('components/pages/BusinessCardPage/index.js'))
@@ -33,6 +34,14 @@ const router = createBrowserRouter([
</React.Suspense> </React.Suspense>
), ),
}, },
{
path: 'activities',
element: (
<React.Suspense fallback={<Loading />}>
<ActivitiesPage />
</React.Suspense>
),
},
{ {
path: 'contacts', path: 'contacts',
element: ( element: (
+1 -1
View File
@@ -1,6 +1,6 @@
import { Typography, TypographyProps } from '@mui/material' import { Typography, TypographyProps } from '@mui/material'
import { FC } from 'react' import { FC } from 'react'
const Header: FC<TypographyProps> = props => <Typography variant="h4" color="primary.main" component="h2" gutterBottom {...props} /> const Header: FC<TypographyProps> = props => <Typography variant="h4" component="h2" gutterBottom {...props} />
export default Header export default Header
@@ -39,13 +39,13 @@ const Description = (props: Props) => {
borderTopColor: theme.palette.primary.main, borderTopColor: theme.palette.primary.main,
p: `${theme.spacing(7)} ${theme.spacing(5)} ${theme.spacing(5.5)} ${theme.spacing(5)}`, p: `${theme.spacing(7)} ${theme.spacing(5)} ${theme.spacing(5.5)} ${theme.spacing(5)}`,
})}> })}>
<Grid container spacing={2} maxWidth="xl"> <Box maxWidth="xl">
<Grid size={4}> <Typography variant="h4" mb={3}>
<Typography variant="h4">{props.title}</Typography> {props.title}
{props.caption} </Typography>
</Grid> {props.caption}
<Grid size={8}>{props.children}</Grid> <Box mt={3}>{props.children}</Box>
</Grid> </Box>
</Box> </Box>
) )
case 'top': case 'top':
+140
View File
@@ -0,0 +1,140 @@
import React from 'react'
import { Box, BoxProps, Typography } from '@mui/material'
import SectionHeader from 'components/atoms/SectionHeader/index.js'
interface SectionProps extends BoxProps {
variant?: 'primary' | 'secondary'
title?: string
headline?: string
imageUrl?: string
imageAlt?: string
imageCaption?: React.ReactNode
children?: React.ReactNode
}
const Section: React.FC<SectionProps> = ({ variant = 'primary', imageUrl, imageAlt, imageCaption, children, ...props }) => {
return (
<Box
component="section"
sx={{
margin: 0,
px: { xs: 1, sm: 2, md: 0 },
display: 'flex',
alignItems: 'center',
justifyContent: 'center',
backgroundColor: variant === 'primary' ? 'background.default' : 'background.paper',
}}>
<Box
{...props}
sx={{
py: 5,
width: theme => theme.breakpoints.values.lg,
...props.sx,
}}>
{props.title && (
<SectionHeader
sx={[
theme => ({
paddingBottom: 3,
[theme.breakpoints.only('md')]: {
width: theme.breakpoints.values.md,
maxWidth: 'calc(100% - 2em)',
},
[theme.breakpoints.up('lg')]: {
width: theme.breakpoints.values.lg,
},
}),
theme =>
theme.applyStyles('dark', {
paddingBottom: 3,
[theme.breakpoints.only('md')]: {
width: theme.breakpoints.values.md,
maxWidth: 'calc(100% - 2em)',
},
[theme.breakpoints.up('lg')]: {
width: theme.breakpoints.values.lg,
},
}),
]}>
{props.title}
</SectionHeader>
)}
{props.headline && (
<Typography
variant="body1"
color="text.secondary"
sx={theme => ({
paddingBottom: 3,
[theme.breakpoints.only('md')]: {
width: theme.breakpoints.values.md,
maxWidth: 'calc(100% - 4em)',
},
[theme.breakpoints.up('lg')]: {
width: theme.breakpoints.values.lg,
},
})}>
{props.headline}
</Typography>
)}
<Box
sx={theme => ({
display: 'flex',
justifyContent: 'center',
[theme.breakpoints.down('md')]: {
// minHeight: imageUrl && '60vh',
flexDirection: props.title || props.headline ? 'column' : 'column-reverse',
alignItems: 'center',
gap: 3,
},
[theme.breakpoints.only('md')]: {
mx: 'auto',
width: theme.breakpoints.values.md,
maxWidth: 'calc(100% - 4em)',
flexDirection: variant === 'primary' ? 'row-reverse' : 'row',
alignItems: 'center',
gap: 5,
},
[theme.breakpoints.up('lg')]: {
mx: 'auto',
width: theme.breakpoints.values.lg,
flexDirection: variant === 'primary' ? 'row-reverse' : 'row',
alignItems: 'center',
gap: 5,
},
})}>
{imageUrl &&
(imageCaption ? (
<Box sx={{ flex: 4, flexDirection: 'column', alignItems: 'center', justifyContent: 'center' }}>
<Box component="img" src={imageUrl} alt={imageAlt} width="100%" />
{imageCaption}
</Box>
) : (
<Box
component="img"
src={imageUrl}
alt={imageAlt}
sx={{ width: { xs: '100%', md: '40%' }, flex: 4, flexDirection: 'column', alignItems: 'center', justifyContent: 'center' }}
/>
))}
<Box
sx={{
flex: 6,
display: 'flex',
flexDirection: 'column',
justifyContent: 'center',
alignContent: 'center',
gap: 1,
...props.sx,
}}>
{children}
</Box>
</Box>
</Box>
</Box>
)
}
export default Section
@@ -91,6 +91,11 @@ const CustomToolbar: React.FC<CustomToolbarProps> = ({ drawerWidth = 240, window
<ListItemText primary="Home" /> <ListItemText primary="Home" />
</DrawerButton> </DrawerButton>
</ListItem> </ListItem>
<ListItem key="Attività" disablePadding>
<DrawerButton component={RouterLink} to="/activities">
<ListItemText primary="Attività" />
</DrawerButton>
</ListItem>
<ListItem key="Personaggi" disablePadding> <ListItem key="Personaggi" disablePadding>
<DrawerButton component={RouterLink} to="/people"> <DrawerButton component={RouterLink} to="/people">
<ListItemText primary="Personaggi" /> <ListItemText primary="Personaggi" />
@@ -159,6 +164,7 @@ const CustomToolbar: React.FC<CustomToolbarProps> = ({ drawerWidth = 240, window
</AppBarLink> </AppBarLink>
<Stack component="div" direction="row" spacing={2} sx={{ display: { xs: 'none', md: 'flex', alignItems: 'center' } }}> <Stack component="div" direction="row" spacing={2} sx={{ display: { xs: 'none', md: 'flex', alignItems: 'center' } }}>
<AppBarLink to="/">Home</AppBarLink> <AppBarLink to="/">Home</AppBarLink>
<AppBarLink to="/activities">Attività</AppBarLink>
<AppBarLink to="/people">Personaggi</AppBarLink> <AppBarLink to="/people">Personaggi</AppBarLink>
<Button component={RouterLink} to="/contacts" color="primary" variant="contained" sx={{ textTransform: 'none' }}> <Button component={RouterLink} to="/contacts" color="primary" variant="contained" sx={{ textTransform: 'none' }}>
<Typography variant="h6">Contattaci</Typography> <Typography variant="h6">Contattaci</Typography>
@@ -0,0 +1,33 @@
import { screen } from '@testing-library/react'
// import userEvent from '@testing-library/user-event'
import { renderWithRouter as render } from 'components/utils/tests'
import ActivitiesPage from '.'
// vi.stubGlobal('open', vi.fn())
describe('Activities Page', () => {
// const open = vi.spyOn(window, 'open')
it('Should render the page correctly on desktop', async () => {
await render(<ActivitiesPage />)
expect(screen.getAllByText('Attività')).toHaveLength(3) // title, appbar button and appbar drawer button
expect(screen.getByText('Percorsi didattici')).toBeInTheDocument()
expect(screen.getByText('Sartoria')).toBeInTheDocument()
expect(screen.getByText('Organizzazione eventi')).toBeInTheDocument()
})
it('Should render the page correctly on mobile', async () => {
// Set the window size to mobile (Galaxy Note 20 Android 11)
window.innerWidth = 412
window.innerHeight = 915
await render(<ActivitiesPage />)
expect(screen.getAllByText('Attività')).toHaveLength(3) // title, appbar button and appbar drawer button
expect(screen.getByText('Percorsi didattici')).toBeInTheDocument()
expect(screen.getByText('Sartoria')).toBeInTheDocument()
expect(screen.getByText('Organizzazione eventi')).toBeInTheDocument()
})
})
@@ -0,0 +1,90 @@
import { Typography } from '@mui/material'
import Section from 'components/molecules/Section/index.js'
import { Page } from 'components/templates/index.js'
const ActivitiesPage = () => {
return (
<Page title="Attività">
<Section title="Percorsi didattici" sx={{ pb: 0 }}>
<Typography variant="body1" color="text.secondary">
La Compagnia propone percorsi didattici dedicati alla scoperta della vita nel Basso Medioevo, illustrando le attività svolte all'interno del
campo armato e il loro ruolo nella quotidianità dei soldati. Attraverso dimostrazioni pratiche e spiegazioni storiche, vengono presentati
armamenti, addestramento, medicina medievale e aspetti della vita civile, offrendo un'esperienza educativa coinvolgente.
</Typography>
</Section>
<Section imageUrl="images/activities/2021_06_15-sartoria.jpg" imageAlt="Sartoria">
<Typography variant="h5">Sartoria</Typography>
<Typography variant="body1" color="text.secondary">
Nel Medioevo l'abbigliamento aveva un valore profondo: i vestiti non servivano solo a coprire il corpo, ma raccontavano chi eravamo, da dove
venivamo e quale ruolo si aveva nella società. La Compagnia d'Arme del Santo Luca realizza abiti ispirati alle forme e alle tecniche
dell'epoca, impiegando tagli, colori e materiali che riflettono le pratiche storiche. Dalle tuniche e vesti di uso quotidiano alle fogge più
ricercate per dame e cavalieri, ogni capo è scelto per mostrare come tessuti come lana, lino e seta erano trasformati in elementi di
abbigliamento che rispecchiavano funzioni, status e gusti del tempo. L'abbigliamento diventa così una finestra sul mondo medievale, fatta di
forme, significati e dettagli che accompagnavano la vita di tutti i giorni e le occasioni speciali.
</Typography>
</Section>
<Section variant="secondary" imageUrl="images/activities/cucina.png" imageAlt="Cucina">
<Typography variant="h5">Cucina</Typography>
<Typography variant="body1" color="text.secondary">
La cucina medievale è un mondo a parte, fatto di sapori, profumi e tecniche di cottura che oggi ci sembrano lontani ma che all'epoca erano
all'ordine del giorno. La compagnia ha una cucina attrezzata e funzionale, con la quale è in grado di preparare e spiegare piatti tipici
dell'epoca, utilizzando ingredienti e metodi di cottura autentici all'inteno di eventi, manifestazioni e rievocazioni storiche.
</Typography>
<Typography variant="body1" color="text.secondary">
Su rirchiesta la compagnia può organizzare lezioni di cucina medievale, dove i partecipanti possono imparare a conoscere e preparare piatti
tipici dell'epoca.
</Typography>
</Section>
<Section imageUrl="images/activities/2021_05_30-cerusico.jpg" imageAlt="Cucina">
<Typography variant="h5">Cerusico</Typography>
<Typography variant="body1" color="text.secondary">
Nell'accampamento medievale la figura del cerusico rivestiva un ruolo fondamentale: era colui che interveniva sulle ferite, conosceva gli
strumenti e sapeva riconoscere le erbe utili a curare i piccoli mali della vita quotidiana. La Compagnia d'Arme del Santo Luca porta in vita
questa figura storica attraverso l'allestimento di postazioni didattiche in cui vengono illustrati strumenti, rimedi e pratiche mediche del
periodo, offrendo uno sguardo autentico su come si affrontavano salute e guarigione nel Medioevo, con attenzione alle conoscenze e alle
tecniche del tempo.
</Typography>
</Section>
<Section variant="secondary" imageUrl="images/activities/2021_05_30-pilgrimage.jpg" imageAlt="Cucina">
<Typography variant="h5">Pellegrinaggio</Typography>
<Typography variant="body1" color="text.secondary">
Il pellegrinaggio nel Medioevo era molto più di un viaggio: era un'esperienza di spiritualità, cultura e incontro. All'interno delle nostre
rievocazioni la Compagnia d'Arme del Santo Luca ricrea gli aspetti di questi cammini antichi, raccontando come si muovevano i pellegrini,
quali mete raggiungevano e quali usanze accompagnavano il loro percorso. Tra storie di santi, architetture sacre e tappe di sosta, il
pellegrinaggio diventa un modo coinvolgente per comprendere le motivazioni profonde che spingevano uomini e donne a intraprendere grandi
traversate a piedi nel cuore dell'Europa medievale.
</Typography>
</Section>
<Section imageUrl="images/activities/2019_02_24-Armi.jpg" imageAlt="Cucina">
<Typography variant="h5">Armi e armature</Typography>
<Typography variant="body1" color="text.secondary">
Alla base della vita militare medievale c'erano le armi e le armature: oggetti di straordinaria ingegneria e simboli di uno stile di
combattimento e di vita che hanno dominato i campi di battaglia per secoli. La Compagnia d'Arme del Santo Luca possiede e utilizza repliche
storicamente documentate di spade, lance, elmi e corazze, e propone dimostrazioni che illustrano l'evoluzione e l'uso di questi elementi,
spiegando materiali, funzione e peculiarità. Lo studio delle armi e delle armature è affiancato da approfondimenti sul contesto bellico e
sociale del tempo, per restituire un quadro completo delle tecniche e delle strategie che contraddistinsero l'arte della guerra medievale.
</Typography>
</Section>
<Section
variant="secondary"
title="Organizzazione eventi"
headline="La compagnia unisce professionalità e creatività per nell'ideare ed organizzare eventi di stampo medievale. Offre la possibilità di curare singoli spettacoli o intere manifestazioni in base alle esigenze dei singoli organizzatori."
imageUrl="images/activities/2018_04_21_gorizia.jpg"
imageAlt="Gorizia 2018">
<Typography variant="body1" color="text.secondary">
La Compagnia d'Arme del Santo Luca partecipa a una varietà di manifestazioni e rievocazioni storiche, collaborando con enti pubblici,
associazioni culturali e festival dedicati alla storia medievale e rinascimentale. Ogni evento è per noi l'occasione di portare il passato
nel presente attraverso cortei, scene di vita, dimostrazioni e spettacoli che raccontano con rigore e passione usi, costumi e valori di
secoli trascorsi. La nostra esperienza nella progettazione e gestione di eventi storici ci permette di trasformare ogni appuntamento in un
momento coinvolgente, capace di affascinare il pubblico, valorizzare i contesti storici e offrire ai visitatori un'immersione autentica
nella cultura medievale. Partecipiamo con entusiasmo a rievocazioni, mercati storici, celebrazioni di battaglie, e altre iniziative in cui
storia e spettacolo si intrecciano, contribuendo a creare un'esperienza viva, educativa e memorabile per tutti i presenti.
</Typography>
</Section>
</Page>
)
}
export default ActivitiesPage
@@ -39,7 +39,13 @@ const ListItemLink: React.FC<ListItemProps> = ({ children, ...props }) => (
const ContactPage = () => { const ContactPage = () => {
return ( return (
<Page title="Contatti"> <Page
title="Contatti"
sx={{
width: theme => theme.breakpoints.values.lg,
px: 'auto',
mx: 'auto',
}}>
<Typography align="left" variant="h6"> <Typography align="left" variant="h6">
Sentiti libero di contattatarci con uno qualsiasi dei seguenti: Sentiti libero di contattatarci con uno qualsiasi dei seguenti:
</Typography> </Typography>
@@ -14,7 +14,6 @@ describe('Main page', () => {
// Make sure the project spotlights are present for both desktop and mobile // Make sure the project spotlights are present for both desktop and mobile
expect(screen.getAllByText('Chi Siamo')).toHaveLength(2) expect(screen.getAllByText('Chi Siamo')).toHaveLength(2)
expect(screen.getAllByText('Vita Civile')).toHaveLength(2) expect(screen.getAllByText('Vita Civile')).toHaveLength(2)
expect(screen.getAllByText('Attività Didattiche')).toHaveLength(2)
expect(screen.getAllByText('Vita Militare')).toHaveLength(2) expect(screen.getAllByText('Vita Militare')).toHaveLength(2)
}) })
}) })
+5 -9
View File
@@ -39,21 +39,17 @@ const MainPage = () => {
</ProjectSpotlight> </ProjectSpotlight>
{/* 2. Attività didattiche */} {/* 2. Attività didattiche */}
<ProjectSpotlight ref={refTeaching} scrollTarget={refTraining} anchor="left" image="images/didattica.png" title="Vita Civile"> <ProjectSpotlight ref={refTeaching} scrollTarget={refTraining} anchor="left" image="images/didattica.png" title="Vita Civile">
<Typography> <Typography pt={1}>
La ricostruzione della vita civile rappresenta un elemento fondamentale delle attività della Compagnia. Non rappresetiamo solo soldati, ma La ricostruzione della vita civile rappresenta un elemento fondamentale delle attività della Compagnia. Non rappresetiamo solo soldati, ma
anche tutte le altre figure che vivevano e operavano al seguito di una compagnie d'arme: cuochi, artigiani, religiosi, pellegrini e anche tutte le altre figure che vivevano e operavano al seguito di una compagnie d'arme: cuochi, artigiani, religiosi, pellegrini e
personale di supporto, tutti riproposti attraverso abiti, strumenti e gesti quotidiani ricostruiti su base storica. Particolare attenzione personale di supporto, tutti riproposti attraverso abiti, strumenti e gesti quotidiani ricostruiti su base storica. Particolare attenzione
è dedicata agli aspetti della vita materiale: la preparazione dei cibi, l'organizzazione del banchetto, la sartoria storica, le pratiche è dedicata agli aspetti della vita materiale: la preparazione dei cibi, l'organizzazione del banchetto, la sartoria storica, le pratiche
mediche e devozionali ed il viaggio. mediche e devozionali ed il viaggio.
</Typography> </Typography>
<Typography pt={1}>
<Typography variant="h4" pt={3}> La Compagnia propone percorsi didattici dedicati alla scoperta della vita nel Basso Medioevo, attraverso dimostrazioni pratiche e
Attività Didattiche spiegazioni storiche, vengono presentati armamenti, addestramento, medicina medievale e aspetti della vita civile, offrendo un'esperienza
</Typography> educativa coinvolgente.
<Typography pt={2}>
La Compagnia propone percorsi didattici dedicati alla scoperta della vita nel Basso Medioevo, illustrando le attività svolte all'interno
del campo armato e il loro ruolo nella quotidianità dei soldati. Attraverso dimostrazioni pratiche e spiegazioni storiche, vengono
presentati armamenti, addestramento, medicina medievale e aspetti della vita civile, offrendo un'esperienza educativa coinvolgente.
</Typography> </Typography>
</ProjectSpotlight> </ProjectSpotlight>
{/* 3. Scuola d'arme */} {/* 3. Scuola d'arme */}
+8 -2
View File
@@ -210,8 +210,14 @@ const ProjectsPage = () => {
setDescription(null) setDescription(null)
} }
return ( return (
<Page title="Personaggi"> <Page
<Typography pb={2}> title="Personaggi"
sx={{
width: theme => theme.breakpoints.values.lg,
px: 'auto',
mx: 'auto',
}}>
<Typography px={{ xs: undefined, md: 2 }} pb={2}>
Tutti i Personaggi storici della Compagnia sono realmente vissuti ed esistono attendibili fonti bibliografiche. Il gruppo è suddiviso per Tutti i Personaggi storici della Compagnia sono realmente vissuti ed esistono attendibili fonti bibliografiche. Il gruppo è suddiviso per
classi sociali: Uomini d'arme, Artigiani, Nobili Cavalieri, Nobildonne, uomini e donne del popolo; Ogni Personaggio, il suo ruolo e il suo classi sociali: Uomini d'arme, Artigiani, Nobili Cavalieri, Nobildonne, uomini e donne del popolo; Ogni Personaggio, il suo ruolo e il suo
comportamento sono fondamentali alla ricostruzione di uno spaccato della vita di un campo d'arme del tardo XIV Secolo. comportamento sono fondamentali alla ricostruzione di uno spaccato della vita di un campo d'arme del tardo XIV Secolo.
+8 -7
View File
@@ -34,8 +34,9 @@ const Page: React.FC<PageProps> = ({ title, children, showCookieConsent, ...prop
aria-label="page-title" aria-label="page-title"
textAlign="center" textAlign="center"
sx={{ sx={{
mt: 6, mx: 'auto',
py: 6, pt: 10,
pb: 6,
}}> }}>
{title} {title}
</Typography> </Typography>
@@ -61,13 +62,13 @@ const Page: React.FC<PageProps> = ({ title, children, showCookieConsent, ...prop
<Container <Container
id="page-content" id="page-content"
component="main" component="main"
maxWidth={false}
sx={{ sx={{
mt: { xs: 8, md: 12 }, mt: { xs: 4, md: 12 },
mb: 4, px: '0 !important',
minHeight: '80vh', minHeight: '80vh',
mx: 'auto', maxWidth: '100%',
maxWidth: { xs: '100%', md: 'calc(100% - 4em)' }, width: '100%',
width: theme => theme.breakpoints.values.lg,
...props.sx, ...props.sx,
}}> }}>
{children} {children}