Skip to content

Commit

Permalink
View New and Edit Problem Tag (#44)
Browse files Browse the repository at this point in the history
  • Loading branch information
nvatuan committed Jun 7, 2023
1 parent a412d4e commit 04fadd2
Show file tree
Hide file tree
Showing 4 changed files with 223 additions and 6 deletions.
19 changes: 19 additions & 0 deletions src/api/problem-tag/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,28 @@ const deleteProblemTag = ({id}) => {
return axiosClient.delete(`/problem-tags/${id}/`);
};

const getProblemTagDetails = ({id}) => {
return axiosClient.get(`/problem-tags/${id}/`);
};

const createProblemTag = ({name, descriptions}) => {
return axiosClient.post(`/problem-tags/`, {
name, descriptions
});
}

const editProblemTag = ({id, name, descriptions}) => {
return axiosClient.put(`/problem-tags/${id}/`, {
name, descriptions
});
}

const problemTagAPI = {
getProblemTags,
deleteProblemTag,
getProblemTagDetails,
createProblemTag,
editProblemTag
};

export default problemTagAPI;
104 changes: 104 additions & 0 deletions src/pages/admin/problem-tag/Edit.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
import {Button, Form, Modal} from "react-bootstrap";
import {ErrorBox, SpinLoader} from "components";
import {toast} from "react-toastify";
import problemTagApi from "api/problem-tag";
import { useEffect, useState } from "react";

const AdminEditProblemTagModal = (props) => {
const {id, show, closeModal, forceRefetch} = props;
const [errors, setErrors] = useState()
const [tagName, setTagName] = useState("")
const [tagDesc, setTagDesc] = useState("")
const [isSubmitting, setSubmitting] = useState(false)

const fetchTag = () => {
if (!id) return;
setSubmitting(true)
setErrors(null)

const resp = problemTagApi.getProblemTagDetails({id})
resp.then(res => {
const data = res.data
setTagName(data.name)
setTagDesc(data.descriptions)
}).catch(err => {
setErrors(err?.response?.data)
toast.error("Could not get Tag")
}).finally(() => {
setSubmitting(false)
})
}
useEffect(() => fetchTag(), [id])
useEffect(() => () => {
setTagName("")
setTagDesc("")
}, [show])

const onSubmit = (e) => {
e.preventDefault();
setErrors(null)
setSubmitting(true)

const resp = problemTagApi.editProblemTag({
id: id,
name: tagName,
descriptions: tagDesc,
})
resp.then(() => {
toast.success("Success")
forceRefetch()
closeModal()
}).catch(err => {
console.log(err.response.data)
setErrors(err?.response?.data)
toast.error("Cannot update Problem Tag")
}).finally(() => {
setSubmitting(false)
})
}

return (
<Modal show={show} onHide={() => closeModal()}>
<Modal.Header>
<Modal.Title>
+ Updating Problem Tag
{ isSubmitting && <SpinLoader /> }
</Modal.Title>
</Modal.Header>
<Modal.Body>
<ErrorBox errors={errors} />
<span>ID: <code>{id}</code></span>
<div>Name</div>
<Form.Control
type="text"
id="problem-tag-name"
placeholder="..."
size="sm"
disabled={isSubmitting}
value={tagName}
onChange={e => setTagName(e.target.value)}
/>
<div className="mt-2"/>
<div>Descriptions</div>
<Form.Control
as="textarea"
id="problem-tag-descriptions"
placeholder="..."
disabled={isSubmitting}
value={tagDesc}
onChange={e => setTagDesc(e.target.value)}
/>
</Modal.Body>
<Modal.Footer>
<Button variant="light" onClick={() => closeModal()}>
Đóng
</Button>
<Button variant="dark" onClick={e => onSubmit(e)} disabled={isSubmitting}>
Lưu
</Button>
</Modal.Footer>
</Modal>
)
}

export default AdminEditProblemTagModal;
28 changes: 22 additions & 6 deletions src/pages/admin/problem-tag/List.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,22 +14,22 @@ import {SpinLoader, ErrorBox} from "components";
import problemTagApi from "api/problem-tag";
import {setTitle} from "helpers/setTitle";
import {qmClarify} from "helpers/components";
import AdminCreateProblemTagModal from "./New"
import AdminEditProblemTagModal from "./Edit"

import "./List.scss";
import "styles/ClassicPagination.scss";

const ProblemTagListItem = (props) => {
const {id, name} = props;
const {selectedIds, setSelectedIds} = props;
const {setEditingTagId, selectedIds, setSelectedIds} = props;

return (
<tr>
<td className="text-truncate" style={{maxWidth: "40px"}}>{id}</td>
<td className="text-truncate" style={{maxWidth: "100px"}}>{name}</td>
<td>
<Link to="#" onClick={e => alert(e)}>
edit
</Link>
<Link to="#" onClick={() => setEditingTagId(id)}>edit</Link>
</td>
<td>
<input
Expand All @@ -48,6 +48,8 @@ const ProblemTagListItem = (props) => {
const AdminProblemTagList = (props) => {
const [isLoading, setIsLoading] = useState(true)
const [errors, setErrors] = useState()
const [showModal, setShowModal] = useState(false)
const [isEditingTagId, setEditingTagId] = useState(null)
const [tags, setTags] = useState([])

const [selectedIds, setSelectedIds] = useState([])
Expand Down Expand Up @@ -103,7 +105,7 @@ const AdminProblemTagList = (props) => {
variant="dark"
className="btn-svg"
disabled={isLoading}
onClick={() => this.setState({redirectUrl: "new"})}
onClick={() => setShowModal(true)}
>
<AiOutlinePlusCircle />
<span className="d-none d-md-inline-flex">Add (Form)</span>
Expand Down Expand Up @@ -163,7 +165,9 @@ const AdminProblemTagList = (props) => {
)}
{!isLoading && tags.length > 0 && (
tags.map((tag, idx) => <ProblemTagListItem
key={`problem-tag-${idx}`} {...tag} selectedIds={selectedIds} setSelectedIds={setSelectedIds}
key={`problem-tag-${idx}`} {...tag}
selectedIds={selectedIds} setSelectedIds={setSelectedIds}
setEditingTagId={(v) => setEditingTagId(v)}
/>)
)}
{!isLoading && tags.length === 0 && (
Expand All @@ -176,6 +180,18 @@ const AdminProblemTagList = (props) => {
</tbody>
</Table>
</div>

<AdminCreateProblemTagModal
show={showModal}
closeModal={() => setShowModal(false)}
forceRefetch={() => fetch()}
/>
<AdminEditProblemTagModal
show={!!isEditingTagId}
closeModal={() => setEditingTagId(null)}
forceRefetch={() => fetch()}
id={isEditingTagId}
/>
</div>
)
}
Expand Down
78 changes: 78 additions & 0 deletions src/pages/admin/problem-tag/New.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
import {Button, Form, Modal} from "react-bootstrap";
import {ErrorBox, SpinLoader} from "components";
import {toast} from "react-toastify";
import problemTagApi from "api/problem-tag";
import { useState } from "react";

const AdminCreateProblemTagModal = (props) => {
const {show, closeModal, forceRefetch} = props;
const [errors, setErrors] = useState()
const [tagName, setTagName] = useState("")
const [tagDesc, setTagDesc] = useState("")
const [isSubmitting, setSubmitting] = useState(false)

const onSubmit = (e) => {
e.preventDefault();
setErrors(null)
setSubmitting(true)

const resp = problemTagApi.createProblemTag({
name: tagName, descriptions: tagDesc,
})
resp.then(() => {
toast.success("Success")
forceRefetch()
closeModal()
}).catch(err => {
console.log(err.response.data)
setErrors(err?.response?.data)
toast.error("Cannot create Problem Tag")
}).finally(() => {
setSubmitting(false)
})
}

return (
<Modal show={show} onHide={() => closeModal()}>
<Modal.Header>
<Modal.Title>
+ Create Problem Tag
{ isSubmitting && <SpinLoader /> }
</Modal.Title>
</Modal.Header>
<Modal.Body>
<ErrorBox errors={errors} />
<div>Name</div>
<Form.Control
type="text"
id="problem-tag-name"
placeholder="tag-name"
size="sm"
disabled={isSubmitting}
value={tagName}
onChange={e => setTagName(e.target.value)}
/>
<div className="mt-2"/>
<div>Descriptions</div>
<Form.Control
as="textarea"
id="problem-tag-descriptions"
placeholder="Tag descriptions here"
disabled={isSubmitting}
value={tagDesc}
onChange={e => setTagDesc(e.target.value)}
/>
</Modal.Body>
<Modal.Footer>
<Button variant="light" onClick={() => closeModal()}>
Đóng
</Button>
<Button variant="dark" onClick={e => onSubmit(e)} disabled={isSubmitting}>
Tạo
</Button>
</Modal.Footer>
</Modal>
)
}

export default AdminCreateProblemTagModal;

0 comments on commit 04fadd2

Please sign in to comment.