Skip to content

Commit

Permalink
feat: reply form
Browse files Browse the repository at this point in the history
* chore: restyle reply

* feat: can reply a form

---------

Co-authored-by: sanda03 <[email protected]>
  • Loading branch information
RickaPrincy and sanda03 authored Feb 18, 2024
1 parent 94cbcfd commit 052966b
Show file tree
Hide file tree
Showing 18 changed files with 876 additions and 183 deletions.
Binary file added src/assets/images/error_multiple.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added src/assets/images/private.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added src/assets/images/success.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
482 changes: 482 additions & 0 deletions src/gen/client/api.ts

Large diffs are not rendered by default.

19 changes: 19 additions & 0 deletions src/operations/error/AlreadyRespond.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import { Button, Typography } from "@material-tailwind/react";
import { useNavigate } from "react-router-dom";

import errorImage from "../../assets/images/private.png";

export function AlreadyRespond() {
const navigate = useNavigate();

return (
<div className="w-[800px] mx-auto flex-col min-h-[500px] gap-5 flex items-center justify-center">
<img src={errorImage} className="w-[350px]" />
<Typography className="text-bgray text-[30px] text-center">
Form not found or Multiple responses are not allowed for the form, so
you no longer have access to respond.
</Typography>
<Button onClick={() => navigate("/dashboard")}>Go to Dashboard</Button>
</div>
);
}
18 changes: 18 additions & 0 deletions src/operations/error/PrivateForm.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
import { Button, Typography } from "@material-tailwind/react";
import { useNavigate } from "react-router-dom";

import errorImage from "../../assets/images/error_multiple.png";

export function PrivateForm() {
const navigate = useNavigate();

return (
<div className="w-[500px] mx-auto flex-col min-h-[500px] gap-5 flex items-center justify-center">
<img src={errorImage} className="w-[350px]" />
<Typography className="text-bgray text-[30px] text-center">
Only the form owner can view the results as the form is set to private
</Typography>
<Button onClick={() => navigate("/dashboard")}>Go to Dashboard</Button>
</div>
);
}
2 changes: 2 additions & 0 deletions src/operations/error/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
export * from "./AlreadyRespond";
export * from "./PrivateForm";
5 changes: 1 addition & 4 deletions src/operations/forms/create/FormEdit.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -28,10 +28,7 @@ export function FormEdit() {
setAll(newStore);
})
.catch(() => {
notify("Oops, form not found or something went wrong", {
color: "red",
});
navigate("/dashboard");
navigate("/dashboard/error/multiple");
})
.finally(() => dumbLoading(() => setIsLoading(false)));
};
Expand Down
25 changes: 18 additions & 7 deletions src/operations/forms/create/components/CreateFormHeader.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -49,13 +49,24 @@ export function CreateFormHeader() {
/>
<NumberOfQuestion />
<CollapseConfig title="More configuration">
<Switch
label="Private"
name="isPrivate"
className="text-bgray text-[14px]"
checked={config.isPrivate}
onChange={({ target }) => updateConfig("isPrivate", target.checked)}
/>
<div className="flex items-center gap-5">
<Switch
label="Multiple response"
name="allowMultipleChoice"
className="text-bgray text-[14px]"
checked={config.allowMultipleChoice}
onChange={({ target }) =>
updateConfig("allowMultipleChoice", target.checked)
}
/>
<Switch
label="Private"
name="isPrivate"
className="text-bgray text-[14px]"
checked={config.isPrivate}
onChange={({ target }) => updateConfig("isPrivate", target.checked)}
/>
</div>
<Input
type="color"
name="color"
Expand Down
2 changes: 1 addition & 1 deletion src/operations/forms/create/components/Question.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -92,7 +92,7 @@ export const Question = React.memo(({ questionIndex }) => {
)}
<div className="flex gap-10 items-start w-full">
<Switch
value={question.isRequired}
checked={question.isRequired}
onChange={({ target }) =>
updateQuestion(question.id, "isRequired", target.checked)
}
Expand Down
14 changes: 14 additions & 0 deletions src/operations/forms/list/components/Actions.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,12 @@ export function Actions({ formId }) {
const { setIsLoading, fetchForms } = useContext(LIST_CONTEXT);
const notify = useNotify();

const copyLink = () => {
const url = `${window.location.origin}/dashboard/forms/${formId}/reply`;
navigator.clipboard.writeText(url);
notify("Link copied", { color: "green" });
};

const doDelete = async () => {
setIsLoading(true);
formsProvider
Expand All @@ -47,6 +53,14 @@ export function Actions({ formId }) {
</IconButton>
</PopoverHandler>
<PopoverContent className="p-0 w-[150px]">
<Button
size="sm"
variant="text"
className="py-2 w-full block"
onClick={copyLink}
>
CopyLink
</Button>
<Button
size="sm"
variant="text"
Expand Down
57 changes: 55 additions & 2 deletions src/operations/forms/reply/FormReply.jsx
Original file line number Diff line number Diff line change
@@ -1,10 +1,63 @@
import { useNavigate, useParams } from "react-router-dom";
import { useEffect, useState } from "react";
import { ReplyFormHeader, ReplyFormBody } from "./components";
import { useNotify } from "../../../hooks";
import { useDashboardState } from "../../../stores";
import { formsProvider } from "../../../providers";
import { dumbLoading } from "../../utils";

/*eslint-disable*/
export function FormReply() {
const [form, setForms] = useState(null);
const { formId } = useParams();
const notify = useNotify((state) => state.setNotify);
const navigate = useNavigate();
const { isLoading, setIsLoading } = useDashboardState();

useEffect(() => {
setIsLoading(true);

const getFormById = async () => {
formsProvider
.getFormById(formId)
.then((formResponse) => {
setForms(formResponse);
})
.catch(() => {
notify("Oops, form not found or something went wrong", {
color: "red",
});
navigate("/dashboard");
})
.finally(() => dumbLoading(() => setIsLoading(false)));
};

const testIfCanReply = async () => {
formsProvider
.canIReply(formId)
.then((data) => {
if (!data) {
navigate("/dashboard/error/multiple");
dumbLoading(() => setIsLoading(false));
} else {
getFormById();
}
})
.catch(async () => {
navigate("/dashboard/error/multiple");
dumbLoading(() => setIsLoading(false));
});
};

testIfCanReply();
}, [formId]);

if (isLoading || form === null) return null;

return (
<div className="w-full mx-auto max-w-[900px]">
<ReplyFormHeader />
<ReplyFormBody />
<ReplyFormHeader form={form} />
<ReplyFormBody questions={form.questions || []} formId={form.id} />
</div>
);
}
Loading

0 comments on commit 052966b

Please sign in to comment.