hiuphub-gamified
Version:
app of gamified
270 lines (240 loc) • 8.25 kB
JavaScript
import PropTypes from "prop-types";
import React, { useState, useRef, useEffect } from "react";
import api from "../../api";
import * as constants from "../../common/constants";
import TipBox from "../../components/Common/TipBox";
export default function AddReputation(props) {
const { activities } = props;
const [state, setState] = useState({
reputations: [{ title: "", subscore: 0 }],
loader: "",
message: "",
tipBoxStatus: false,
tipBoxType: "success",
});
const timer = useRef();
useEffect(() => {
return () => {
clearTimeout(timer.current);
};
}, []);
const vanisTipBox = () => {
timer.current = setTimeout(() => {
setState(state => ({ ...state, tipBoxStatus: false, message: "" }));
}, 7000);
};
const closeTipBox = () => {
setState(state => ({ ...state, tipBoxStatus: false, message: "" }));
};
const saveReputations = async () => {
let url = "/reputationpoints/v1";
const data = {
reputationPoints: state.reputations.filter(
reputation => reputation.title
),
};
if (!data.reputationPoints.length || state.loader === constants.SAVING) {
return;
}
setState(state => ({ ...state, loader: constants.SAVING }));
try {
const result = await api.post(url, data);
console.log({ result });
setState(state => ({
...state,
loader: "",
tipBoxStatus: true,
tipBoxType: "success",
message: "Sucessfully saved Reputation Point.",
}));
props.onResponse(result.data);
vanisTipBox();
timer.current = setTimeout(() => {
props.closeModal();
}, 2000);
} catch (err) {
const error = err.message || err;
console.log({ error });
setState(state => ({
...state,
loader: "",
tipBoxStatus: true,
message: error,
tipBoxType: "error",
title: "",
subscore: 0,
}));
vanisTipBox();
}
};
const addPoint = (e, title) => {
e.persist();
let value = e.target.value;
let reputations = [];
if (e.target.name === "title") {
let changeValue = false;
reputations = state.reputations.map(reputation => {
if (reputation.title === value) {
changeValue = true;
return reputation;
} else if (reputation.title && reputation.title === title) {
const isAlreadyExists = state.reputations.find(
reputation => reputation.title === value
);
if (!isAlreadyExists) {
changeValue = true;
return { title: value, subscore: reputation.subscore };
}
}
return reputation;
});
if (!changeValue)
reputations = [
...reputations.slice(0, -1),
{
title: value,
subscore: reputations[state.reputations.length - 1].subscore || 0,
},
];
} else if (e.target.name === "subscore") {
value = Math.floor(value);
if (e.target.value === "") value = "";
let isAlreadyExists = false;
reputations = state.reputations.map(reputation => {
if (reputation.title === title) {
isAlreadyExists = true;
return { title, subscore: value };
}
return reputation;
});
if (!isAlreadyExists) reputations = [...reputations.slice(0, -1)];
}
setState(state => ({ ...state, reputations }));
};
const removeReputation = title => {
const reputations = state.reputations.filter(
reputation => reputation.title !== title
);
setState(state => ({ ...state, reputations }));
};
const addNextActivity = () => {
const hasEmptyActivity = state.reputations.find(
reputation => !reputation.title
);
if (!hasEmptyActivity) {
setState(state => ({
...state,
reputations: [...state.reputations, { title: "", subscore: 0 }],
}));
}
};
if (!activities.length) return <span>Activities required</span>;
const { tipBoxStatus, message, tipBoxType } = state;
return (
<div className="row h-100">
<div className="col-lg-12 col-md-12 col-sm-12">
<section className="mb-4 d-flex justify-content-between align-items-center">
<span>
Add <span className="fw-bold">Reputation</span>
</span>
</section>
{tipBoxStatus && (
<TipBox
tipBoxType={tipBoxType}
onClose={closeTipBox}
message={message}
status={tipBoxStatus}
/>
)}
<div className="d-flex flex-column h-100">
{state.reputations.map(reputation => (
<div
className="border-0 bg-transparent"
key={reputation.title + reputation.subscore}
>
<div className="p-0">
<div className="g-2 row">
{reputation.title ? (
<div className="d-flex flex-row-reverse">
<span
className="btn btn-sm text-danger p-0 px-1"
onClick={() => removeReputation(reputation.title)}
style={{ cursor: "pointer" }}
>
Remove
</span>
</div>
) : null}
<div className="col-lg-7 col-md-12 col-sm-12">
<div className="mb-3 form-floating">
<select
aria-label="Select Reputation Title"
className="border-radius-lg form-select"
id="floatingSelect"
name="title"
onChange={e => addPoint(e, reputation.title)}
value={reputation.title}
>
<option value="">Select title</option>
{activities.map(activity => (
<option key={activity._id} value={activity.name}>
{activity.name}
</option>
))}
</select>
<label htmlFor="floatingSelect">
Select Reputation Title
</label>
</div>
</div>
<div className="col-lg-5 col-md-12 col-sm-12">
<div className="mb-3 form-floating">
<input
type="number"
placeholder="Enter subscore point"
id="floatingInput"
className="border-radius-lg form-control"
name="subscore"
min="0"
value={reputation.subscore}
onChange={e => addPoint(e, reputation.title)}
/>
<label htmlFor="floatingInput">Reputation Point</label>
</div>
</div>
</div>
</div>
</div>
))}
<div>
<div className="text-start">
<button
type="button"
className="btn btn-dark"
onClick={addNextActivity}
>
Add
</button>
</div>
</div>
<div className="mt-auto">
<div className="text-end">
<button
type="button"
className="btn btn-dark"
onClick={saveReputations}
>
{state.loader === constants.SAVING ? "Saving" : "Save"}
</button>
</div>
</div>
</div>
</div>
</div>
);
}
AddReputation.propTypes = {
activities: PropTypes.array.isRequired,
onCloseModal: PropTypes.func.isRequired,
onResponse: PropTypes.func.isRequired,
};