Compare commits

..

No commits in common. "7495bf896e539f86c4cd0448839bf6780d08a1d9" and "6cb0cc1740c9d5ecc93d8cc9a921969de841083a" have entirely different histories.

1 changed files with 133 additions and 164 deletions

View File

@ -1,175 +1,144 @@
import { useEffect, useState } from "react"; import { useState } from "react";
import { useUser } from "../user-context"; import { useUser } from "../user-context";
const ratings = [ const ratings = [
{ value: 0, emoji: "😭" }, { value: 0, emoji: "😭" },
{ value: 1, emoji: "😕" }, { value: 1, emoji: "😕" },
{ value: 2, emoji: "🙂" }, { value: 2, emoji: "🙂" },
{ value: 3, emoji: "🤩" }, { value: 3, emoji: "🤩" },
]; ]
function ChapterFeedback({ chapter }: { chapter: string }) { function ChapterFeedback({ chapter }: { chapter: string }) {
const { user } = useUser(); const { user } = useUser();
const [rating, setRating] = useState<number | undefined>(undefined); const [rating, setRating] = useState<number | undefined>(undefined);
const [anonymous, setAnonymous] = useState<boolean>(false); const [anonymous, setAnonymous] = useState<boolean>(false);
const [feedback, setFeedback] = useState<string>(""); const [feedback, setFeedback] = useState<string>("");
const [feedbackStatus, setFeedbackStatus] = useState< const [feedbackStatus, setFeedbackStatus] = useState<"unsent" | "sending" | "sent">("unsent")
"unsent" | "sending" | "sent" function handleRatingClick(v: number) {
>("unsent"); setRating(o => o === v ? undefined : v);
useEffect(() => { }
setFeedbackStatus("unsent"); // automatic sending of emoji click feedback if someone leaves the chapter without
setFeedback(""); // filling in and sending the feedback textbox
setRating(undefined); // not doing this yet because not sure if it's a clean setup like "componentWillUnmount"
}, [chapter]); // or if it unecessarily unmounts and re-renders
function handleRatingClick(v: number) { // useEffect(() => {
setRating((o) => (o === v ? undefined : v)); // return () => {
} // if (rating === undefined || feedbackStatus === "sent") return;
// automatic sending of emoji click feedback if someone leaves the chapter without // fetch("https://account.lingdocs.com/feedback", {
// filling in and sending the feedback textbox // method: "PUT",
// not doing this yet because not sure if it's a clean setup like "componentWillUnmount" // credentials: "include",
// or if it unecessarily unmounts and re-renders // headers: {
// useEffect(() => { // "Content-Type": "application/json",
// return () => { // },
// if (rating === undefined || feedbackStatus === "sent") return; // body: JSON.stringify({ feedback: "", rating }),
// fetch("https://account.lingdocs.com/feedback", { // }).catch(() => {
// method: "PUT", // console.error("couldn't send chapter feedback");
// credentials: "include", // });
// headers: { // }
// "Content-Type": "application/json", // // eslint-disable-next-line
// }, // }, []);
// body: JSON.stringify({ feedback: "", rating }), function handleSendFeedback() {
// }).catch(() => { const toSend = {
// console.error("couldn't send chapter feedback"); chapter,
// }); feedback,
// } rating,
// // eslint-disable-next-line anonymous,
// }, []); ts: Date.now(),
function handleSendFeedback() { };
const toSend = { setFeedbackStatus("sending");
chapter, fetch("https://account.lingdocs.com/feedback", {
feedback, method: "PUT",
rating, credentials: "include",
anonymous, headers: {
ts: Date.now(), "Content-Type": "application/json",
}; },
setFeedbackStatus("sending"); body: JSON.stringify(toSend),
fetch("https://account.lingdocs.com/feedback", { }).then(res => res.json()).then(res => {
method: "PUT", if (res.ok) {
credentials: "include", setFeedbackStatus("sent");
headers: { } else {
"Content-Type": "application/json", setFeedbackStatus("unsent");
}, alert("error sending feedback");
body: JSON.stringify(toSend), }
}) }).catch(() => {
.then((res) => res.json()) setFeedbackStatus("unsent");
.then((res) => { alert("connect to the internet to send feedback");
if (res.ok) { });
setFeedbackStatus("sent"); }
} else { if (feedbackStatus === "sent") {
setFeedbackStatus("unsent"); return <div>
alert("error sending feedback"); <hr/>
} <div className="d-flex flex-row justify-content-center align-items-center my-3" style={{ height: "6rem" }}>
}) <div className="lead">Thanks for your feedback!</div>
.catch(() => {
setFeedbackStatus("unsent");
alert("connect to the internet to send feedback");
});
}
if (feedbackStatus === "sent") {
return (
<div>
<hr />
<div
className="d-flex flex-row justify-content-center align-items-center my-3"
style={{ height: "6rem" }}
>
<div className="lead">Thanks for your feedback!</div>
</div>
<hr />
</div>
);
}
return (
<div>
<hr />
<div className="my-4">
<div className="text-center">Was this chapter helpful?</div>
<div className="d-flex flex-row align-items-center justify-content-center">
{ratings.map(({ value, emoji }) => (
<div
key={value}
className="mx-2 clickable"
style={
rating !== value
? {
filter: "grayscale(100%)",
fontSize: "2.25rem",
}
: { fontSize: "2.75rem" }
}
onClick={() => handleRatingClick(value)}
>
{emoji}
</div> </div>
))} <hr/>
</div> </div>
{rating !== undefined && ( }
<div style={{ maxWidth: "30rem", margin: "0 auto" }}> return <div>
<div className="form-group"> <hr />
<label htmlFor="feedbackText" className="text-left"> <div className="my-4">
Feedback: <div className="text-center">Was this chapter helpful?</div>
</label> <div className="d-flex flex-row align-items-center justify-content-center">
<textarea {ratings.map(({ value, emoji }) => (
className="form-control" <div
id="feedbackText" key={value}
placeholder="Share more or leave blank" className="mx-2 clickable"
rows={3} style={rating !== value
value={feedback} ? {
onChange={(e) => setFeedback(e.target.value)} filter: "grayscale(100%)",
/> fontSize: "2.25rem",
} : { fontSize: "2.75rem" }}
onClick={() => handleRatingClick(value)}
>
{emoji}
</div>
))}
</div> </div>
<div className="d-flex flex-row justify-content-between align-items-center"> {rating !== undefined && <div style={{ maxWidth: "30rem", margin: "0 auto" }}>
<div className="small"> <div className="form-group">
{user && !anonymous <label htmlFor="feedbackText" className="text-left">Feedback:</label>
? `Private feedback will be sent as "${user.name}"` <textarea
: `Private feedback will be anonymous`} className="form-control"
</div> id="feedbackText"
<div className="d-flex flex-row align-items-center"> placeholder="Share more or leave blank"
{feedbackStatus === "sending" && ( rows={3}
<div className="mr-3"> value={feedback}
<samp>sending...</samp> onChange={e => setFeedback(e.target.value)}
</div> />
)}
<div>
<button
className="btn btn-sm btn-primary"
onClick={handleSendFeedback}
>
Send
</button>
</div> </div>
</div> <div className="d-flex flex-row justify-content-between align-items-center">
</div> <div className="small">
{user && ( {(user && !anonymous)
<div className="form-check small"> ? `Private feedback will be sent as "${user.name}"`
<input : `Private feedback will be anonymous`}
className="form-check-input" </div>
type="checkbox" <div className="d-flex flex-row align-items-center">
checked={anonymous} {feedbackStatus === "sending" && <div className="mr-3">
onChange={(e) => setAnonymous(e.target.checked)} <samp>sending...</samp>
id="anonymounCheck" </div>}
/> <div>
<label className="form-check-label" htmlFor="anonymousCheck"> <button className="btn btn-sm btn-primary" onClick={handleSendFeedback}>Send</button>
stay anonymouns </div>
</label> </div>
</div> </div>
)} {user && <div className="form-check small">
</div> <input
)} className="form-check-input"
</div> type="checkbox"
<hr /> checked={anonymous}
</div> onChange={e => setAnonymous(e.target.checked)}
); id="anonymounCheck"
/>
<label className="form-check-label" htmlFor="anonymousCheck">
stay anonymouns
</label>
</div>}
</div>}
</div>
<hr />
</div>;
} }
export default ChapterFeedback;
export default ChapterFeedback;