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}
+ ))}