Rewrite in bun and vite away from NextJs
Co-authored-by: Copilot <copilot@github.com>
This commit is contained in:
34
src/App.tsx
Normal file
34
src/App.tsx
Normal file
@@ -0,0 +1,34 @@
|
||||
import { BrowserRouter, Routes, Route } from 'react-router-dom';
|
||||
import Footer from './components/Footer';
|
||||
import Logo from './components/Logo';
|
||||
import Index from './pages/Index';
|
||||
import Performers from './pages/Performers';
|
||||
import PerformerPage from './pages/PerformerPage';
|
||||
import Program from './pages/Program';
|
||||
import Info from './pages/Info';
|
||||
import Safety from './pages/Safety';
|
||||
import Workshops from './pages/Workshops';
|
||||
import Archive from './pages/Archive';
|
||||
|
||||
function App() {
|
||||
return (
|
||||
<BrowserRouter>
|
||||
<Logo />
|
||||
<main>
|
||||
<Routes>
|
||||
<Route path="/" element={<Index />} />
|
||||
<Route path="/performers" element={<Performers />} />
|
||||
<Route path="/performers/:id" element={<PerformerPage />} />
|
||||
<Route path="/program" element={<Program />} />
|
||||
<Route path="/info" element={<Info />} />
|
||||
<Route path="/safety" element={<Safety />} />
|
||||
<Route path="/workshops" element={<Workshops />} />
|
||||
<Route path="/archive" element={<Archive />} />
|
||||
</Routes>
|
||||
</main>
|
||||
<Footer />
|
||||
</BrowserRouter>
|
||||
);
|
||||
}
|
||||
|
||||
export default App;
|
||||
28
src/components/Collaboration.tsx
Normal file
28
src/components/Collaboration.tsx
Normal file
@@ -0,0 +1,28 @@
|
||||
import React from 'react';
|
||||
import styles from '../../styles/Collaboration.module.scss';
|
||||
|
||||
const Collaboration = () => {
|
||||
return (
|
||||
<>
|
||||
<h1>Yhteistyössä</h1>
|
||||
<div className={styles.collabContainer}>
|
||||
<span>Runoviikko Ry</span>
|
||||
<div className={styles.collabLogoRow}>
|
||||
<img
|
||||
className={styles.collabLogo}
|
||||
src='/collaborators/kirjan_talo.png'
|
||||
alt='kirjan talo logo'
|
||||
/>
|
||||
</div>
|
||||
<span>Velkuan saaristolaisyhdistys ry</span>
|
||||
<span>Cafe Laituri</span>
|
||||
<span>Saaristohotelli Vaihela</span>
|
||||
<span>Aviador Kustannus</span>
|
||||
<span>Enostone Kustannus</span>
|
||||
<span>Keski-Suomen kirjailijat</span>
|
||||
</div>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
export default Collaboration;
|
||||
42
src/components/Footer.tsx
Normal file
42
src/components/Footer.tsx
Normal file
@@ -0,0 +1,42 @@
|
||||
import { Link } from 'react-router-dom';
|
||||
import React from 'react';
|
||||
import styles from '../../styles/Footer.module.scss';
|
||||
|
||||
const Footer = () => {
|
||||
return (
|
||||
<footer className={styles.footer}>
|
||||
<div className={styles.container}>
|
||||
<div className={styles.left}>
|
||||
Livonsaari & Palva & Velkuanmaa
|
||||
<br />
|
||||
Naantalin saaristo
|
||||
<br />
|
||||
</div>
|
||||
<div className={styles.middle}>
|
||||
<Link to='/#nav-bar'>
|
||||
<img
|
||||
className={styles.logo}
|
||||
src='/small-logo.png'
|
||||
alt='small logo'
|
||||
/>
|
||||
</Link>
|
||||
<div>
|
||||
<a
|
||||
className={styles.sourceLink}
|
||||
href='https://github.com/codevictory/runosaari.net'
|
||||
>
|
||||
lähdekoodi
|
||||
</a>
|
||||
{' '}by codevictory
|
||||
</div>
|
||||
</div>
|
||||
<div className={styles.right}>
|
||||
Katariina Vuorinen <br />
|
||||
<a href='mailto:runosaari@gmail.com'>runosaari@gmail.com</a>
|
||||
</div>
|
||||
</div>
|
||||
</footer>
|
||||
);
|
||||
};
|
||||
|
||||
export default Footer;
|
||||
17
src/components/Lead.tsx
Normal file
17
src/components/Lead.tsx
Normal file
@@ -0,0 +1,17 @@
|
||||
import React from 'react';
|
||||
import styles from '../../styles/Lead.module.scss';
|
||||
|
||||
const Lead = () => {
|
||||
return (
|
||||
<div className={styles.leadContainer}>
|
||||
<h2 className={styles.leadTitle}>
|
||||
Runofestivaali saariston sylissä!
|
||||
<span className={styles.dateAndPlace}>
|
||||
11. - 13.6.2026
|
||||
</span>
|
||||
</h2>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default Lead;
|
||||
31
src/components/Logo.tsx
Normal file
31
src/components/Logo.tsx
Normal file
@@ -0,0 +1,31 @@
|
||||
import React from 'react';
|
||||
import { Link } from 'react-router-dom';
|
||||
import styles from '../../styles/Logo.module.scss';
|
||||
|
||||
const Logo = () => {
|
||||
return (
|
||||
<Link to="/">
|
||||
<section className={styles.logoContainer}>
|
||||
<div className={styles.logo} id='logo-start'>
|
||||
<picture>
|
||||
<source
|
||||
srcSet='/runosaari-logo_small.jpg'
|
||||
media='(max-width: 600px)'
|
||||
/>
|
||||
<source srcSet='/runosaari-logo.jpg' />
|
||||
<img
|
||||
src='/runosaari-logo.jpg'
|
||||
alt='Runosaari logo'
|
||||
className={styles.logoImage}
|
||||
/>
|
||||
</picture>
|
||||
<div className={styles.logoCredits}>
|
||||
<div>@Sanna Hukkanen</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
</Link>
|
||||
);
|
||||
};
|
||||
|
||||
export default Logo;
|
||||
22
src/components/NavBar.tsx
Normal file
22
src/components/NavBar.tsx
Normal file
@@ -0,0 +1,22 @@
|
||||
import { Link } from 'react-router-dom';
|
||||
import styles from '../../styles/NavBar.module.scss';
|
||||
|
||||
const NavBar = () => {
|
||||
return (
|
||||
<>
|
||||
<div className={styles.navBarContainer}>
|
||||
<nav className={styles.navBar}>
|
||||
<Link to='/' className={styles.navBarLink}>Etusivu</Link>
|
||||
<Link to='/program' className={styles.navBarLink}>Ohjelma</Link>
|
||||
<Link to='/performers' className={styles.navBarLink}>Esiintyjät</Link>
|
||||
{/* <Link to='/workshops' className={styles.navBarLink}>Työpajat</Link> */}
|
||||
<Link to='/info' className={styles.navBarLink}>Info</Link>
|
||||
<Link to='/safety' className={styles.navBarLink}>Turvallisuus</Link>
|
||||
<Link to='/archive' className={styles.navBarLink}>Arkisto</Link>
|
||||
</nav>
|
||||
</div>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
export default NavBar;
|
||||
11
src/main.tsx
Normal file
11
src/main.tsx
Normal file
@@ -0,0 +1,11 @@
|
||||
import React from 'react';
|
||||
import ReactDOM from 'react-dom/client';
|
||||
import App from './App';
|
||||
import '../styles/globals.scss';
|
||||
import '../styles/transitions.scss';
|
||||
|
||||
ReactDOM.createRoot(document.getElementById('root')!).render(
|
||||
<React.StrictMode>
|
||||
<App />
|
||||
</React.StrictMode>
|
||||
);
|
||||
102
src/pages/Archive.tsx
Normal file
102
src/pages/Archive.tsx
Normal file
@@ -0,0 +1,102 @@
|
||||
import React, { useEffect, useState } from 'react';
|
||||
import { CSSTransition } from 'react-transition-group';
|
||||
import shared from '../../styles/Shared.module.scss';
|
||||
import styles from '../../styles/Archive.module.scss';
|
||||
import PerformersData2021 from '../../data/performers/2021';
|
||||
import PerformersData2022 from '../../data/performers/2022';
|
||||
import PerformersData2023 from '../../data/performers/2023';
|
||||
import PerformersData2024 from '../../data/performers/2024';
|
||||
import PerformersData2025 from '../../data/performers/2025';
|
||||
import Performer from '../../types/Performer';
|
||||
import { BiChevronDown, BiChevronLeft } from 'react-icons/bi';
|
||||
|
||||
interface PerformerCard extends Performer {
|
||||
showDesc: boolean;
|
||||
}
|
||||
|
||||
const dataByYear: Record<number, Performer[]> = {
|
||||
2025: PerformersData2025,
|
||||
2024: PerformersData2024,
|
||||
2023: PerformersData2023,
|
||||
2022: PerformersData2022,
|
||||
2021: PerformersData2021,
|
||||
};
|
||||
|
||||
const sortedYears = Object.keys(dataByYear).map(Number).sort((a, b) => b - a);
|
||||
|
||||
const Archive = () => {
|
||||
const [performersByYear, setPerformersByYear] = useState<Record<number, PerformerCard[]>>({});
|
||||
|
||||
useEffect(() => {
|
||||
const initial: Record<number, PerformerCard[]> = {};
|
||||
for (const year of sortedYears) {
|
||||
initial[year] = dataByYear[year].map((p) => ({ ...p, showDesc: false }));
|
||||
}
|
||||
setPerformersByYear(initial);
|
||||
}, []);
|
||||
|
||||
const togglePerformerDesc = (year: number, id: string) => {
|
||||
setPerformersByYear((prev) => ({
|
||||
...prev,
|
||||
[year]: prev[year].map((p) =>
|
||||
p.id === id ? { ...p, showDesc: !p.showDesc } : p
|
||||
),
|
||||
}));
|
||||
};
|
||||
|
||||
return (
|
||||
<section className={shared.page + ' ' + styles.archivePage}>
|
||||
<h1>Arkisto</h1>
|
||||
{sortedYears.map((year) => (
|
||||
<React.Fragment key={year}>
|
||||
<h2 className={styles.year}>{year}</h2>
|
||||
{(performersByYear[year] ?? []).map((p) => (
|
||||
<div className={styles.performerContainer} key={p.id}>
|
||||
<img
|
||||
className={styles.performerImage}
|
||||
src={'/performers/' + year + '/' + p.id + '.jpg'}
|
||||
width={100}
|
||||
height={100}
|
||||
loading="lazy"
|
||||
alt={p.name}
|
||||
/>
|
||||
<div className={styles.performerTextContainer}>
|
||||
<div
|
||||
className={styles.performerTitle}
|
||||
onClick={() => togglePerformerDesc(year, p.id)}
|
||||
>
|
||||
<h2>{p.name}</h2>
|
||||
<button className={shared.openingChevron}>
|
||||
{p.showDesc ? (
|
||||
<BiChevronDown size='3rem' />
|
||||
) : (
|
||||
<BiChevronLeft size='3rem' />
|
||||
)}
|
||||
</button>
|
||||
</div>
|
||||
<CSSTransition
|
||||
in={p.showDesc}
|
||||
timeout={1000}
|
||||
classNames='fadeTransition'
|
||||
>
|
||||
{p.showDesc ? (
|
||||
<div>
|
||||
{p.paragraphs.map((parag, index) => (
|
||||
<p key={index}>{parag.toString()}</p>
|
||||
))}
|
||||
</div>
|
||||
) : (
|
||||
<span></span>
|
||||
)}
|
||||
</CSSTransition>
|
||||
<hr />
|
||||
</div>
|
||||
</div>
|
||||
))}
|
||||
</React.Fragment>
|
||||
))}
|
||||
</section>
|
||||
);
|
||||
};
|
||||
|
||||
export default Archive;
|
||||
21
src/pages/Index.tsx
Normal file
21
src/pages/Index.tsx
Normal file
@@ -0,0 +1,21 @@
|
||||
import Performers from './Performers';
|
||||
import Program from './Program';
|
||||
import styles from '../../styles/Index.module.scss';
|
||||
import Lead from '../components/Lead';
|
||||
|
||||
const Index = () => {
|
||||
return (
|
||||
<div className={styles.indexContainer}>
|
||||
<h1>Runosaari</h1>
|
||||
<Lead />
|
||||
<Program />
|
||||
<Performers />
|
||||
{/* <Workshops /> */}
|
||||
{/* <Info /> */}
|
||||
{/* <Collaboration /> */}
|
||||
{/* <Archive /> */}
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default Index;
|
||||
205
src/pages/Info.tsx
Normal file
205
src/pages/Info.tsx
Normal file
@@ -0,0 +1,205 @@
|
||||
import React, { useState } from 'react';
|
||||
import shared from '../../styles/Shared.module.scss';
|
||||
import styles from '../../styles/Info.module.scss';
|
||||
import { BiChevronDown, BiChevronLeft } from 'react-icons/bi';
|
||||
import { CSSTransition } from 'react-transition-group';
|
||||
|
||||
interface InfoToggles {
|
||||
shop: boolean;
|
||||
bus: boolean;
|
||||
accom: boolean;
|
||||
ferry: boolean;
|
||||
fb: boolean;
|
||||
}
|
||||
|
||||
const Info = () => {
|
||||
const [infoToggles, setInfoToggles] = useState<InfoToggles>({
|
||||
shop: false,
|
||||
bus: false,
|
||||
accom: false,
|
||||
ferry: false,
|
||||
fb: false,
|
||||
});
|
||||
|
||||
const toggleInfo = (info: keyof InfoToggles) => {
|
||||
let updated = { ...infoToggles };
|
||||
updated[info] = !updated[info];
|
||||
setInfoToggles(updated);
|
||||
};
|
||||
|
||||
return (
|
||||
<section className={shared.page}>
|
||||
<h1>Info</h1>
|
||||
|
||||
<div className={styles.infoContainer}>
|
||||
<div className={styles.infoTitle} onClick={() => toggleInfo('shop')}>
|
||||
<h2>Livonsaaren Osuuskauppa</h2>
|
||||
<button className={shared.openingChevron}>
|
||||
{infoToggles.shop ? (
|
||||
<BiChevronDown size='3rem' />
|
||||
) : (
|
||||
<BiChevronLeft size='3rem' />
|
||||
)}
|
||||
</button>
|
||||
</div>
|
||||
<CSSTransition
|
||||
in={infoToggles.shop}
|
||||
timeout={1000}
|
||||
classNames='fadeTransition'
|
||||
>
|
||||
{infoToggles.shop ? (
|
||||
<div>
|
||||
<p>
|
||||
Livonsaaren osuuskauppa palvelee klo 9-19 joka päivä. Keittiö ja
|
||||
baari 12-19 to-pe. Ostosten yhteydessä mahdollista nostaa
|
||||
käteistä, mutta suosittelemme tuomaan käteistä rahaa kaupungista
|
||||
esim. mahdollisia kirjaostoksia varten.
|
||||
</p>
|
||||
<a href='https://livonsaarenosuuskauppa.fi/'>Kaupan kotisivut</a>
|
||||
</div>
|
||||
) : (
|
||||
<></>
|
||||
)}
|
||||
</CSSTransition>
|
||||
<hr />
|
||||
</div>
|
||||
<div className={styles.infoContainer}>
|
||||
<div className={styles.infoTitle} onClick={() => toggleInfo('bus')}>
|
||||
<h2>Bussiaikataulut</h2>
|
||||
<button className={shared.openingChevron}>
|
||||
{infoToggles.bus ? (
|
||||
<BiChevronDown size='3rem' />
|
||||
) : (
|
||||
<BiChevronLeft size='3rem' />
|
||||
)}
|
||||
</button>
|
||||
</div>
|
||||
<CSSTransition
|
||||
in={infoToggles.bus}
|
||||
timeout={1000}
|
||||
classNames='fadeTransition'
|
||||
>
|
||||
{infoToggles.bus ? (
|
||||
<div>
|
||||
<p>
|
||||
Bussi 203 lähtee Turusta ma-pe klo 16:10 ja Naantalista klo 17,
|
||||
ja saapuu Velkuan Teersaloon n. klo 17:45. Tämä on ainoa suora
|
||||
yhteys festivaalille. Palvan saareen on Teersalosta yksi lossi,
|
||||
ja Velkuanmaahan kaksi. Lossit lähtevät puolen tunnin välein
|
||||
(tasatunnein ja puolelta) Teersalosta ja Velkuanmaasta, ja Palvasta
|
||||
aina varttia vaille ja yli tasatunnin. (Aikataulut:{' '}
|
||||
<a href="https://www.finferries.fi/">finnferries.fi</a>)
|
||||
Takaisin päin busseja ei kulje viikonloppuisin.
|
||||
</p>
|
||||
<a href='https://cms.foli.fi/sites/default/files/documents-2024-04/Linja%20200%2C203.pdf'>
|
||||
Paikallisliikenteen bussiaikataulut
|
||||
</a>
|
||||
</div>
|
||||
) : (
|
||||
<></>
|
||||
)}
|
||||
</CSSTransition>
|
||||
<hr />
|
||||
</div>
|
||||
<div className={styles.infoContainer}>
|
||||
<div className={styles.infoTitle} onClick={() => toggleInfo('accom')}>
|
||||
<h2>Majoitus</h2>
|
||||
<button className={shared.openingChevron}>
|
||||
{infoToggles.accom ? (
|
||||
<BiChevronDown size='3rem' />
|
||||
) : (
|
||||
<BiChevronLeft size='3rem' />
|
||||
)}
|
||||
</button>
|
||||
</div>
|
||||
<CSSTransition
|
||||
in={infoToggles.accom}
|
||||
timeout={1000}
|
||||
classNames='fadeTransition'
|
||||
>
|
||||
{infoToggles.accom ? (
|
||||
<div className={styles.infoContent}>
|
||||
<p>
|
||||
Majoituspalveluita Livonsaari-Velkua: Wanha Salakuljettaja
|
||||
(Teersalo), Livonsaari Caravan, Saaristohotelli Vaihela.
|
||||
</p>
|
||||
<div className={styles.linkList}>
|
||||
<a href='https://oldsmuggler.fi/'>Vanha Salakuljettaja</a>
|
||||
<a href='https://www.livonsaarencaravan.fi/'>
|
||||
Livonsaari Caravan
|
||||
</a>
|
||||
<a href='https://vaihela.fi/'>Saaristohotelli Vaihela</a>
|
||||
</div>
|
||||
</div>
|
||||
) : (
|
||||
<></>
|
||||
)}
|
||||
</CSSTransition>
|
||||
<hr />
|
||||
</div>
|
||||
<div className={styles.infoContainer}>
|
||||
<div className={styles.infoTitle} onClick={() => toggleInfo('ferry')}>
|
||||
<h2>Lossiyhteydet</h2>
|
||||
<button className={shared.openingChevron}>
|
||||
{infoToggles.ferry ? (
|
||||
<BiChevronDown size='3rem' />
|
||||
) : (
|
||||
<BiChevronLeft size='3rem' />
|
||||
)}
|
||||
</button>
|
||||
</div>
|
||||
<CSSTransition
|
||||
in={infoToggles.ferry}
|
||||
timeout={1000}
|
||||
classNames='fadeTransition'
|
||||
>
|
||||
{infoToggles.ferry ? (
|
||||
<div>
|
||||
<p>
|
||||
Lossiyhteydet Palvaan ja Velkuanmaahan Finferries-sivustolla
|
||||
(huom. yövuoro edellyttää tilauksen etukäteen. Lossi on osa
|
||||
julkista tieverkostoa eli maksuton.)
|
||||
</p>
|
||||
<a href='https://www.finferries.fi/lauttaliikenne/lauttapaikat-ja-aikataulut/velkuanmaa.html'>
|
||||
Aikataulut Palvaan ja Velkuanmaahan
|
||||
</a>
|
||||
</div>
|
||||
) : (
|
||||
<></>
|
||||
)}
|
||||
</CSSTransition>
|
||||
<hr />
|
||||
</div>
|
||||
<div className={styles.infoContainer}>
|
||||
<div className={styles.infoTitle} onClick={() => toggleInfo('fb')}>
|
||||
<h2>Facebook</h2>
|
||||
<button className={shared.openingChevron}>
|
||||
{infoToggles.fb ? (
|
||||
<BiChevronDown size='3rem' />
|
||||
) : (
|
||||
<BiChevronLeft size='3rem' />
|
||||
)}
|
||||
</button>
|
||||
</div>
|
||||
<CSSTransition
|
||||
in={infoToggles.fb}
|
||||
timeout={1000}
|
||||
classNames='fadeTransition'
|
||||
>
|
||||
{infoToggles.fb ? (
|
||||
<div>
|
||||
<a href='https://www.facebook.com/Runosaari-festivaali-110533364561933'>
|
||||
Tapahtuman facebook-sivut
|
||||
</a>
|
||||
</div>
|
||||
) : (
|
||||
<></>
|
||||
)}
|
||||
</CSSTransition>
|
||||
<hr />
|
||||
</div>
|
||||
</section>
|
||||
);
|
||||
};
|
||||
|
||||
export default Info;
|
||||
49
src/pages/PerformerPage.tsx
Normal file
49
src/pages/PerformerPage.tsx
Normal file
@@ -0,0 +1,49 @@
|
||||
import React, { useEffect, useState } from 'react';
|
||||
import { useParams } from 'react-router-dom';
|
||||
import shared from '../../styles/Shared.module.scss';
|
||||
import styles from '../../styles/Performer.module.scss';
|
||||
import PerformersData from '../../data/performers/2025';
|
||||
import Performer from '../../types/Performer';
|
||||
|
||||
const PerformerPage = () => {
|
||||
const { id } = useParams<{ id: string }>();
|
||||
|
||||
const [performer, setPerformer] = useState<Performer>({
|
||||
name: '',
|
||||
paragraphs: [],
|
||||
id: '',
|
||||
});
|
||||
|
||||
useEffect(() => {
|
||||
setPerformer(
|
||||
PerformersData.find((p) => p.id === id) ?? {
|
||||
name: '',
|
||||
paragraphs: [],
|
||||
id: '',
|
||||
}
|
||||
);
|
||||
}, [id]);
|
||||
|
||||
return performer.name === '' ? (
|
||||
<div>Esiintyjää tunnisteella {id} ei löydy.</div>
|
||||
) : (
|
||||
<div className={styles.performerContainer}>
|
||||
<img
|
||||
className={styles.performerImage}
|
||||
src={'/performers/2025/' + performer.id + '.jpg'}
|
||||
width={300}
|
||||
height={300}
|
||||
loading="lazy"
|
||||
alt={performer.name}
|
||||
/>
|
||||
<h2>{performer.name}</h2>
|
||||
<div>
|
||||
{performer.paragraphs.map((parag, index) => (
|
||||
<p key={index}>{parag.toString()}</p>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default PerformerPage;
|
||||
99
src/pages/Performers.tsx
Normal file
99
src/pages/Performers.tsx
Normal file
@@ -0,0 +1,99 @@
|
||||
import React, { useEffect, useState } from 'react';
|
||||
import { Link } from 'react-router-dom';
|
||||
import styles from '../../styles/Performers.module.scss';
|
||||
import shared from '../../styles/Shared.module.scss';
|
||||
import Performer from '../../types/Performer';
|
||||
import { BiChevronDown, BiChevronLeft } from 'react-icons/bi';
|
||||
import PerformersData from '../../data/performers/2026';
|
||||
import { CSSTransition } from 'react-transition-group';
|
||||
import { FiExternalLink } from 'react-icons/fi';
|
||||
|
||||
interface PerformerCard extends Performer {
|
||||
showDesc: boolean;
|
||||
}
|
||||
|
||||
const Performers = () => {
|
||||
const [performers, setPerformers] = useState<PerformerCard[]>([]);
|
||||
|
||||
useEffect(() => {
|
||||
let cards: PerformerCard[] = [];
|
||||
|
||||
PerformersData.map((p) => {
|
||||
let newCard = { ...p, showDesc: false };
|
||||
cards.push(newCard);
|
||||
});
|
||||
|
||||
setPerformers(cards);
|
||||
}, []);
|
||||
|
||||
const togglePerformerDesc = (id: string) => {
|
||||
let updated: PerformerCard[];
|
||||
updated = performers.map((p) => {
|
||||
if (p.id === id) {
|
||||
p.showDesc = !p.showDesc;
|
||||
}
|
||||
return p;
|
||||
});
|
||||
|
||||
setPerformers(updated);
|
||||
};
|
||||
|
||||
return (
|
||||
<section className={shared.page}>
|
||||
<h1>Esiintyjät</h1>
|
||||
{performers.length !== 0 ? (
|
||||
performers.map((p) => (
|
||||
<div className={styles.performerContainer} key={p.id}>
|
||||
<img
|
||||
className={styles.performerImage}
|
||||
src={'/performers/2025/' + p.id + '.jpg'}
|
||||
width={100}
|
||||
height={100}
|
||||
loading="lazy"
|
||||
alt={p.name + ' image'}
|
||||
/>
|
||||
<div className={styles.performerTextContainer}>
|
||||
<div
|
||||
className={styles.performerTitle}
|
||||
onClick={() => togglePerformerDesc(p.id)}
|
||||
>
|
||||
<h2>{p.name}</h2>
|
||||
<button className={shared.openingChevron}>
|
||||
{p.showDesc ? (
|
||||
<BiChevronDown size='3rem' />
|
||||
) : (
|
||||
<BiChevronLeft size='3rem' />
|
||||
)}
|
||||
</button>
|
||||
</div>
|
||||
<CSSTransition
|
||||
in={p.showDesc}
|
||||
timeout={1000}
|
||||
classNames='fadeTransition'
|
||||
>
|
||||
{p.showDesc ? (
|
||||
<div>
|
||||
{p.paragraphs.map((parag, index) => (
|
||||
<p key={index}>{parag.toString()}</p>
|
||||
))}
|
||||
</div>
|
||||
) : (
|
||||
<span></span>
|
||||
)}
|
||||
</CSSTransition>
|
||||
<hr />
|
||||
</div>
|
||||
</div>
|
||||
))
|
||||
) : (
|
||||
<i className={shared.moreInfoLaterText}>Lisätietoja tulossa myöhemmin...</i>
|
||||
)}
|
||||
<Link to="/archive">
|
||||
<span className={styles.archiveLinkText}>Aiempien vuosien esiintyjiä</span>
|
||||
<FiExternalLink fontSize={20} />
|
||||
</Link>
|
||||
</section>
|
||||
);
|
||||
};
|
||||
|
||||
export default Performers;
|
||||
70
src/pages/Program.tsx
Normal file
70
src/pages/Program.tsx
Normal file
@@ -0,0 +1,70 @@
|
||||
import React from 'react';
|
||||
import { FiExternalLink } from 'react-icons/fi';
|
||||
import shared from '../../styles/Shared.module.scss';
|
||||
import styles from '../../styles/Program.module.scss';
|
||||
import { BiChevronDown, BiChevronLeft } from 'react-icons/bi';
|
||||
|
||||
const Program = () => {
|
||||
return (
|
||||
<section className={shared.page}>
|
||||
<h1 id='program-start'>Ohjelma</h1>
|
||||
<i className={shared.moreInfoLaterText}>Lisätietoja tulossa myöhemmin...</i>
|
||||
|
||||
{/* <p className={styles.programTimeAndPlace}>
|
||||
Torstai 12.6. klo 18-21 <span className={styles.locationName}>Palva</span>
|
||||
</p>
|
||||
<h2 className={styles.placeTitle}>
|
||||
<a href='https://www.cafelaituri.fi'>
|
||||
Cafe Laituri
|
||||
</a>
|
||||
</h2>
|
||||
<ul className={styles.performerList}>
|
||||
<li>Pegasos</li>
|
||||
<li>Henriikka Tavi ja Jaakko Martikainen</li>
|
||||
<li>Peter Mickwitz</li>
|
||||
<li>Milagros Corcuera</li>
|
||||
</ul>
|
||||
<hr className={styles.programHr} />
|
||||
|
||||
<p className={styles.programTimeAndPlace}>
|
||||
Perjantai 13.6. klo 18-21 <span className={styles.locationName}>Velkuanmaa</span>
|
||||
</p>
|
||||
<h2 className={styles.placeTitle}>
|
||||
<a href='https://www.vaihela.fi/'>
|
||||
<span className={styles.placeName}>Saaristohotelli Vaihela</span>
|
||||
</a>
|
||||
</h2>
|
||||
<ul className={styles.performerList}>
|
||||
<li>Kauko Röyhkä & Severi Pyysalo</li>
|
||||
<li>Juha Kulmala + Positroninen Runo-orkesteri!</li>
|
||||
<li>Katariina Vuorinen & Pekka Tolonen</li>
|
||||
</ul>
|
||||
<hr className={styles.programHr} />
|
||||
|
||||
<p className={styles.programTimeAndPlace}>
|
||||
Lauantai 14.6. klo 15-20 <span className={styles.locationName}>Teersalo</span>
|
||||
</p>
|
||||
<h2 className={styles.placeTitle}>
|
||||
<a href='https://prosinervo.com/'>
|
||||
<span className={styles.placeName}>Sinervon talo</span>
|
||||
</a>
|
||||
</h2>
|
||||
<ul className={styles.performerList}>
|
||||
<li>Santtu Puukka</li>
|
||||
<li>Maaria Päivinen</li>
|
||||
<li>Silja Järventausta</li>
|
||||
<li>Tiina Lehikoinen</li>
|
||||
<li>Katariina Vuorinen</li>
|
||||
<li>Panu Hämeenaho</li>
|
||||
<li>Uhrijuhla</li>
|
||||
<li>Djangomania</li>
|
||||
<li>Milagros Corcuera</li>
|
||||
</ul>
|
||||
|
||||
<hr className={styles.programHr} /> */}
|
||||
|
||||
</section>
|
||||
);
|
||||
};
|
||||
|
||||
export default Program;
|
||||
54
src/pages/Safety.tsx
Normal file
54
src/pages/Safety.tsx
Normal file
@@ -0,0 +1,54 @@
|
||||
import React from 'react';
|
||||
import shared from '../../styles/Shared.module.scss';
|
||||
import styles from '../../styles/Safety.module.scss';
|
||||
|
||||
const Safety = () => {
|
||||
return (
|
||||
<section className={shared.page + ' ' + styles.safetyPage}>
|
||||
<h1>Turvallisemman tilan periaatteet</h1>
|
||||
|
||||
<p>
|
||||
Runosaaren tapahtumissa noudatetaan turvallisemman tilan periaatteita.
|
||||
Pyrimme tapahtumissamme turvaamaan näiden periaatteiden toteutumisen
|
||||
omalla toiminnallamme, tilojen suunnittelulla sekä henkilökunnan,
|
||||
esiintyjien ja yleisön informoinnilla.
|
||||
</p>
|
||||
|
||||
<ul className={styles.safetyList}>
|
||||
<li>
|
||||
<b>Kunnioitus. </b>Jokaisella ihmisellä on oikeus tulla kunnioitetuksi
|
||||
omana itsenään. Kunnioitathan muiden ihmisten fyysistä ja psyykkistä
|
||||
koskemattomuutta, mielipiteitä sekä ihmisarvoa. Jokaisella on oikeus
|
||||
poistua epämukavaksi kokemastaan tilanteesta tai keskustelusta. Ethän
|
||||
myöskään ota ihmisistä kuvia kysymättä ensin.{' '}
|
||||
</li>
|
||||
<li>
|
||||
<b>Olettaminen. </b>Ethän oleta kenenkään sukupuolta, kansallisuutta,
|
||||
seksuaalista suuntautumista, kulttuuria, kieltä, uskontoa, arvoja,
|
||||
terveydentilaa tai toimintakykyä. Ethän tee johtopäätelmiä kenenkään
|
||||
ulkonäön, käytöksen tai oletetun sosioekonomisen aseman perusteella.
|
||||
</li>
|
||||
<li>
|
||||
<b>Kommunikointi. </b>
|
||||
Pyrithän luomaan ympärillesi ystävällistä ja turvallista ilmapiiriä.
|
||||
Ole avoin muita ihmisiä kohtaan, kuuntele ja käytä kunnioittavaa
|
||||
kieltä. Ethän oleta puheessasi kenenkään sukupuolta tai muita
|
||||
ominaisuuksia. Ethän käytä stereotypisoivaa, toiseuttavaa tai
|
||||
halventaa kieltä. Jos kuitenkin vahingossa loukkaat sanoillasi
|
||||
jotakuta, pyydäthän anteeksi.
|
||||
</li>
|
||||
<li>
|
||||
<b>Toimiminen. </b>
|
||||
Mikäli havaitset epäasiallista käytöstä tai koet olosi uhatuksi, älä
|
||||
epäröi pyytää apua Runosaaren ja tapahtumapaikkojen työntekijöiltä.
|
||||
Jos koet, että olet kohdannut häirintää tapahtumissamme ja siihen ei
|
||||
ole onnistuttu puuttumaan, ole yhteydessä Runosaari-työryhmään
|
||||
sähköpostilla{' '}
|
||||
<a href='mailto:runosaari@gmail.com'>runosaari@gmail.com</a> .
|
||||
</li>
|
||||
</ul>
|
||||
</section>
|
||||
);
|
||||
};
|
||||
|
||||
export default Safety;
|
||||
14
src/pages/Workshops.tsx
Normal file
14
src/pages/Workshops.tsx
Normal file
@@ -0,0 +1,14 @@
|
||||
import React from 'react';
|
||||
import shared from '../../styles/Shared.module.scss';
|
||||
import styles from '../../styles/Workshops.module.scss';
|
||||
|
||||
const Workshops = () => {
|
||||
return (
|
||||
<section className={shared.page + ' ' + styles.workshopPage}>
|
||||
<h1>Työpajat</h1>
|
||||
<i>Lisätietoja tulossa myöhemmin...</i>
|
||||
</section>
|
||||
);
|
||||
};
|
||||
|
||||
export default Workshops;
|
||||
Reference in New Issue
Block a user