Compare commits
5 Commits
ae89ee0356
...
4774dcda11
Author | SHA1 | Date |
---|---|---|
Vencislav Atanasov | 4774dcda11 | |
Vencislav Atanasov | 86833b5276 | |
Vencislav Atanasov | 24bcaa6d23 | |
Vencislav Atanasov | 78064e3f8f | |
Vencislav Atanasov | ad782899b2 |
|
@ -1,4 +1,4 @@
|
||||||
import ScheduleChooser from './ScheduleChooser.jsx';
|
import ScheduleChooser from './Schedule/ScheduleChooser.jsx';
|
||||||
|
|
||||||
function App() {
|
function App() {
|
||||||
return (<ScheduleChooser/>);
|
return (<ScheduleChooser/>);
|
||||||
|
|
|
@ -1,3 +0,0 @@
|
||||||
export default function Event() {
|
|
||||||
|
|
||||||
}
|
|
|
@ -0,0 +1,11 @@
|
||||||
|
import PropTypes from 'prop-types';
|
||||||
|
|
||||||
|
export default function Event({
|
||||||
|
title,
|
||||||
|
}) {
|
||||||
|
return (<strong>{title}</strong>);
|
||||||
|
}
|
||||||
|
|
||||||
|
Event.propTypes = {
|
||||||
|
title: PropTypes.string.isRequired,
|
||||||
|
};
|
|
@ -1,10 +1,10 @@
|
||||||
import PropTypes from 'prop-types';
|
import PropTypes from 'prop-types';
|
||||||
import useSchedule from './hooks/useSchedule.js';
|
import useSchedule from '../hooks/useSchedule.js';
|
||||||
import { getSpeakerName, isTrackHidden } from './utils.js';
|
import { getSpeakerName, isTrackHidden } from './utils.js';
|
||||||
import { Fragment } from 'react';
|
import { Fragment } from 'react';
|
||||||
import useScheduleTable from './hooks/useScheduleTable.js';
|
import useScheduleTable from '../hooks/useScheduleTable.js';
|
||||||
import Event from './Event.jsx';
|
import Event from './Event.jsx';
|
||||||
import defaultSpeaker from './assets/default-speaker.png';
|
import defaultSpeaker from '../assets/default-speaker.png';
|
||||||
import './Schedule.scss';
|
import './Schedule.scss';
|
||||||
import { langs } from './constants.js';
|
import { langs } from './constants.js';
|
||||||
|
|
||||||
|
@ -33,8 +33,9 @@ export default function Schedule({
|
||||||
});
|
});
|
||||||
|
|
||||||
return (<>
|
return (<>
|
||||||
{isLoading && <>Loading... <progress value={loadingProgress} /></>}
|
{isLoading && <progress value={loadingProgress}/>}
|
||||||
<div className="schedule">
|
<div className="schedule">
|
||||||
|
<hr />
|
||||||
{header && rows && <>
|
{header && rows && <>
|
||||||
<table>
|
<table>
|
||||||
<thead>
|
<thead>
|
|
@ -71,11 +71,11 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
.schedule-en::after {
|
.schedule-en::after {
|
||||||
background: url('./assets/en_US.png');
|
background: url('../assets/en_US.png');
|
||||||
}
|
}
|
||||||
|
|
||||||
.schedule-bg::after {
|
.schedule-bg::after {
|
||||||
background: url('./assets/bg_BG.png');
|
background: url('../assets/bg_BG.png');
|
||||||
}
|
}
|
||||||
|
|
||||||
.schedule-avatar {
|
.schedule-avatar {
|
|
@ -0,0 +1,37 @@
|
||||||
|
import ScheduleLoader from './ScheduleLoader.jsx';
|
||||||
|
import { langs } from './constants.js';
|
||||||
|
import { useMemo, useState } from 'react';
|
||||||
|
import { dateSorter } from '../utils.js';
|
||||||
|
import useConferences from '../hooks/useConferences.js';
|
||||||
|
import { getConferenceYear } from './utils.js';
|
||||||
|
|
||||||
|
export default function ScheduleChooser() {
|
||||||
|
const {
|
||||||
|
data,
|
||||||
|
error,
|
||||||
|
isLoading,
|
||||||
|
} = useConferences();
|
||||||
|
|
||||||
|
const conferences = useMemo(() => Array.isArray(data) ? data.sort(dateSorter('start_date')) : data, [data]);
|
||||||
|
|
||||||
|
const [ year, setYear ] = useState(2023);
|
||||||
|
const [ lang, setLang ] = useState('bg');
|
||||||
|
|
||||||
|
return (<>
|
||||||
|
{isLoading && <p>Please wait...</p>}
|
||||||
|
{error && <p>Error: {error}</p>}
|
||||||
|
{conferences && <>
|
||||||
|
<select value={year} onChange={e => setYear(parseInt(e.target.value, 10))}>
|
||||||
|
{conferences.map(conference =>
|
||||||
|
<option key={conference.id} value={getConferenceYear(conference)}>{conference.title}</option>)}
|
||||||
|
</select>
|
||||||
|
</>}
|
||||||
|
{Object.entries(langs).map(([langId, langName]) =>
|
||||||
|
<label key={langId}>
|
||||||
|
<input type="radio" checked={langId === lang} onChange={e =>
|
||||||
|
setLang(e.target.value)} name="lang" value={langId} />
|
||||||
|
{langName}
|
||||||
|
</label>)}
|
||||||
|
<ScheduleLoader year={year} lang={lang} />
|
||||||
|
</>);
|
||||||
|
}
|
|
@ -1,4 +1,4 @@
|
||||||
import useConferences from './hooks/useConferences.js';
|
import useConferences from '../hooks/useConferences.js';
|
||||||
import Schedule from './Schedule.jsx';
|
import Schedule from './Schedule.jsx';
|
||||||
import PropTypes from 'prop-types';
|
import PropTypes from 'prop-types';
|
||||||
import { useMemo } from 'react';
|
import { useMemo } from 'react';
|
||||||
|
@ -27,6 +27,6 @@ export default function ScheduleLoader({
|
||||||
}
|
}
|
||||||
|
|
||||||
ScheduleLoader.propTypes = {
|
ScheduleLoader.propTypes = {
|
||||||
year: PropTypes.number,
|
year: PropTypes.number.isRequired,
|
||||||
lang: PropTypes.string,
|
lang: PropTypes.string.isRequired,
|
||||||
};
|
};
|
|
@ -0,0 +1,5 @@
|
||||||
|
export const getConferenceYear = conference => (new Date(conference.start_date)).getFullYear();
|
||||||
|
|
||||||
|
export const getSpeakerName = speaker => speaker.first_name.concat(' ').concat(speaker.last_name);
|
||||||
|
|
||||||
|
export const isTrackHidden = track => track.name.en === 'Other' || track.name.bg === 'Други';
|
|
@ -1,44 +0,0 @@
|
||||||
import PropTypes from 'prop-types';
|
|
||||||
import ScheduleLoader from './ScheduleLoader.jsx';
|
|
||||||
|
|
||||||
export default function ScheduleChooser({
|
|
||||||
year = 2023,
|
|
||||||
lang = 'bg',
|
|
||||||
}) {
|
|
||||||
/*
|
|
||||||
const {
|
|
||||||
data,
|
|
||||||
error,
|
|
||||||
isLoading,
|
|
||||||
} = useConferences();
|
|
||||||
|
|
||||||
const conferences = useMemo(() => Array.isArray(data) ? data.sort(dateSorter('start_date')) : data, [data]);
|
|
||||||
|
|
||||||
const [ selectedConferenceId, setSelectedConferenceId ] = useState();
|
|
||||||
const [ selectedLang, setSelectedLang ] = useState(lang);
|
|
||||||
|
|
||||||
return (<>
|
|
||||||
<div>
|
|
||||||
<select onChange={e => setSelectedLang(e.target.value)}>
|
|
||||||
{Object.entries(langs).map(([langId, langName]) => <option key={langId} value={langId}>{langName}</option>)}
|
|
||||||
</select>
|
|
||||||
</div>
|
|
||||||
{isLoading && <p>Please wait...</p>}
|
|
||||||
{error && <p>Error: {error}</p>}
|
|
||||||
{conferences && <>
|
|
||||||
<label>Select a conference</label>
|
|
||||||
<select onChange={e => setSelectedConferenceId(e.target.value)}>
|
|
||||||
{conferences.map(conference => <option key={conference.id}
|
|
||||||
value={conference.id}>{conference.title}</option>)}
|
|
||||||
</select>
|
|
||||||
</>}
|
|
||||||
<ScheduleLoader year={year} lang={selectedLang} />
|
|
||||||
</>);
|
|
||||||
*/
|
|
||||||
return (<ScheduleLoader year={year} lang={lang} />);
|
|
||||||
}
|
|
||||||
|
|
||||||
ScheduleChooser.propTypes = {
|
|
||||||
year: PropTypes.number,
|
|
||||||
lang: PropTypes.string,
|
|
||||||
};
|
|
|
@ -1,4 +1,5 @@
|
||||||
export default function useScheduleTable({
|
export default function useScheduleTable({
|
||||||
|
events = {},
|
||||||
halls = {},
|
halls = {},
|
||||||
lang,
|
lang,
|
||||||
}) {
|
}) {
|
||||||
|
@ -8,7 +9,16 @@ export default function useScheduleTable({
|
||||||
name: hall.name[lang],
|
name: hall.name[lang],
|
||||||
}));
|
}));
|
||||||
|
|
||||||
const rows = [];
|
const rows = Object.entries(events).map(([eventId, event]) => ({
|
||||||
|
id: eventId,
|
||||||
|
cells: [{
|
||||||
|
id: 1,
|
||||||
|
attributes: {
|
||||||
|
colSpan: 2,
|
||||||
|
},
|
||||||
|
event,
|
||||||
|
}],
|
||||||
|
}));
|
||||||
|
|
||||||
return {
|
return {
|
||||||
header,
|
header,
|
||||||
|
|
|
@ -3,10 +3,6 @@
|
||||||
line-height: 1.5;
|
line-height: 1.5;
|
||||||
font-weight: 400;
|
font-weight: 400;
|
||||||
|
|
||||||
color-scheme: light dark;
|
|
||||||
color: rgba(255, 255, 255, 0.87);
|
|
||||||
background-color: #242424;
|
|
||||||
|
|
||||||
font-synthesis: none;
|
font-synthesis: none;
|
||||||
text-rendering: optimizeLegibility;
|
text-rendering: optimizeLegibility;
|
||||||
-webkit-font-smoothing: antialiased;
|
-webkit-font-smoothing: antialiased;
|
||||||
|
|
|
@ -9,10 +9,6 @@ function sorter(a, b, fieldFn) {
|
||||||
|
|
||||||
export const dateSorter = key => (a, b) => sorter(a, b, item => Date.parse(item[key]));
|
export const dateSorter = key => (a, b) => sorter(a, b, item => Date.parse(item[key]));
|
||||||
|
|
||||||
export const getSpeakerName = speaker => speaker.first_name.concat(' ').concat(speaker.last_name);
|
|
||||||
|
|
||||||
export const isTrackHidden = track => track.name.en === 'Other' || track.name.bg === 'Други';
|
|
||||||
|
|
||||||
export function calculateProgress(...elements) {
|
export function calculateProgress(...elements) {
|
||||||
const totalCount = elements.length;
|
const totalCount = elements.length;
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue