wire new alarm modal to storage and botch 'reactivity'

main
Kay 3 weeks ago
parent bbb09ed06e
commit 365c2382f1

1
.gitignore vendored

@ -12,6 +12,7 @@
# production
/build
/dist
# misc
.DS_Store

@ -25,6 +25,7 @@
"@types/react-router": "^5.1.20",
"@types/react-router-dom": "^5.3.3",
"ionicons": "^7.0.0",
"moment": "^2.29.4",
"react": "^18.2.0",
"react-dom": "^18.2.0",
"react-intl": "^6.4.2",
@ -47,6 +48,7 @@
"eslint": "^8.35.0",
"eslint-plugin-react": "^7.32.2",
"jsdom": "^21.1.0",
"terser": "^5.17.4",
"typescript": "^4.9.3",
"vite": "^4.1.0",
"vitest": "^0.29.2"

@ -59,22 +59,7 @@ const App: React.FC = () => {
initializeStore().then(async () => {
// TODO: testing data, remove later
if (!(await store.get("alarms"))) {
await store.set("alarms", [
{
uuid: v4(),
days: [1, 2, 3, 4, 5],
note: "hello world",
enabled: true,
time: "08:45",
},
{
uuid: v4(),
days: [6, 7],
note: "goodbye world",
enabled: false,
time: "10:00",
},
]);
await store.set("alarms", []);
}
if (!(await store.get("settings"))) {
await store.set("settings", {

@ -15,32 +15,68 @@ import "./AddAlarm.css";
import { OverlayEventDetail } from "@ionic/core/components";
import { useRef, useState } from "react";
import moment from "moment";
import { FormattedMessage, useIntl } from "react-intl";
const AddAlarm: React.FC = () => {
import { v4 } from "uuid";
import type { Storage } from "@ionic/storage";
import { DaysMap } from "../utils/mapDays";
interface Props {
store: Storage;
setShouldRefresh: Function;
}
const AddAlarm: React.FC<Props> = ({ store, setShouldRefresh }) => {
const modal = useRef<HTMLIonModalElement>(null);
const input = useRef<HTMLIonInputElement>(null);
const noteRef = useRef<HTMLIonInputElement>(null);
const timeRef = useRef<HTMLIonDatetimeElement>(null);
const [message, setMessage] = useState(
"This modal example uses triggers to automatically open a modal when the button is clicked."
);
const [buttonsState, setButtonsState] = useState({
1: false,
2: false,
3: false,
4: false,
5: false,
6: false,
7: false,
});
function confirm() {
modal.current?.dismiss(input.current?.value, "confirm");
async function confirm() {
modal.current?.dismiss(noteRef.current?.value, "confirm");
await store.set("alarms", [
...(await store.get("alarms")),
{
uuid: v4(),
time: moment(timeRef.current?.value).format("HH:mm") || moment().format("HH:mm"),
days: Object.keys(buttonsState)
.filter((day) => buttonsState[Number(day) as keyof DaysMap] === true)
.map((day) => parseInt(day)),
note: noteRef.current?.value,
enabled: true,
},
]);
}
function onWillDismiss(ev: CustomEvent<OverlayEventDetail>) {
if (ev.detail.role === "confirm") {
setMessage(`Hello, ${ev.detail.data}!`);
setShouldRefresh(true);
}
}
function buttonToggle(dayKey: keyof DaysMap, event: any) {
// console.log(event);
setButtonsState({ ...buttonsState, [dayKey]: !buttonsState[dayKey] });
}
const buttonStateToColor = (state: boolean) => {
return state ? "success" : "danger";
};
return (
<IonModal
ref={modal}
onWillDismiss={(ev) => onWillDismiss(ev)}
trigger="add-alarm"
>
<IonModal ref={modal} onWillDismiss={(ev) => onWillDismiss(ev)} trigger="add-alarm">
<IonHeader>
<IonToolbar>
<IonButtons slot="start">
@ -66,32 +102,32 @@ const AddAlarm: React.FC = () => {
</IonText>
<IonDatetimeButton datetime="datetime"></IonDatetimeButton>
<IonModal keepContentsMounted={true}>
<IonDatetime id="datetime" presentation="time"></IonDatetime>
<IonDatetime id="datetime" presentation="time" ref={timeRef}></IonDatetime>
</IonModal>
<IonText>
<h2>
<FormattedMessage id="days" />
</h2>
</IonText>
<IonButton>
<IonButton onClick={(ev) => buttonToggle(1, ev)} color={buttonStateToColor(buttonsState[1])}>
<FormattedMessage id="mon" />
</IonButton>
<IonButton>
<IonButton onClick={(ev) => buttonToggle(2, ev)} color={buttonStateToColor(buttonsState[2])}>
<FormattedMessage id="tue" />
</IonButton>
<IonButton>
<IonButton onClick={(ev) => buttonToggle(3, ev)} color={buttonStateToColor(buttonsState[3])}>
<FormattedMessage id="wed" />
</IonButton>
<IonButton>
<IonButton onClick={(ev) => buttonToggle(4, ev)} color={buttonStateToColor(buttonsState[4])}>
<FormattedMessage id="thu" />
</IonButton>
<IonButton>
<IonButton onClick={(ev) => buttonToggle(5, ev)} color={buttonStateToColor(buttonsState[5])}>
<FormattedMessage id="fri" />
</IonButton>
<IonButton>
<IonButton onClick={(ev) => buttonToggle(6, ev)} color={buttonStateToColor(buttonsState[6])}>
<FormattedMessage id="sat" />
</IonButton>
<IonButton>
<IonButton onClick={(ev) => buttonToggle(7, ev)} color={buttonStateToColor(buttonsState[7])}>
<FormattedMessage id="sun" />
</IonButton>
<IonText>
@ -99,11 +135,7 @@ const AddAlarm: React.FC = () => {
<FormattedMessage id="note" />
</h2>
</IonText>
<IonInput
ref={input}
type="text"
placeholder={useIntl().formatMessage({ id: "alarmNote" })}
></IonInput>
<IonInput ref={noteRef} type="text" placeholder={useIntl().formatMessage({ id: "alarmNote" })}></IonInput>
</IonContent>
</IonModal>
);

@ -1,13 +1,4 @@
import {
IonContent,
IonHeader,
IonPage,
IonTitle,
IonToolbar,
IonFabButton,
IonIcon,
IonFab,
} from "@ionic/react";
import { IonContent, IonHeader, IonPage, IonTitle, IonToolbar, IonFabButton, IonIcon, IonFab } from "@ionic/react";
import { add } from "ionicons/icons";
import type { Storage } from "@ionic/storage";
@ -24,16 +15,25 @@ interface Props {
}
const Alarms: React.FC<Props> = ({ store }) => {
// feels yikes
// not sure if theres a cleaner way to let a parent know a child has changed stuff
// tried [store] in the useEffect dependencies but it doesn't work
const [shouldRefresh, setShouldRefresh] = useState(true);
const [alarms, setAlarms] = useState([]);
useEffect(() => {
const getAlarms = async ({ store }: Props) => {
const alarms = await store.get("alarms");
setAlarms(alarms);
};
if (shouldRefresh) {
const getAlarms = async ({ store }: Props) => {
const alarms = await store.get("alarms");
setAlarms(alarms);
};
getAlarms({ store });
setShouldRefresh(false);
}
}, [shouldRefresh]);
getAlarms({ store });
}, []);
return (
<IonPage>
<IonHeader>
@ -59,7 +59,7 @@ const Alarms: React.FC<Props> = ({ store }) => {
<IonIcon aria-hidden="true" icon={add} />
</IonFabButton>
</IonFab>
<AddAlarm />
<AddAlarm store={store} setShouldRefresh={setShouldRefresh} />
</IonContent>
</IonPage>
);

@ -1411,6 +1411,14 @@
resolved "https://registry.yarnpkg.com/@jridgewell/set-array/-/set-array-1.1.2.tgz#7c6cf998d6d20b914c0a55a91ae928ff25965e72"
integrity sha512-xnkseuNADM0gt2bs+BvhO0p78Mk762YnZdsuzFV018NoG1Sj1SCQvpSqa7XUaTam5vAGasABV9qXASMKnFMwMw==
"@jridgewell/source-map@^0.3.2":
version "0.3.3"
resolved "https://registry.yarnpkg.com/@jridgewell/source-map/-/source-map-0.3.3.tgz#8108265659d4c33e72ffe14e33d6cc5eb59f2fda"
integrity sha512-b+fsZXeLYi9fEULmfBrhxn4IrPlINf8fiNarzTof004v3lFdntdwa9PF7vFJqm3mg7s+ScJMxXaE3Acp1irZcg==
dependencies:
"@jridgewell/gen-mapping" "^0.3.0"
"@jridgewell/trace-mapping" "^0.3.9"
"@jridgewell/sourcemap-codec@1.4.14":
version "1.4.14"
resolved "https://registry.yarnpkg.com/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.14.tgz#add4c98d341472a289190b424efbdb096991bb24"
@ -1763,7 +1771,7 @@ acorn-walk@^8.0.2, acorn-walk@^8.2.0:
resolved "https://registry.yarnpkg.com/acorn-walk/-/acorn-walk-8.2.0.tgz#741210f2e2426454508853a2f44d0ab83b7f69c1"
integrity sha512-k+iyHEuPgSw6SbuDpGQM+06HQUa04DZ3o+F6CSzXMvvI5KMvnaEqXe+YVe555R9nn6GPt404fos4wcgpw12SDA==
acorn@^8.1.0, acorn@^8.8.0, acorn@^8.8.1, acorn@^8.8.2:
acorn@^8.1.0, acorn@^8.5.0, acorn@^8.8.0, acorn@^8.8.1, acorn@^8.8.2:
version "8.8.2"
resolved "https://registry.yarnpkg.com/acorn/-/acorn-8.8.2.tgz#1b2f25db02af965399b9776b0c2c391276d37c4a"
integrity sha512-xjIYgE8HBrkpd/sJqOGNspf8uHG+NOHGOw6a/Urj8taM2EXfdNAH2oFcPeIFfsv3+kz/mJrS5VuMqbNLjCa2vw==
@ -2048,6 +2056,11 @@ buffer-crc32@~0.2.3:
resolved "https://registry.yarnpkg.com/buffer-crc32/-/buffer-crc32-0.2.13.tgz#0d333e3f00eac50aa1454abd30ef8c2a5d9a7242"
integrity sha512-VO9Ht/+p3SN7SKWqcrgEzjGbRSJYTx+Q1pTQC0wrWqHx0vpJraQ6GtHx8tvcg1rlK1byhU5gccxgOgj7B0TDkQ==
buffer-from@^1.0.0:
version "1.1.2"
resolved "https://registry.yarnpkg.com/buffer-from/-/buffer-from-1.1.2.tgz#2b146a6fd72e80b4f55d255f35ed59a3a9a41bd5"
integrity sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==
buffer@^5.6.0:
version "5.7.1"
resolved "https://registry.yarnpkg.com/buffer/-/buffer-5.7.1.tgz#ba62e7c13133053582197160851a8f648e99eed0"
@ -2220,6 +2233,11 @@ combined-stream@^1.0.6, combined-stream@^1.0.8, combined-stream@~1.0.6:
dependencies:
delayed-stream "~1.0.0"
commander@^2.20.0:
version "2.20.3"
resolved "https://registry.yarnpkg.com/commander/-/commander-2.20.3.tgz#fd485e84c03eb4881c20722ba48035e8531aeb33"
integrity sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==
commander@^6.2.1:
version "6.2.1"
resolved "https://registry.yarnpkg.com/commander/-/commander-6.2.1.tgz#0792eb682dfbc325999bb2b84fddddba110ac73c"
@ -3973,6 +3991,11 @@ mlly@^1.1.0, mlly@^1.2.0:
pkg-types "^1.0.3"
ufo "^1.1.2"
moment@^2.29.4:
version "2.29.4"
resolved "https://registry.yarnpkg.com/moment/-/moment-2.29.4.tgz#3dbe052889fe7c1b2ed966fcb3a77328964ef108"
integrity sha512-5LC9SOxjSc2HF6vO2CyuTDNivEdoz2IvyJJGj6X8DJ0eFyfszE0QiEd+iXmBvUP3WHxSjFH/vIsA0EN00cgr8w==
ms@2.1.2:
version "2.1.2"
resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.2.tgz#d09d1f357b443f493382a8eb3ccd183872ae6009"
@ -4748,7 +4771,15 @@ source-map-js@^1.0.2:
resolved "https://registry.yarnpkg.com/source-map-js/-/source-map-js-1.0.2.tgz#adbc361d9c62df380125e7f161f71c826f1e490c"
integrity sha512-R0XvVJ9WusLiqTCEiGCmICCMplcCkIwwR11mOSD9CR5u+IXYdiseeEuXCVAjS54zqwkLcPNnmU4OeJ6tUrWhDw==
source-map@^0.6.1, source-map@~0.6.1:
source-map-support@~0.5.20:
version "0.5.21"
resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.5.21.tgz#04fe7c7f9e1ed2d662233c28cb2b35b9f63f6e4f"
integrity sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==
dependencies:
buffer-from "^1.0.0"
source-map "^0.6.0"
source-map@^0.6.0, source-map@^0.6.1, source-map@~0.6.1:
version "0.6.1"
resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.6.1.tgz#74722af32e9614e9c287a8d0bbde48b5e2f1a263"
integrity sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==
@ -4949,6 +4980,16 @@ tar@^6.1.11:
mkdirp "^1.0.3"
yallist "^4.0.0"
terser@^5.17.4:
version "5.17.4"
resolved "https://registry.yarnpkg.com/terser/-/terser-5.17.4.tgz#b0c2d94897dfeba43213ed5f90ed117270a2c696"
integrity sha512-jcEKZw6UPrgugz/0Tuk/PVyLAPfMBJf5clnGueo45wTweoV8yh7Q7PEkhkJ5uuUbC7zAxEcG3tqNr1bstkQ8nw==
dependencies:
"@jridgewell/source-map" "^0.3.2"
acorn "^8.5.0"
commander "^2.20.0"
source-map-support "~0.5.20"
text-table@^0.2.0:
version "0.2.0"
resolved "https://registry.yarnpkg.com/text-table/-/text-table-0.2.0.tgz#7f5ee823ae805207c00af2df4a84ec3fcfa570b4"

Loading…
Cancel
Save