diff --git a/src/components/ChangeLanguageButton.tsx b/src/components/ChangeLanguageButton.tsx index 4a49483..e9ef880 100644 --- a/src/components/ChangeLanguageButton.tsx +++ b/src/components/ChangeLanguageButton.tsx @@ -23,5 +23,5 @@ export default styled(ChangeLanguageButton)` font-size: 4rem; background: none; border: none; - width: fit-content; + width: 2cm; `; diff --git a/src/components/Icon.tsx b/src/components/Icon.tsx index cae974b..2052546 100644 --- a/src/components/Icon.tsx +++ b/src/components/Icon.tsx @@ -70,16 +70,34 @@ const nameToIcon = (name: IconType): JSX.Element | null => { } if (name === IconType.FinlandFlag) { return ( - - 🇫🇮 - + + Finland flag + + + + ); } if (name === IconType.GBFlag) { return ( - - 🇬🇧 - + + GB flag + + + + + + ); } return null; diff --git a/src/components/Select.tsx b/src/components/Select.tsx new file mode 100644 index 0000000..5d5dec1 --- /dev/null +++ b/src/components/Select.tsx @@ -0,0 +1,12 @@ +import styled from "styled-components"; + +const StyledSelect = styled.select` + padding: 0.25rem; + margin: 0.5rem; +`; + +const SelectWrapper = styled.div` + padding: 0.5rem; +`; + +export { StyledSelect, SelectWrapper }; diff --git a/src/pages/admin/events/index.tsx b/src/pages/admin/events/index.tsx index d20cb54..46e7579 100644 --- a/src/pages/admin/events/index.tsx +++ b/src/pages/admin/events/index.tsx @@ -1,4 +1,4 @@ -import React from "react"; +import React, { useState, useEffect } from "react"; import { NextPage } from "next"; import useSWR from "swr"; import { formatRelative } from "date-fns"; @@ -10,6 +10,7 @@ import AddLink from "@components/AddLink"; import Event from "@models/Event"; import EventApi from "@api/eventApi"; import { fetcher, APIPath, API } from "@api/backend"; +import { StyledSelect, SelectWrapper } from "@components/Select"; const URL = "/admin/events"; @@ -37,42 +38,100 @@ const Renderer: React.FC = () => { const api: API = { path: APIPath.EVENTS, authenticated: true }; const { data: events, error } = useSWR(api, fetcher); + const [sort, setSort] = useState("start_time"); + const [order, setOrder] = useState("descending"); + const [filter, setFilter] = useState("all"); + + const eventSort = (a, b) => { + let result = 0; + if (order === "descending") { + if (["start_time", "end_time"].includes(sort)) { + result = new Date(b[sort]).getTime() - new Date(a[sort]).getTime(); + } else if (sort === "id") { + result = b[sort] - a[sort]; + } + } else if (order === "ascending") { + if (["start_time", "end_time"].includes(sort)) { + result = new Date(a[sort]).getTime() - new Date(b[sort]).getTime(); + } else if (sort === "id") { + result = a[sort] - b[sort]; + } + } + return result; + }; + + const dateFilter = (a) => { + let result = true; + + if (filter === "upcoming") { + result = new Date(a.end_time).getTime() > Date.now(); + } else if (filter === "past") { + result = new Date(a.end_time).getTime() < Date.now(); + } + return result; + }; + + useEffect(() => { + }, [sort, order, filter, events]); + if (error) { console.error(error); return (
- Failed loading events + Failed loading events.
); } + if (!events?.length) { return
No events.
; } return ( - - - - - - - - - - {events.map((event) => ( - - - - - +
+ + Sort by: + setSort(e.target.value)}> + + + + + Order: + setOrder(e.target.value)}> + + + + Filter: + setFilter(e.target.value)}> + + + + + +
TitleStart timeEnd time
{event.title_fi}{formatRelative(new Date(event.start_time), new Date())}{formatRelative(new Date(event.end_time), new Date())} - confirmDelete(event)}> - Delete - -
+ + + + + - ))} - -
TitleStart timeEnd time
+ + + {events.sort(eventSort).filter(dateFilter).map((event) => ( + + {event.title_fi} + {formatRelative(new Date(event.start_time), new Date())} + {formatRelative(new Date(event.end_time), new Date())} + + confirmDelete(event)}> + Delete + + + + ))} + + + ); }; diff --git a/src/pages/admin/feed/index.tsx b/src/pages/admin/feed/index.tsx index 07bfc8d..140ba28 100644 --- a/src/pages/admin/feed/index.tsx +++ b/src/pages/admin/feed/index.tsx @@ -1,4 +1,4 @@ -import React from "react"; +import React, { useState, useEffect } from "react"; import { NextPage } from "next"; import useSWR from "swr"; import { formatRelative } from "date-fns"; @@ -10,6 +10,7 @@ import AddLink from "@components/AddLink"; import Post from "@models/Feed"; import PostApi from "@api/feedApi"; import { fetcher, APIPath, API } from "@api/backend"; +import { SelectWrapper, StyledSelect } from "@components/Select"; const URL = "/admin/feed"; @@ -37,6 +38,21 @@ const Renderer: React.FC = () => { const api: API = { path: APIPath.FEED, authenticated: true }; const { data: feed, error } = useSWR(api, fetcher); + const [order, setOrder] = useState("descending"); + + const feedSort = (a, b) => { + let result = 0; + if (order === "descending") { + result = new Date(b.publish_time).getTime() - new Date(a.publish_time).getTime(); + } else if (order === "ascending") { + result = new Date(a.publish_time).getTime() - new Date(b.publish_time).getTime(); + } + return result; + }; + + useEffect(() => { + }, [order, feed]); + if (error) { console.error(error); return ( @@ -52,29 +68,38 @@ const Renderer: React.FC = () => { } return ( - - - - - - - - - - {feed.map((post) => ( - - - - - +
+ + Order: + setOrder(e.target.value)}> + + + + +
TitleDescriptionPublish time
{post.title_fi}{post.description_fi}{formatRelative(new Date(post.publish_time), new Date())} - confirmDelete(post)}> - Delete - -
+ + + + + - ))} - -
TitleDescriptionPublish time
+ + + {feed.sort(feedSort).map((post) => ( + + {post.title_fi} + {post.description_fi} + {formatRelative(new Date(post.publish_time), new Date())} + + confirmDelete(post)}> + Delete + + + + ))} + + + ); }; diff --git a/src/pages/admin/signups/index.tsx b/src/pages/admin/signups/index.tsx index 6c4b762..703610b 100644 --- a/src/pages/admin/signups/index.tsx +++ b/src/pages/admin/signups/index.tsx @@ -1,5 +1,6 @@ -import React, { useEffect, useState } from "react"; +import React, { useState, useEffect } from "react"; import { NextPage } from "next"; +import useSWR from "swr"; import { formatRelative } from "date-fns"; import { toast } from "react-toastify"; import styled from "styled-components"; @@ -8,6 +9,8 @@ import { Button, Link } from "@components/index"; import AddLink from "@components/AddLink"; import { SignupForm } from "@models/Signup"; import SignupApi from "@api/signupApi"; +import { fetcher, APIPath, API } from "@api/backend"; +import { SelectWrapper, StyledSelect } from "@components/Select"; const URL = "/admin/signups"; @@ -31,57 +34,117 @@ const confirmDelete = async (signup: SignupForm) => { } }; -const renderData = (signupForms: SignupForm[]) => { - if (!signupForms || signupForms.length === 0) { +const Renderer: React.FC = () => { + const api: API = { path: APIPath.SIGNUP_FORMS, authenticated: true }; + const { data: signupForms, error } = useSWR(api, fetcher); + + const [sort, setSort] = useState("start_time"); + const [order, setOrder] = useState("descending"); + const [filter, setFilter] = useState("all"); + + const signupFormSort = (a, b) => { + let result = 0; + if (order === "descending") { + if (["start_time", "end_time"].includes(sort)) { + result = new Date(b[sort]).getTime() - new Date(a[sort]).getTime(); + } else if (sort === "id") { + result = b[sort] - a[sort]; + } + } else if (order === "ascending") { + if (["start_time", "end_time"].includes(sort)) { + result = new Date(a[sort]).getTime() - new Date(b[sort]).getTime(); + } else if (sort === "id") { + result = a[sort] - b[sort]; + } + } + return result; + }; + + const dateFilter = (a) => { + let result = true; + + if (filter === "upcoming") { + result = new Date(a.end_time).getTime() > Date.now(); + } else if (filter === "past") { + result = new Date(a.end_time).getTime() < Date.now(); + } + return result; + }; + + useEffect(() => { + }, [sort, order, filter, signupForms]); + + if (error) { + console.error(error); + return ( +
+ Failed loading events. +
+ ); + } + + if (!signupForms?.length) { return
No signup forms.
; } return ( - - - - - - - - - - - - {signupForms.map((signupForm) => ( - - - - - - - +
+ + Sort by: + setSort(e.target.value)}> + + + + + Order: + setOrder(e.target.value)}> + + + + Filter: + setFilter(e.target.value)}> + + + + + +
TitleStart timeEnd timeSign-upsSend email
{signupForm.title_fi}{formatRelative(new Date(signupForm.start_time), new Date())}{formatRelative(new Date(signupForm.end_time), new Date())}ViewSend - confirmDelete(signupForm)}> - Delete - -
+ + + + + + + - ))} - -
TitleStart timeEnd timeSign-upsSend email
+ + + {signupForms.sort(signupFormSort).filter(dateFilter).map((signupForm) => ( + + {signupForm.title_fi} + {formatRelative(new Date(signupForm.start_time), new Date())} + {formatRelative(new Date(signupForm.end_time), new Date())} + View + Send + + confirmDelete(signupForm)}> + Delete + + + + ))} + + + ); }; -const AdminSignupPage: NextPage = () => { - const [forms, setForms] = useState(null); - - useEffect(() => { - SignupApi.getForms(true) - .then((res) => setForms(res)); - }, []); - - return ( - -

Sign-up forms

- - {renderData(forms)} -
- ); -}; +const AdminSignupPage: NextPage = () => ( + +

Sign-up forms

+ + +
+); export default AdminSignupPage; diff --git a/src/views/FrontPage/FrontPageView.tsx b/src/views/FrontPage/FrontPageView.tsx index 0a3f3c2..bd60e98 100644 --- a/src/views/FrontPage/FrontPageView.tsx +++ b/src/views/FrontPage/FrontPageView.tsx @@ -24,6 +24,7 @@ const Fingrid = "https://static.sahkoinsinoorikilta.fi/img/corporate_logos/fingr const Okmetic = "https://static.sahkoinsinoorikilta.fi/img/corporate_logos/okmetic.jpg"; const Nokia = "https://static.sahkoinsinoorikilta.fi/img/corporate_logos/nokia.jpg"; const Granlund = "https://static.sahkoinsinoorikilta.fi/img/corporate_logos/granlund.jpg"; +const GE = "https://static.sahkoinsinoorikilta.fi/img/corporate_logos/GE.png"; interface FrontPageViewProps { events: Event[]; @@ -111,6 +112,9 @@ const FrontPageView: React.FC = ({ events, feed }) => ( Granlund + + GE + Haluatko kuulla lisää yhteistyöstä kanssamme?