From ea279b72957c11d7349e00350fc809fef4da08cc Mon Sep 17 00:00:00 2001 From: Elizabeth Hunt Date: Tue, 4 Apr 2023 13:27:33 -0600 Subject: [PATCH] Link to friend in card --- client/package-lock.json | 60 ++++++++++++ client/package.json | 1 + client/src/components/timerCard.tsx | 29 ++++-- client/src/components/timerHeader.tsx | 129 +++++++++++++++++--------- client/src/routes/login.tsx | 6 +- client/src/routes/timers.tsx | 25 +++-- 6 files changed, 191 insertions(+), 59 deletions(-) diff --git a/client/package-lock.json b/client/package-lock.json index 85564d7..a11531b 100644 --- a/client/package-lock.json +++ b/client/package-lock.json @@ -11,6 +11,7 @@ "chota": "^0.9.2", "react": "^18.2.0", "react-dom": "^18.2.0", + "react-modal": "^3.16.1", "react-router-dom": "^6.10.0", "socket.io-client": "^4.6.1" }, @@ -1044,6 +1045,11 @@ "node": ">=0.8.0" } }, + "node_modules/exenv": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/exenv/-/exenv-1.2.2.tgz", + "integrity": "sha512-Z+ktTxTwv9ILfgKCk32OX3n/doe+OcLTRtqK9pcL+JsP3J1/VW8Uvl4ZjLlKqeW4rzK4oesDOGMEMRIZqtP4Iw==" + }, "node_modules/fsevents": { "version": "2.3.2", "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz", @@ -1205,6 +1211,14 @@ "integrity": "sha512-5GFldHPXVG/YZmFzJvKK2zDSzPKhEp0+ZR5SVaoSag9fsL5YgHbUHDfnG5494ISANDcK4KwPXAx2xqVEydmd7w==", "dev": true }, + "node_modules/object-assign": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", + "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==", + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/path-parse": { "version": "1.0.7", "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", @@ -1241,6 +1255,16 @@ "node": "^10 || ^12 || >=14" } }, + "node_modules/prop-types": { + "version": "15.8.1", + "resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.8.1.tgz", + "integrity": "sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg==", + "dependencies": { + "loose-envify": "^1.4.0", + "object-assign": "^4.1.1", + "react-is": "^16.13.1" + } + }, "node_modules/react": { "version": "18.2.0", "resolved": "https://registry.npmjs.org/react/-/react-18.2.0.tgz", @@ -1264,6 +1288,34 @@ "react": "^18.2.0" } }, + "node_modules/react-is": { + "version": "16.13.1", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz", + "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==" + }, + "node_modules/react-lifecycles-compat": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/react-lifecycles-compat/-/react-lifecycles-compat-3.0.4.tgz", + "integrity": "sha512-fBASbA6LnOU9dOU2eW7aQ8xmYBSXUIWr+UmF9b1efZBazGNO+rcXT/icdKnYm2pTwcRylVUYwW7H1PHfLekVzA==" + }, + "node_modules/react-modal": { + "version": "3.16.1", + "resolved": "https://registry.npmjs.org/react-modal/-/react-modal-3.16.1.tgz", + "integrity": "sha512-VStHgI3BVcGo7OXczvnJN7yT2TWHJPDXZWyI/a0ssFNhGZWsPmB8cF0z33ewDXq4VfYMO1vXgiv/g8Nj9NDyWg==", + "dependencies": { + "exenv": "^1.2.0", + "prop-types": "^15.7.2", + "react-lifecycles-compat": "^3.0.0", + "warning": "^4.0.3" + }, + "engines": { + "node": ">=8" + }, + "peerDependencies": { + "react": "^0.14.0 || ^15.0.0 || ^16 || ^17 || ^18", + "react-dom": "^0.14.0 || ^15.0.0 || ^16 || ^17 || ^18" + } + }, "node_modules/react-refresh": { "version": "0.14.0", "resolved": "https://registry.npmjs.org/react-refresh/-/react-refresh-0.14.0.tgz", @@ -1509,6 +1561,14 @@ } } }, + "node_modules/warning": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/warning/-/warning-4.0.3.tgz", + "integrity": "sha512-rpJyN222KWIvHJ/F53XSZv0Zl/accqHR8et1kpaMTD/fLCRxtV8iX8czMzY7sVZupTI3zcUTg8eycS2kNF9l6w==", + "dependencies": { + "loose-envify": "^1.0.0" + } + }, "node_modules/ws": { "version": "8.11.0", "resolved": "https://registry.npmjs.org/ws/-/ws-8.11.0.tgz", diff --git a/client/package.json b/client/package.json index 8d6f957..fc5a173 100644 --- a/client/package.json +++ b/client/package.json @@ -12,6 +12,7 @@ "chota": "^0.9.2", "react": "^18.2.0", "react-dom": "^18.2.0", + "react-modal": "^3.16.1", "react-router-dom": "^6.10.0", "socket.io-client": "^4.6.1" }, diff --git a/client/src/components/timerCard.tsx b/client/src/components/timerCard.tsx index 89777b8..55fee4a 100644 --- a/client/src/components/timerCard.tsx +++ b/client/src/components/timerCard.tsx @@ -1,19 +1,24 @@ import { ago } from "../utils/ago"; import { useEffect, useState } from "react"; -const replaceReferencedFriendsInName = (name, referencedFriends) => { +const replaceReferencedFriendsInName = (name, referencedFriends, onSelect) => { const friendIdToFriend = referencedFriends.reduce((friendMap, friend) => { friendMap[friend.id] = friend; return friendMap; }, {}); - return name.replaceAll( - /@\<(\d+)\>/g, - (_match, id) => friendIdToFriend[id].name - ); -}; -// name.replaceAll( + return name.split(/(@\<\d+\>)/g).map((s) => { + const matches = /@\<(\d+)\>/g.exec(s); + if (matches) { + const [_match, id] = matches; + const name = friendIdToFriend[id].name; -export default function TimerCard({ timer }) { + return onSelect({ friendId: id })}>{name}; + } + return s; + }); +}; + +export default function TimerCard({ timer, onSelect }) { const [since, setSince] = useState(ago(timer.start)); useEffect(() => { @@ -33,7 +38,13 @@ export default function TimerCard({ timer }) { return (

