Skip to content

Commit

Permalink
πŸ€ [Frontend] Manage/Add Testimonial on Admin Panel Added (#1053)
Browse files Browse the repository at this point in the history
* added

* Update

* fix
  • Loading branch information
Hemu21 authored Jun 15, 2024
1 parent 89a7d74 commit ed6ac50
Show file tree
Hide file tree
Showing 13 changed files with 1,017 additions and 1 deletion.
Binary file added frontend/public/images/testimonialImg.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
23 changes: 23 additions & 0 deletions frontend/src/pages/Admin/Admin.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,9 @@ import { useDispatch } from "react-redux";
import { ManageFaq } from "./Components/Faq/ManageFaq";
import { QandA } from "./Components/Faq/Q&A/QandA";
import { Manageqa } from "./Components/Faq/Q&A/ManageQ&A/ManageQ&A";
import { Testimonial } from "./Components/Testimonial";
import { AddTestimonial } from "./Components/Testimonial/AddTestimonial";
import { ManageTestimonial } from "./Components/Testimonial/ManageTestimonial";

export const Admin = (props) => {
const [tab, setTab] = useState(1);
Expand Down Expand Up @@ -177,6 +180,20 @@ export const Admin = (props) => {
<div className={style["span"]}>FAQs and Q&As</div>
</div>
</li>
<li onClick={closeMobileMenu}>
<div
className={
tab === 20 ? style["features-icons"] : style["features-icons1"]
}
onClick={() => setTab(20)}
>
<i
className="fas fa-solid fa-comments fa-fw fa-lg"
aria-hidden="true"
></i>
<div className={style["span"]}>Testimonial</div>
</div>
</li>
<li onClick={closeMobileMenu}>
<div
className={
Expand Down Expand Up @@ -246,6 +263,12 @@ export const Admin = (props) => {
<QandA setQId={setQId} setTab={setTab} tab={tab} />
) : tab === 19 ? (
<Manageqa qId={qId} setTab={setTab} />
) : tab === 20 ? (
<Testimonial setTab={setTab} />
) : tab === 21 ? (
<AddTestimonial setTab={setTab} />
) : tab === 22 ? (
<ManageTestimonial setTab={setTab} />
) : null}
</div>
</div>
Expand Down
6 changes: 6 additions & 0 deletions frontend/src/pages/Admin/Components/Dashboard/Dashboard.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import { useSelector } from "react-redux";
import LiveHelpIcon from "@material-ui/icons/LiveHelp";
import PermContactCalendarIcon from "@material-ui/icons/PermContactCalendar";
import { SimpleToast } from "../../../../components/util/Toast";
import Chat from "@material-ui/icons/Chat"

export const Dashboard = (props) => {
const [openLoginSuccess, setOpenLoginSuccessToast] = React.useState(false);
Expand Down Expand Up @@ -50,6 +51,11 @@ export const Dashboard = (props) => {
icon: <LiveHelpIcon style={{ fontSize: 23 }} />,
tab: 5,
},
{
name: "Testimonial",
icon: <Chat style={{ fontSize: 23 }} />,
tab: 20,
},
];

return (
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,278 @@
import React, { useState } from "react";
import Joi from "joi-browser";
import styles from "./add-testimonial.module.scss";
import { Button2 } from "../../../../../components/util/Button/index";
import { Grid } from "@material-ui/core";
import { SimpleToast } from "./../../../../../components/util/Toast/Toast";
import { addTestimonial } from "../../../../../service/Testimonial";

export function AddTestimonial() {
const [formData, setFormData] = useState({
name: "",
position: "",
company: "",
image: "https://i.pinimg.com/originals/f4/cd/d8/f4cdd85c50e44aa59a303fb163ff90f8.jpg",
text: "",
rating: "",
});
const [toast, setToast] = useState({
toastStatus: false,
toastType: "",
toastMessage: "",
});
const [formErrors, setFormErrors] = useState({});
const [picUrl, setPicUrl] = useState("./images/testimonialImg.png");
const [pic, setPic] = useState();
const schema = {
name: Joi.string().required().label("Name"),
position: Joi.string().required().label("Position"),
company: Joi.string().required().label("Company"),
image: Joi.any().required().label("Image"),
text: Joi.string().required().label("Text"),
rating: Joi.number().required().min(1).max(5).label("Rating"),
};

const validate = () => {
const result = Joi.validate(formData, schema, { abortEarly: false });
if (!result.error) return {};
const errors = {};
for (let item of result.error.details) {
errors[item.path[0]] = item.message;
}
return errors;
};

const validateProperty = (input) => {
const { name, value } = input;
const obj = { [name]: value };
const obj_schema = { [name]: schema[name] };
const result = Joi.validate(obj, obj_schema);
return result.error ? result.error.details[0].message : null;
};
const onPicChange = (event) => {
const { target } = event;
const { files } = target;

if (files && files[0]) {
setPic(files[0]);
let reader = new FileReader();
reader.onload = function (e) {
setPicUrl(e.target.result);
};
reader.readAsDataURL(files[0]);
}
return;
};

const changePic = () => {
return document.getElementById("profile-pic-input")?.click();
};

const handleCloseToast = (event, reason) => {
if (reason === "clickaway") {
return;
}
setToast({ ...toast, toastStatus: false });
};

const handleChange = (e) => {
const { currentTarget: input } = e;
const errors = { ...formErrors };
const errorMessage = validateProperty(input);
if (errorMessage) errors[input.name] = errorMessage;
else delete errors[input.name];

const data = { ...formData };
data[input.name] = input.value;
setFormData(data);
setFormErrors(errors);
};

const onSubmit = async (e) => {
e.preventDefault();
const errors = validate();
setFormErrors(errors);
if (Object.keys(errors).length !== 0) {
console.log(errors);
} else {
// Call the server
await addTestimonial(formData, setToast, toast);

const temp = {
name: "",
position: "",
company: "",
text: "",
rating: "",
};
setFormData(temp);
setPicUrl("./images/testimonialImg.png");
}
return pic;
};

return (
<div className={styles["add-testimonial-section"]}>
<div className={styles["add-testimonial-parent"]}>
<div
className={styles["add-testimonial-child"] + " " + styles["child1"]}
>
<div className={styles["add-testimonial-card"]}>
<h1 className={styles["add-testimonial-header-text"]}>
Add Testimonial
</h1>
<form
className={styles["inside-add-testimonial"]}
onSubmit={onSubmit}
>
<Grid container>
<Grid xs={12} sm={2} md={3} />
<Grid xs={12} sm={8} md={6}>
<div className={styles["upload-section"]} onClick={changePic}>
<img
src={picUrl}
className={styles["img-admin"]}
alt="admin_img"
/>
<h1
className={styles["h1"]}
style={{ color: "white", fontSize: "15px" }}
>
Click to Change
</h1>
<input
id="profile-pic-input"
type="file"
accept="image/*"
capture="camera"
onChange={onPicChange}
style={{ display: "none" }}
/>
</div>
</Grid>
</Grid>
<div className={styles["add-testimonial-input"]}>
<input
id="txt_name"
type="text"
name="name"
placeholder="Name"
value={formData["name"]}
onChange={handleChange}
/>
<i className="fas fa-signature"></i>
<div
className={`${styles["validation"]} validation d-sm-none d-md-block`}
>
{formErrors["name"] ? (
<div>* {formErrors["name"]}</div>
) : (
<div>&nbsp; &nbsp;</div>
)}
</div>
</div>
<div className={styles["add-testimonial-input"]}>
<input
id="txt_position"
type="text"
name="position"
placeholder="Position"
value={formData["position"]}
onChange={handleChange}
/>
<i className="fas fa-briefcase"></i>
<div
className={`${styles["validation"]} validation d-sm-none d-md-block`}
>
{formErrors["position"] ? (
<div>* {formErrors["position"]}</div>
) : (
<div>&nbsp; &nbsp;</div>
)}
</div>
</div>
<div className={styles["add-testimonial-input"]}>
<input
id="txt_company"
type="text"
name="company"
placeholder="Company"
value={formData["company"]}
onChange={handleChange}
/>
<i className="fas fa-building"></i>
<div
className={`${styles["validation"]} validation d-sm-none d-md-block`}
>
{formErrors["company"] ? (
<div>* {formErrors["company"]}</div>
) : (
<div>&nbsp; &nbsp;</div>
)}
</div>
</div>
<div className={styles["add-testimonial-input"]}>
<input
id="txt_text"
type="text"
name="text"
placeholder="Testimonial Text"
value={formData["text"]}
onChange={handleChange}
/>
<i className="fas fa-comment"></i>
<div
className={`${styles["validation"]} validation d-sm-none d-md-block`}
>
{formErrors["text"] ? (
<div>* {formErrors["text"]}</div>
) : (
<div>&nbsp; &nbsp;</div>
)}
</div>
</div>
<div className={styles["add-testimonial-input"]}>
<input
id="txt_rating"
type="number"
name="rating"
placeholder="Rating (1-5)"
value={formData["rating"]}
onChange={handleChange}
/>
<i className="fas fa-star"></i>
<div
className={`${styles["validation"]} validation d-sm-none d-md-block`}
>
{formErrors["rating"] ? (
<div>* {formErrors["rating"]}</div>
) : (
<div>&nbsp; &nbsp;</div>
)}
</div>
</div>
<br />
<br />
<div className={styles["submit-btn"]}>
<Button2
className={styles["submit-btn-text"]}
label="Submit"
type="submit"
/>
</div>
</form>
</div>
</div>
</div>

{toast.toastStatus && (
<SimpleToast
open={toast.toastStatus}
message={toast.toastMessage}
handleCloseToast={handleCloseToast}
severity={toast.toastType}
/>
)}
</div>
);
}
Loading

0 comments on commit ed6ac50

Please sign in to comment.