Styles of Group Profile
Styles of Group Profile
Styles of Group Profile
import {
CModal,
CModalHeader,
CModalTitle,
CModalBody,
CModalFooter,
CButton,
} from "@coreui/react-pro";
import { useFormik } from "formik";
import * as Yup from "yup";
const GroupProfileForm = ({
modalVisible,
setModalVisible,
newActivity,
handleFormSubmit,
}) => {
const validationSchema = Yup.object({
activityDate: Yup.date().required("Activity Date is required"),
maleBeneficiaryCount: Yup.number()
.min(0, "Must be greater than or equal to 0")
.required("Male Beneficiary Count is required"),
femaleBeneficiaryCount: Yup.number()
.min(0, "Must be greater than or equal to 0")
.required("Female Beneficiary Count is required"),
othersBeneficiaryCount: Yup.number()
.min(0, "Must be greater than or equal to 0")
.required("Others Beneficiary Count is required"),
});
return (
<CModal
alignment="center"
visible={modalVisible}
onClose={() => setModalVisible(false)}
>
<CModalHeader>
<CModalTitle>Add New Activity</CModalTitle>
</CModalHeader>
<CModalBody>
<form onSubmit={formik.handleSubmit}>
<div className="mb-3">
<label htmlFor="activityDate" className="form-label">
Activity Date
</label>
<input
type="date"
className="form-control"
id="activityDate"
name="activityDate"
value={formik.values.activityDate}
onChange={formik.handleChange}
onBlur={formik.handleBlur}
/>
{formik.touched.activityDate && formik.errors.activityDate ? (
<div className="text-danger">{formik.errors.activityDate}</div>
) : null}
</div>
<div className="mb-3">
<label htmlFor="maleBeneficiaryCount" className="form-label">
Male Beneficiary Count
</label>
<input
type="number"
className="form-control"
id="maleBeneficiaryCount"
name="maleBeneficiaryCount"
value={formik.values.maleBeneficiaryCount}
onChange={formik.handleChange}
onBlur={formik.handleBlur}
/>
{formik.touched.maleBeneficiaryCount &&
formik.errors.maleBeneficiaryCount ? (
<div className="text-danger">
{formik.errors.maleBeneficiaryCount}
</div>
) : null}
</div>
<div className="mb-3">
<label htmlFor="femaleBeneficiaryCount" className="form-label">
Female Beneficiary Count
</label>
<input
type="number"
className="form-control"
id="femaleBeneficiaryCount"
name="femaleBeneficiaryCount"
value={formik.values.femaleBeneficiaryCount}
onChange={formik.handleChange}
onBlur={formik.handleBlur}
/>
{formik.touched.femaleBeneficiaryCount &&
formik.errors.femaleBeneficiaryCount ? (
<div className="text-danger">
{formik.errors.femaleBeneficiaryCount}
</div>
) : null}
</div>
<div className="mb-3">
<label htmlFor="othersBeneficiaryCount" className="form-label">
Others Beneficiary Count
</label>
<input
type="number"
className="form-control"
id="othersBeneficiaryCount"
name="othersBeneficiaryCount"
value={formik.values.othersBeneficiaryCount}
onChange={formik.handleChange}
onBlur={formik.handleBlur}
/>
{formik.touched.othersBeneficiaryCount &&
formik.errors.othersBeneficiaryCount ? (
<div className="text-danger">
{formik.errors.othersBeneficiaryCount}
</div>
) : null}
</div>
<CModalFooter>
<CButton color="success text-white" type="submit">
Save
</CButton>
<CButton color="secondary" onClick={() => setModalVisible(false)}>
Cancel
</CButton>
</CModalFooter>
</form>
</CModalBody>
</CModal>
);
};
if (!fiscalYearId) {
setActivities([]);
setSelectedDates({});
setCheckedActivities({});
return;
}
try {
const response = await getData(
`groupFYActivities/${groupId}/${fiscalYearId}`,
);
if (Array.isArray(response?.data)) {
setActivities(response.data);
const newSelectedDates = {};
const newCheckedActivities = {};
response.data.forEach(
({ activityId, activityDate, groupFYActivityId }) => {
newSelectedDates[activityId] = activityDate;
newCheckedActivities[activityId] = {
checked: true,
groupFYActivityId,
};
},
);
setSelectedDates(newSelectedDates);
setCheckedActivities(newCheckedActivities);
} else {
throw new Error("Invalid activity data");
}
} catch {
setError("Error fetching activities");
}
};
postData("groupFYActivities", {
fiscalYearId: selectedFiscalYear,
activityId,
groupId,
activityDate: date,
}).catch(() => setError("Error saving activity data"));
};
if (
isChecked &&
groupFYActivityId &&
window.confirm("Are you sure you want to delete this activity?")
) {
try {
await deleteData(`groupFYActivity/${groupFYActivityId}`);
setCheckedActivities((prev) => ({
...prev,
[activityId]: { checked: false },
}));
setSelectedDates((prev) => ({ ...prev, [activityId]: undefined }));
setActivities((prev) =>
prev.filter((a) => a.activityId !== activityId),
);
} catch {
setError("Error deleting activity");
}
}
};
if (!acc[phaseName]) {
acc[phaseName] = {};
}
if (!acc[phaseName][sectorName]) {
acc[phaseName][sectorName] = [];
}
acc[phaseName][sectorName].push(activity);
return acc;
}, {});
return (
<div>
{loading ? (
<CSpinner color="primary" className="d-flex justify-content-center" />
) : error ? (
<CAlert color="danger">{error}</CAlert>
) : (
<>
<CRow>
<CCol xl={12}>
<GroupDetails
groupName={groupName}
groupType={groupType}
address={address}
/>
</CCol>
</CRow>
<CRow className="mt-3 justify-content-end">
<CCol md="3">
<CFormSelect
size="md"
aria-label="Select fiscal year"
options={[
{ label: "Select Fiscal Year", value: "" },
...fiscalYears.map(({ fiscalYearName, fiscalYearId }) => ({
label: fiscalYearName,
value: fiscalYearId,
})),
]}
onChange={handleFiscalYearChange}
value={selectedFiscalYear}
/>
</CCol>
<CCol md="3">
<CFormSelect
size="md"
aria-label="Select phase"
options={[
{ label: "Select Phase", value: "" },
...Object.keys(groupedActivities).map((phaseName) => ({
label: phaseName,
value: phaseName,
})),
]}
onChange={handlePhaseChange}
value={selectedPhase}
/>
</CCol>
</CRow>
<CCol xl={12}>
<CCard className="mt-3">
<CCardHeader>
<h2>Activities</h2>
</CCardHeader>
<CCardBody>
{!selectedFiscalYear ? (
<CAlert color="warning">Please select a fiscal year</CAlert>
) : !selectedPhase ? (
<CAlert color="warning">Please select a phase</CAlert>
) : (
<CAccordion activeItemKey={1}>
{Object.entries(groupedActivities[selectedPhase]).map(
([sectorName, activities], index) => (
<CAccordionItem itemKey={index + 1} key={sectorName}>
<CAccordionHeader>
Sector: {sectorName}
</CAccordionHeader>
<CAccordionBody>
<CRow>
{activities.map((activity) => (
<GroupCheckBox
key={activity.activityId}
activity={activity}
isChecked={
checkedActivities[activity.activityId]
?.checked || false
}
onChange={() =>
handleCheckboxChange(activity.activityId)
}
selectedDate={
selectedDates[activity.activityId]
}
showDetails={true}
setModalVisible={setModalVisible}
setCurrentActivity={setCurrentActivity}
formatDate={formatDate} // Pass the formatDate
function
/>
))}
</CRow>
</CAccordionBody>
</CAccordionItem>
),
)}
</CAccordion>
)}
</CCardBody>
</CCard>
</CCol>
<GroupProfileForm
modalVisible={modalVisible}
setModalVisible={setModalVisible}
newActivity={newActivity}
handleInputChange={handleInputChange}
handleFormSubmit={handleFormSubmit}
/>
</>
)}
</div>
);
};
const GroupCheckBox = ({
activity,
isChecked,
onChange,
selectedDate,
showDetails,
setModalVisible,
setCurrentActivity,
formatDate,
}) => (
<CCol xs="12" md="4">
<CCard className="mb-3">
<CCardHeader className="d-flex justify-content-between align-items-center">
<CFormCheck
id={`activity-${activity.activityId}`}
checked={isChecked}
onChange={onChange}
label={activity.activityName}
/>
{!isChecked && (
<CButton
color="primary"
// color="success text-white"
size="sm"
className="d-flex align-items-center text-white"
onClick={() => {
setCurrentActivity(activity);
setModalVisible(true);
}}
>
<CIcon icon={cilPlus} className="me-2" />
Add
</CButton>
)}
</CCardHeader>
{isChecked && (
<CCardBody>
{showDetails && (
<div>
<p>
<strong>Activity Date:</strong> {formatDate(selectedDate)}
</p>
<p>
<strong>Male Beneficiary Count:</strong>{" "}
{activity.maleBeneficiaryCount}
</p>
<p>
<strong>Female Beneficiary Count:</strong>{" "}
{activity.femaleBeneficiaryCount}
</p>
<p>
<strong>Others Beneficiary Count:</strong>{" "}
{activity.othersBeneficiaryCount}
</p>
</div>
)}
</CCardBody>
)}
</CCard>
</CCol>
);