{since}{" "} - {replaceReferencedFriendsInName(timer.name, timer.referenced_friends)} + {replaceReferencedFriendsInName( + timer.name, + timer.referenced_friends, + onSelect + ).map((s, i) => ( + {s} + ))}

); } diff --git a/client/src/components/timerHeader.tsx b/client/src/components/timerHeader.tsx index fdf4aa8..99f93e9 100644 --- a/client/src/components/timerHeader.tsx +++ b/client/src/components/timerHeader.tsx @@ -1,58 +1,103 @@ +import Modal from "react-modal"; import { useEffect, useState } from "react"; import { useAuthContext } from "../context/authContext"; -export default function TimerHeader({ onSelect }) { - const [friends, setFriends] = useState([]); +const customStyles = { + content: { + top: "50%", + left: "50%", + right: "auto", + bottom: "auto", + marginRight: "-50%", + transform: "translate(-50%, -50%)", + width: "40vw", + maxWidth: "800px", + }, +}; + +Modal.setAppElement("#root"); + +export default function TimerHeader({ friends, selected, onSelect }) { + const [modalOpen, setModalOpen] = useState(false); const { friendName, setSignedIn } = useAuthContext(); - const [selected, setSelected] = useState(); const logout = () => { fetch("/api/auth/logout").then(() => setSignedIn(false)); }; - useEffect(() => { - fetch("/api/auth/friends") - .then((r) => r.json()) - .then((friends) => setFriends(friends)); - }, []); - return ( - +
+ + {friendName} + + + Logout + +
+ + + ); } diff --git a/client/src/routes/login.tsx b/client/src/routes/login.tsx index 015c42b..8446348 100644 --- a/client/src/routes/login.tsx +++ b/client/src/routes/login.tsx @@ -57,7 +57,11 @@ export default function Login() { setErrors([error]); }; - if (signedIn) return ; + + if (signedIn) { + return ; + } + if (!token) return (
diff --git a/client/src/routes/timers.tsx b/client/src/routes/timers.tsx index c561838..69f9bbb 100644 --- a/client/src/routes/timers.tsx +++ b/client/src/routes/timers.tsx @@ -42,6 +42,20 @@ export default function Timers() { namespace: "/events/timers", query: {}, }); + const [friends, setFriends] = useState([]); + const [selected, setSelected] = useState(); + + useEffect(() => { + fetch("/api/auth/friends") + .then((r) => r.json()) + .then((friends) => setFriends(friends)); + }, []); + + const onSelect = (selected: TimersFilter) => { + setSelected(selected); + setEndpoint(makeEndpoint(selected)); + setQuery(selected); + }; useEffect(() => { socket?.on("refreshed", (newTimer: TimerResponse) => { @@ -60,12 +74,7 @@ export default function Timers() { return (
- { - setEndpoint(makeEndpoint(selected)); - setQuery(selected); - }} - /> + {timers ? ( timers .map((timer) => ({ @@ -73,7 +82,9 @@ export default function Timers() { start: new Date(timer.start), })) .sort(({ start: startA }, { start: startB }) => startB - startA) - .map((timer) => ) + .map((timer) => ( + + )) ) : ( <> )}