Fix autocomplete, create new timer
This commit is contained in:
parent
ea279b7295
commit
a862ad4d3b
49
client/package-lock.json
generated
49
client/package-lock.json
generated
@ -11,6 +11,7 @@
|
||||
"chota": "^0.9.2",
|
||||
"react": "^18.2.0",
|
||||
"react-dom": "^18.2.0",
|
||||
"react-mentions": "^4.4.7",
|
||||
"react-modal": "^3.16.1",
|
||||
"react-router-dom": "^6.10.0",
|
||||
"socket.io-client": "^4.6.1"
|
||||
@ -330,6 +331,14 @@
|
||||
"@babel/core": "^7.0.0-0"
|
||||
}
|
||||
},
|
||||
"node_modules/@babel/runtime": {
|
||||
"version": "7.4.5",
|
||||
"resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.4.5.tgz",
|
||||
"integrity": "sha512-TuI4qpWZP6lGOGIuGWtp9sPluqYICmbk8T/1vpSysqJxRPkudh/ofFWyqdcMsDf2s7KvDL4/YHgKyvcS3g9CJQ==",
|
||||
"dependencies": {
|
||||
"regenerator-runtime": "^0.13.2"
|
||||
}
|
||||
},
|
||||
"node_modules/@babel/template": {
|
||||
"version": "7.20.7",
|
||||
"resolved": "https://registry.npmjs.org/@babel/template/-/template-7.20.7.tgz",
|
||||
@ -1109,6 +1118,14 @@
|
||||
"node": ">=4"
|
||||
}
|
||||
},
|
||||
"node_modules/invariant": {
|
||||
"version": "2.2.4",
|
||||
"resolved": "https://registry.npmjs.org/invariant/-/invariant-2.2.4.tgz",
|
||||
"integrity": "sha512-phJfQVBuaJM5raOpJjSfkiD6BpbCE4Ns//LaXl6wGYtUBY83nWS6Rf9tXm2e8VaK60JEjYldbPif/A2B1C2gNA==",
|
||||
"dependencies": {
|
||||
"loose-envify": "^1.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/is-core-module": {
|
||||
"version": "2.11.0",
|
||||
"resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.11.0.tgz",
|
||||
@ -1298,6 +1315,21 @@
|
||||
"resolved": "https://registry.npmjs.org/react-lifecycles-compat/-/react-lifecycles-compat-3.0.4.tgz",
|
||||
"integrity": "sha512-fBASbA6LnOU9dOU2eW7aQ8xmYBSXUIWr+UmF9b1efZBazGNO+rcXT/icdKnYm2pTwcRylVUYwW7H1PHfLekVzA=="
|
||||
},
|
||||
"node_modules/react-mentions": {
|
||||
"version": "4.4.7",
|
||||
"resolved": "https://registry.npmjs.org/react-mentions/-/react-mentions-4.4.7.tgz",
|
||||
"integrity": "sha512-VNriu2h/uOB+RS0mwZgPG2Vf+UtdDvRh5zbXa2TNc1WqacKuNDgTdhlbo9LEOZRBxRzIeTUYQmYJ7p9M9rDHqQ==",
|
||||
"dependencies": {
|
||||
"@babel/runtime": "7.4.5",
|
||||
"invariant": "^2.2.4",
|
||||
"prop-types": "^15.5.8",
|
||||
"substyle": "^9.1.0"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"react": ">=16.8.3",
|
||||
"react-dom": ">=16.8.3"
|
||||
}
|
||||
},
|
||||
"node_modules/react-modal": {
|
||||
"version": "3.16.1",
|
||||
"resolved": "https://registry.npmjs.org/react-modal/-/react-modal-3.16.1.tgz",
|
||||
@ -1355,6 +1387,11 @@
|
||||
"react-dom": ">=16.8"
|
||||
}
|
||||
},
|
||||
"node_modules/regenerator-runtime": {
|
||||
"version": "0.13.11",
|
||||
"resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.11.tgz",
|
||||
"integrity": "sha512-kY1AZVr2Ra+t+piVaJ4gxaFaReZVH40AKNo7UCX6W+dEwBo/2oZJzqfuN1qLq1oL45o56cPaTXELwrTh8Fpggg=="
|
||||
},
|
||||
"node_modules/resolve": {
|
||||
"version": "1.22.1",
|
||||
"resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.1.tgz",
|
||||
@ -1440,6 +1477,18 @@
|
||||
"node": ">=0.10.0"
|
||||
}
|
||||
},
|
||||
"node_modules/substyle": {
|
||||
"version": "9.4.1",
|
||||
"resolved": "https://registry.npmjs.org/substyle/-/substyle-9.4.1.tgz",
|
||||
"integrity": "sha512-VOngeq/W1/UkxiGzeqVvDbGDPM8XgUyJVWjrqeh+GgKqspEPiLYndK+XRcsKUHM5Muz/++1ctJ1QCF/OqRiKWA==",
|
||||
"dependencies": {
|
||||
"@babel/runtime": "^7.3.4",
|
||||
"invariant": "^2.2.4"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"react": ">=16.8.3"
|
||||
}
|
||||
},
|
||||
"node_modules/supports-color": {
|
||||
"version": "5.5.0",
|
||||
"resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz",
|
||||
|
@ -12,6 +12,7 @@
|
||||
"chota": "^0.9.2",
|
||||
"react": "^18.2.0",
|
||||
"react-dom": "^18.2.0",
|
||||
"react-mentions": "^4.4.7",
|
||||
"react-modal": "^3.16.1",
|
||||
"react-router-dom": "^6.10.0",
|
||||
"socket.io-client": "^4.6.1"
|
||||
|
@ -1,36 +1,55 @@
|
||||
import Modal from "react-modal";
|
||||
import { useEffect, useState } from "react";
|
||||
import { Mention, MentionsInput } from "react-mentions";
|
||||
import { useAuthContext } from "../context/authContext";
|
||||
|
||||
const customStyles = {
|
||||
content: {
|
||||
top: "50%",
|
||||
left: "50%",
|
||||
right: "auto",
|
||||
bottom: "auto",
|
||||
marginRight: "-50%",
|
||||
transform: "translate(-50%, -50%)",
|
||||
width: "40vw",
|
||||
maxWidth: "800px",
|
||||
},
|
||||
};
|
||||
import mentionStyles from "../styles/mention";
|
||||
import modalStyles from "../styles/modal";
|
||||
|
||||
Modal.setAppElement("#root");
|
||||
|
||||
export default function TimerHeader({ friends, selected, onSelect }) {
|
||||
const [modalOpen, setModalOpen] = useState(false);
|
||||
const [newTimerName, setNewTimerName] = useState("");
|
||||
const [errors, setErrors] = useState([]);
|
||||
const { friendName, setSignedIn } = useAuthContext();
|
||||
|
||||
const logout = () => {
|
||||
fetch("/api/auth/logout").then(() => setSignedIn(false));
|
||||
};
|
||||
|
||||
const createTimer = (e) => {
|
||||
e.preventDefault();
|
||||
|
||||
fetch("/api/timers", {
|
||||
method: "POST",
|
||||
body: JSON.stringify({
|
||||
name: newTimerName.replaceAll(
|
||||
/\[@[\w\d\s]+\]\((\@<\d+>)\)/g,
|
||||
(_match, atId) => atId
|
||||
),
|
||||
}),
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
},
|
||||
})
|
||||
.then((r) => r.json())
|
||||
.then((r) => {
|
||||
if (r.message) {
|
||||
setErrors([r.message]);
|
||||
return;
|
||||
}
|
||||
setNewTimerName("");
|
||||
setErrors([]);
|
||||
setModalOpen(false);
|
||||
});
|
||||
};
|
||||
|
||||
return (
|
||||
<>
|
||||
<Modal
|
||||
isOpen={modalOpen}
|
||||
onRequestClose={() => setModalOpen(false)}
|
||||
style={customStyles}
|
||||
style={modalStyles}
|
||||
>
|
||||
<div id="createTimerModal">
|
||||
<div>
|
||||
@ -42,13 +61,35 @@ export default function TimerHeader({ friends, selected, onSelect }) {
|
||||
marginBottom: "1rem",
|
||||
}}
|
||||
>
|
||||
<span>New Timer</span>
|
||||
<h4 style={{ margin: "none" }}>New Timer</h4>
|
||||
|
||||
<a onClick={() => setModalOpen(false)} className="button outline">
|
||||
×
|
||||
</a>
|
||||
</div>
|
||||
<div>
|
||||
<form>
|
||||
<form onSubmit={createTimer}>
|
||||
<MentionsInput
|
||||
style={mentionStyles}
|
||||
value={newTimerName}
|
||||
onChange={(e) => setNewTimerName(e.target.value)}
|
||||
>
|
||||
<Mention
|
||||
data={friends.map(({ id, name }) => ({
|
||||
id: `@<${id}>`,
|
||||
display: `@${name}`,
|
||||
}))}
|
||||
/>
|
||||
</MentionsInput>
|
||||
{errors.length ? (
|
||||
errors.map((error, i) => (
|
||||
<div key={i} className="text-error">
|
||||
{error}
|
||||
</div>
|
||||
))
|
||||
) : (
|
||||
<></>
|
||||
)}
|
||||
<button type="submit">Add</button>
|
||||
</form>
|
||||
</div>
|
||||
|
@ -31,9 +31,11 @@ export default function Login() {
|
||||
|
||||
const getTokenFormSubmission = async (e) => {
|
||||
e.preventDefault();
|
||||
const { error, token } = await requestTokenSubmit(e.target.name.value);
|
||||
if (error) {
|
||||
setErrors([error]);
|
||||
const { error, message, token } = await requestTokenSubmit(
|
||||
e.target.name.value
|
||||
);
|
||||
if (error && message) {
|
||||
setErrors([message]);
|
||||
return;
|
||||
}
|
||||
setErrors([]);
|
||||
@ -42,9 +44,8 @@ export default function Login() {
|
||||
|
||||
const signTokenFormSubmission = async (e) => {
|
||||
e.preventDefault();
|
||||
const { error, token, expiration, friend } = await submitSignedToken(
|
||||
e.target.signature.value
|
||||
);
|
||||
const { error, message, token, expiration, friend } =
|
||||
await submitSignedToken(e.target.signature.value);
|
||||
|
||||
if (token) {
|
||||
setSignedIn(true);
|
||||
@ -55,7 +56,9 @@ export default function Login() {
|
||||
return;
|
||||
}
|
||||
|
||||
setErrors([error]);
|
||||
if (error & message) {
|
||||
setErrors([message]);
|
||||
}
|
||||
};
|
||||
|
||||
if (signedIn) {
|
||||
|
47
client/src/styles/mention.ts
Normal file
47
client/src/styles/mention.ts
Normal file
@ -0,0 +1,47 @@
|
||||
export default {
|
||||
control: {
|
||||
backgroundColor: "#fff",
|
||||
fontSize: 16,
|
||||
// fontWeight: 'normal',
|
||||
},
|
||||
"&multiLine": {
|
||||
control: {
|
||||
fontFamily: "monospace",
|
||||
minHeight: 63,
|
||||
},
|
||||
highlighter: {
|
||||
padding: 9,
|
||||
border: "1px solid transparent",
|
||||
},
|
||||
input: {
|
||||
padding: 9,
|
||||
border: "1px solid silver",
|
||||
},
|
||||
},
|
||||
"&singleLine": {
|
||||
display: "inline-block",
|
||||
width: 180,
|
||||
highlighter: {
|
||||
padding: 1,
|
||||
border: "2px inset transparent",
|
||||
},
|
||||
input: {
|
||||
padding: 1,
|
||||
border: "2px inset",
|
||||
},
|
||||
},
|
||||
suggestions: {
|
||||
list: {
|
||||
backgroundColor: "white",
|
||||
border: "1px solid rgba(0,0,0,0.15)",
|
||||
fontSize: 16,
|
||||
},
|
||||
item: {
|
||||
padding: "5px 15px",
|
||||
borderBottom: "1px solid rgba(0,0,0,0.15)",
|
||||
"&focused": {
|
||||
backgroundColor: "#cee4e5",
|
||||
},
|
||||
},
|
||||
},
|
||||
};
|
12
client/src/styles/modal.ts
Normal file
12
client/src/styles/modal.ts
Normal file
@ -0,0 +1,12 @@
|
||||
export default {
|
||||
content: {
|
||||
top: "50%",
|
||||
left: "50%",
|
||||
right: "auto",
|
||||
bottom: "auto",
|
||||
marginRight: "-50%",
|
||||
transform: "translate(-50%, -50%)",
|
||||
width: "40vw",
|
||||
maxWidth: "800px",
|
||||
},
|
||||
};
|
Loading…
Reference in New Issue
Block a user