Skip to content

Commit

Permalink
refactor: use zustand
Browse files Browse the repository at this point in the history
* refactor: use zustand

* chore: use zustand

* fix: login fixed

* chore: migrate useNotify to zustand

* refactor: uptomize create form rendering

* refactor: optimisize question rendering

* refactor:run prettier

* refactor: remove unecessary wrapper

* fix: send token when signup
  • Loading branch information
RickaPrincy authored Feb 11, 2024
1 parent 537ce25 commit b76215d
Show file tree
Hide file tree
Showing 31 changed files with 409 additions and 384 deletions.
38 changes: 37 additions & 1 deletion package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 2 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,8 @@
"react-dom": "^18.2.0",
"react-hook-form": "^7.50.0",
"react-router-dom": "^6.22.0",
"uuid": "^9.0.1"
"uuid": "^9.0.1",
"zustand": "^4.5.0"
},
"devDependencies": {
"@types/react": "^18.2.43",
Expand Down
32 changes: 27 additions & 5 deletions src/App.jsx
Original file line number Diff line number Diff line change
@@ -1,11 +1,32 @@
import { useEffect, useState } from "react";
import { BrowserRouter, Route, Routes } from "react-router-dom";
import { Login, Profile, NotFoundPage, CreateForm } from "./pages";
import { AuthProvider } from "./context";
import { Login, Profile, NotFoundPage, CreateForm, LoadingPage } from "./pages";
import { Authentificate } from "./security/componens";
import { Alert } from "./components";

import { getWhoAmi } from "./security/authProvider";
import { authFirebase } from "./security/authFirebase";
import { useAuthStore } from "./security/stores";

function App() {
return (
<AuthProvider>
const setUser = useAuthStore((state) => state.setUser);
const [isTestingWhoAmi, setIsTestingWhoAmi] = useState(true);

useEffect(() => {
const makeWhoAmiCall = async () => {
getWhoAmi()
.then((userConnected) => setUser(userConnected))
.catch(() => authFirebase.signOut())
.finally(() => setIsTestingWhoAmi(false));
};

makeWhoAmiCall();
}, [setUser]);

return isTestingWhoAmi ? (
<LoadingPage />
) : (
<div className="w-full">
<BrowserRouter>
<Routes>
<Route path="/" element={<Login />} />
Expand All @@ -21,7 +42,8 @@ function App() {
<Route path="/forms/create" element={<CreateForm />} />
</Routes>
</BrowserRouter>
</AuthProvider>
<Alert />
</div>
);
}

Expand Down
18 changes: 7 additions & 11 deletions src/components/Alert.jsx
Original file line number Diff line number Diff line change
@@ -1,25 +1,21 @@
import PropTypes from "prop-types";
import { Alert as _Alert } from "@material-tailwind/react";
import { useNotifyStore } from "../stores";

import { DEFAULT_CONFIG } from "../hooks";
export function Alert() {
const { message, config } = useNotifyStore();

export function Alert({ notifyConfig = DEFAULT_CONFIG }) {
return (
<_Alert
open={notifyConfig.message !== ""}
open={message !== ""}
animate={{
mount: { y: 0 },
unmount: { y: -100 },
}}
variant={notifyConfig.config.variant}
color={notifyConfig.config.color}
variant={config.variant}
color={config.color}
className="fixed top-5 right-10 min-w-[350px] w-fit"
>
{notifyConfig.message}
{message}
</_Alert>
);
}

Alert.propTypes = {
notifyConfig: PropTypes.object,
};
33 changes: 24 additions & 9 deletions src/components/forms/CreateFormBody.jsx
Original file line number Diff line number Diff line change
@@ -1,15 +1,32 @@
import { Button } from "@material-tailwind/react";
import { v4 as uuid } from "uuid";
import { useCreateForm } from "../../hooks/useCreateForm";
import { Question } from "./Question";
import { useCreateFormStore } from "../../stores";

export function CreateFormBody() {
const { questions, addQuestion, createValue } = useCreateForm();
// to avoid multiple rendering
function SaveButton() {
const formToCreate = useCreateFormStore((state) => ({
config: state.config,
questions: state.questions,
}));

const saveForm = () => {
console.log(createValue);
console.log(formToCreate);
};

return (
<Button onClick={saveForm} variant="filled" color="blue">
Save
</Button>
);
}

export function CreateFormBody() {
const { numberOfQuestion, addQuestion } = useCreateFormStore((state) => ({
numberOfQuestion: state.questions.length,
addQuestion: state.addQuestion,
}));

const createNewQuestion = () => {
addQuestion({
id: uuid(),
Expand All @@ -22,8 +39,8 @@ export function CreateFormBody() {

return (
<>
{questions.map((question) => (
<Question key={question.id} question={question} />
{Array.from({ length: numberOfQuestion }, (_, index) => (
<Question key={uuid()} questionIndex={index} />
))}
<div className="flex w-full justify-end gap-5 items-center">
<Button
Expand All @@ -33,9 +50,7 @@ export function CreateFormBody() {
>
Add question
</Button>
<Button onClick={saveForm} variant="filled" color="blue">
Save
</Button>
<SaveButton />
</div>
</>
);
Expand Down
24 changes: 18 additions & 6 deletions src/components/forms/CreateFormHeader.jsx
Original file line number Diff line number Diff line change
@@ -1,9 +1,23 @@
import { Input, Textarea, Switch } from "@material-tailwind/react";
import { useCreateForm } from "../../hooks/useCreateForm";
import { CollapseConfig } from "./CollapseConfig";
import { useCreateFormStore } from "../../stores";

function NumberOfQuestion() {
const numberOfQuestion = useCreateFormStore(
(state) => state.questions.length
);
return (
<p className="text-gray-800 mt-5">
Number of questions: {numberOfQuestion}
</p>
);
}

export function CreateFormHeader() {
const { config, questions, updateConfig } = useCreateForm();
const { config, updateConfig } = useCreateFormStore((state) => ({
config: state.config,
updateConfig: state.updateConfig,
}));

const updateConfigByName = ({ target }) => {
const { name, value } = target;
Expand Down Expand Up @@ -33,14 +47,12 @@ export function CreateFormHeader() {
value={config.description}
onChange={updateConfigByName}
/>
<p className="text-gray-800 mt-5">
Number of questions: {questions.length}
</p>
<NumberOfQuestion />
<CollapseConfig title="More configuration">
<Switch
label="Private"
value={config.isPrivate}
onChange={({ target }) => updateConfig("isPrivate", target.value)}
onChange={({ target }) => updateConfig("isPrivate", target.checked)}
/>
<Input
type="color"
Expand Down
9 changes: 7 additions & 2 deletions src/components/forms/QOption.jsx
Original file line number Diff line number Diff line change
@@ -1,10 +1,15 @@
import { Input, IconButton } from "@material-tailwind/react";
import { Delete as DeleteIcon } from "@mui/icons-material";
import { useCreateForm } from "../../hooks/useCreateForm";
import { useCreateFormStore } from "../../stores";

/*eslint-disable*/
export function QOption({ questionId, option }) {
const { updateQuestionOption, deleteQuestionOption } = useCreateForm();
const { updateQuestionOption, deleteQuestionOption } = useCreateFormStore(
(state) => ({
updateQuestionOption: state.updateQuestionOption,
deleteQuestionOption: state.deleteQuestionOption,
})
);

return (
<div className="flex items-center gap-5">
Expand Down
22 changes: 16 additions & 6 deletions src/components/forms/Question.jsx
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import React from "react";
import {
IconButton,
Button,
Expand All @@ -13,17 +14,24 @@ import {
import { v4 as uuid } from "uuid";
import PropTypes from "prop-types";

import { useCreateForm } from "../../hooks/useCreateForm";
import { QUESTION_TYPES } from "./utils";
import { QOption } from "./QOption";
import { useCreateFormStore } from "../../stores";

export function Question({ question = {} }) {
export const Question = React.memo(({ questionIndex }) => {
const {
question,
deleteQuestion,
updateQuestion,
duplicateQuestion,
addQuestionOption,
} = useCreateForm();
} = useCreateFormStore((state) => ({
question: state.questions.at(questionIndex),
deleteQuestion: state.deleteQuestion,
updateQuestion: state.updateQuestion,
duplicateQuestion: state.duplicateQuestion,
addQuestionOption: state.addQuestionOption,
}));

const updateQuestionByName = ({ target }) => {
updateQuestion(question.id, target.name, target.value);
Expand Down Expand Up @@ -83,7 +91,7 @@ export function Question({ question = {} }) {
<Switch
value={question.isRequired}
onChange={({ target }) =>
updateQuestion(question.id, "isRequired", target.value)
updateQuestion(question.id, "isRequired", target.checked)
}
label="Required"
/>
Expand All @@ -108,8 +116,10 @@ export function Question({ question = {} }) {
</div>
</div>
);
}
});

Question.displayName = "Question";

Question.propTypes = {
question: PropTypes.object,
questionIndex: PropTypes.number,
};
31 changes: 0 additions & 31 deletions src/context/AuthContext.jsx

This file was deleted.

Loading

0 comments on commit b76215d

Please sign in to comment.