Skip to content

Commit

Permalink
Merge pull request #9 from JohanGrims/timezone-handling
Browse files Browse the repository at this point in the history
Fixed timezone handling
  • Loading branch information
JohanGrims authored Oct 3, 2024
2 parents 63ec8d4 + 7df1e93 commit d2ca0b8
Show file tree
Hide file tree
Showing 9 changed files with 164 additions and 106 deletions.
14 changes: 10 additions & 4 deletions src/App.jsx
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
import { collection, getDocs } from "firebase/firestore/lite";
import moment from "moment-timezone";
import React from "react";
import { useLoaderData } from "react-router-dom";
import "./App.css";
import { db } from "./firebase";

function App() {
const { activeVotes, expiredVotes, scheduledVotes } = useLoaderData();

Expand All @@ -26,7 +26,7 @@ function App() {
<h1>WaldorfWahlen</h1>
<mdui-list>
{activeVotes.length < 1 && (
<mdui-list-item disabled>Keine aktiven Wahlen</mdui-list-item>
<mdui-list-item disabled>Keine Wahlen</mdui-list-item>
)}
{activeVotes.map((vote) => (
<mdui-list-item
Expand Down Expand Up @@ -109,8 +109,13 @@ export async function loader() {
votes.docs.map((e) => {
let data = e.data();
console.log(data, e.id);
if (Date.now() > data.startTime.seconds * 1000) {
if (data.active && Date.now() < data.endTime.seconds * 1000) {

const now = moment().tz("Europe/Berlin");
const startTime = moment.unix(data.startTime.seconds).tz("Europe/Berlin");
const endTime = moment.unix(data.endTime.seconds).tz("Europe/Berlin");

if (now.isAfter(startTime)) {
if (data.active && now.isBefore(endTime)) {
activeVotes.push({ id: e.id, title: data.title });
} else {
expiredVotes.push({ id: e.id, title: data.title });
Expand All @@ -119,5 +124,6 @@ export async function loader() {
}
scheduledVotes.push({ id: e.id, title: data.title });
});

return { activeVotes, expiredVotes, scheduledVotes };
}
17 changes: 14 additions & 3 deletions src/Gateway.jsx
Original file line number Diff line number Diff line change
@@ -1,19 +1,30 @@
import { doc, getDoc } from "firebase/firestore/lite";
import moment from "moment-timezone";
import React from "react";
import { useLoaderData, useNavigate } from "react-router-dom";
import { db } from "./firebase";

export default function Gateway() {
const { voteData } = useLoaderData();

const navigate = useNavigate();

React.useEffect(() => {
if (!voteData.active || Date.now() > voteData.endTime.seconds * 1000) {
const berlinTime = moment.tz(Date.now(), "Europe/Berlin");

if (
!voteData.active ||
berlinTime.isAfter(
moment.unix(voteData.endTime.seconds).tz("Europe/Berlin")
)
) {
navigate(`/r/${voteData.id}`);
return;
}
if (Date.now() < voteData.startTime.seconds * 1000) {
if (
berlinTime.isBefore(
moment.unix(voteData.startTime.seconds).tz("Europe/Berlin")
)
) {
navigate(`/s/${voteData.id}`);
return;
}
Expand Down
2 changes: 1 addition & 1 deletion src/Result.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ export default function Result() {
<p>
Die Wahl ist beendet. Es sind (noch) keine Ergebnisse online
verfügbar. Bei Fragen oder Problemen melden Sie sich beim
betreuenden Lehrer der Wahl oder den SV-Vertretern Deiner Klasse.
zuständigen Lehrer.
</p>
</div>
<p />
Expand Down
24 changes: 9 additions & 15 deletions src/Scheduled.jsx
Original file line number Diff line number Diff line change
@@ -1,30 +1,24 @@
import moment from "moment-timezone";
import React from "react";
import { useLoaderData, useNavigate } from "react-router-dom";

export default function Scheduled() {
const { vote } = useLoaderData();

const navigate = useNavigate();

return (
<mdui-dialog open headline="Geplante Wahl">
<div className="mdui-prose">
<p>Diese Wahl ist noch nicht aktiv.</p>
<p>
Die Wahl wird am{" "}
{new Date(vote.startTime.seconds * 1000).toLocaleString([], {
hour: "2-digit",
minute: "2-digit",
year: "numeric",
month: "2-digit",
day: "2-digit",
})}{" "}
{moment
.tz(vote.startTime.seconds * 1000, "Europe/Berlin")
.format("DD.MM.YYYY HH:mm")}{" "}
starten und am{" "}
{new Date(vote.endTime.seconds * 1000).toLocaleString([], {
hour: "2-digit",
minute: "2-digit",
year: "numeric",
month: "2-digit",
day: "2-digit",
})}{" "}
{moment
.tz(vote.endTime.seconds * 1000, "Europe/Berlin")
.format("DD.MM.YYYY HH:mm")}{" "}
enden.
</p>
</div>
Expand Down
26 changes: 9 additions & 17 deletions src/Vote.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,10 @@ import React, { useRef } from "react";
import { useLoaderData, useNavigate, useParams } from "react-router-dom";
import { db } from "./firebase";

import moment from "moment-timezone";

import { confirm, snackbar } from "mdui";
import "./vote.css";

export default function Vote() {
const refs = useRef([]);
const urlParams = new URLSearchParams(window.location.search);
Expand Down Expand Up @@ -156,14 +157,9 @@ export default function Vote() {
snackbar({
message:
"Die Wahl startet erst am " +
new Date(startTime.seconds * 1000).toLocaleString("de-DE", {
weekday: "long",
year: "numeric",
month: "long",
day: "numeric",
hour: "numeric",
minute: "numeric",
}),
moment
.tz(startTime.seconds * 1000, "Europe/Berlin")
.format("dddd, D. MMMM YYYY, HH:mm"),
});
navigate("/");
}
Expand Down Expand Up @@ -229,14 +225,10 @@ export default function Vote() {
<h1 className="vote-title">{title}</h1>
<div className="time-label">
Endet am{" "}
{new Date(endTime.seconds * 1000).toLocaleString("de-DE", {
weekday: "long",
year: "numeric",
month: "long",
day: "numeric",
hour: "numeric",
minute: "numeric",
})}
{moment
.tz(endTime.seconds * 1000, "Europe/Berlin")
.locale("de")
.format("dddd, D. MMMM YYYY, HH:mm")}
</div>
</div>
<p />
Expand Down
74 changes: 60 additions & 14 deletions src/admin/NewVote.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,12 @@ import {
setDoc,
Timestamp,
} from "firebase/firestore/lite";
import { confirm, snackbar } from "mdui";
import { confirm, prompt, snackbar } from "mdui";
import moment from "moment-timezone";
import React from "react";
import { useNavigate } from "react-router-dom";
import { db } from "../firebase";
import { generateRandomHash } from "./utils";

export default function NewVote() {
const [title, setTitle] = React.useState("");
const [selectCount, setSelectCount] = React.useState(3);
Expand All @@ -26,6 +26,8 @@ export default function NewVote() {
const [description, setDescription] = React.useState("");
const [max, setMax] = React.useState();

const [id, setId] = React.useState(generateRandomHash());

const navigate = useNavigate();

function addOption() {
Expand All @@ -50,11 +52,14 @@ export default function NewVote() {
async function publish() {
const id = generateRandomHash();
console.log("Generating new vote with id: " + id);
const berlinStartTime = moment.tz(startTime, "Europe/Berlin").toDate();
const berlinEndTime = moment.tz(endTime, "Europe/Berlin").toDate();

const vote = await setDoc(doc(db, "/votes", id), {
title: title,
selectCount: selectCount,
startTime: Timestamp.fromDate(new Date(startTime)),
endTime: Timestamp.fromDate(new Date(endTime)),
startTime: Timestamp.fromDate(berlinStartTime),
endTime: Timestamp.fromDate(berlinEndTime),
active: true,
version: 3,
});
Expand Down Expand Up @@ -152,14 +157,26 @@ export default function NewVote() {
label="Startzeitpunkt"
type="datetime-local"
value={startTime}
onInput={(e) => setStartTime(e.target.value)}
onInput={(e) =>
setStartTime(
moment
.tz(e.target.value, "Europe/Berlin")
.format("YYYY-MM-DDTHH:mm")
)
}
></mdui-text-field>

<mdui-text-field
label="Endzeitpunkt"
type="datetime-local"
value={endTime}
onInput={(e) => setEndTime(e.target.value)}
onInput={(e) =>
setEndTime(
moment
.tz(e.target.value, "Europe/Berlin")
.format("YYYY-MM-DDTHH:mm")
)
}
></mdui-text-field>
</div>
</div>
Expand All @@ -183,19 +200,48 @@ export default function NewVote() {
<p />
</>
))}
<mdui-tooltip
variant="rich"
headline="Extrafeld hinzufügen"
content="Fügen Sie zusätzliche Felder hinzu, um weitere Informationen von Ihren Schülern zu erhalten."
<div
style={{
display: "flex",
justifyContent: "space-between",
}}
>
<mdui-tooltip
variant="rich"
headline="Extrafeld hinzufügen"
content="Fügen Sie zusätzliche Felder hinzu, um weitere Informationen von Ihren Schülern zu erhalten."
>
<mdui-button
icon="add"
onClick={() => setExtraFields([...extraFields, ""])}
variant="text"
>
Extrafeld hinzufügen
</mdui-button>
</mdui-tooltip>
<mdui-button
icon="add"
onClick={() => setExtraFields([...extraFields, ""])}
icon="settings"
variant="text"
end-icon="expand_more"
onClick={() => {
prompt({
headline: "ID der Wahl",
description:
"Ändern Sie die ID der Wahl. Diese erscheint in der URL (waldorfwahlen.de/[ID]). Achten Sie darauf, dass die ID eindeutig ist und keine Sonderzeichen enthält.",
inputType: "text",
textFieldOptions: {
value: id,
onInput: (e) => setId(e.target.value),
placeholder: "spw24",
label: "ID",
},
onConfirm: (value) => setId(value),
});
}}
>
Extrafeld hinzufügen
Erweitert
</mdui-button>
</mdui-tooltip>
</div>

<p />
<mdui-divider></mdui-divider>
Expand Down
50 changes: 26 additions & 24 deletions src/admin/Overview.jsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { collection, getDocs } from "firebase/firestore/lite";
import moment from "moment-timezone";
import { useLoaderData, useNavigate } from "react-router-dom";
import { db } from "../firebase";

export default function Overview() {
const { votes } = useLoaderData();

Expand All @@ -18,29 +18,31 @@ export default function Overview() {
gap: "20px",
}}
>
{votes.map((vote) => (
<mdui-card
key={vote.id}
variant="filled"
style={{ padding: "20px" }}
clickable
onClick={() => navigate(`/admin/${vote.id}`)}
>
<h3>{vote.title}</h3>
<p>
<mdui-icon
style={{ fontSize: "50px" }}
name={
vote.active && vote.endTime.seconds * 1000 > Date.now()
? vote.startTime.seconds * 1000 < Date.now()
? "event_available"
: "event"
: "done_all"
}
></mdui-icon>
</p>
</mdui-card>
))}
{votes.map((vote) => {
const now = moment();
const startTime = moment.unix(vote.startTime.seconds);
const endTime = moment.unix(vote.endTime.seconds);
const isActive =
vote.active && endTime.isAfter(now) && startTime.isBefore(now);

return (
<mdui-card
key={vote.id}
variant="filled"
style={{ padding: "20px" }}
clickable
onClick={() => navigate(`/admin/${vote.id}`)}
>
<h3>{vote.title}</h3>
<p>
<mdui-icon
style={{ fontSize: "50px" }}
name={isActive ? "event_available" : "done_all"}
></mdui-icon>
</p>
</mdui-card>
);
})}
<mdui-card
variant="outlined"
style={{ padding: "20px" }}
Expand Down
Loading

0 comments on commit d2ca0b8

Please sign in to comment.