Skip to content

Commit c81fb59

Browse files
authored
Merge pull request #157 from amaydixit11/main
Refactored Common cards and POR Section
2 parents 9b84736 + 52435b7 commit c81fb59

13 files changed

Lines changed: 380 additions & 177 deletions

frontend/src/Components/ManagePosition.jsx

Lines changed: 6 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ import {
1111
import api from "../utils/api";
1212
import { AdminContext } from "../context/AdminContext";
1313
import AddPositionHolder from "./AddPositionHolder";
14+
import ViewPositionHolder from "./Positions/ViewPositionHolder";
1415

1516
const ManagePositions = () => {
1617
const { isUserLoggedIn } = React.useContext(AdminContext);
@@ -128,17 +129,10 @@ const ManagePositions = () => {
128129
</div>
129130
</div>
130131
</div>
131-
{/* Gray horizontal line separator */}
132-
{/* <button
133-
onClick={() => setShowAddModal(true)}
134-
className="flex items-center gap-2 bg-black text-white text-sm px-4 py-2 rounded-lg hover:bg-[#856A5D] transition-colors"
135-
>
136-
<Plus className="w-4 h-4" /> Add Position
137-
</button> */}
138132
<div className="w-full h-[2px] bg-gray-300"></div>
139133
</div>
140-
141-
{/* Filters */}
134+
<ViewPositionHolder />
135+
{/*
142136
<div className="">
143137
<div className="flex flex lg:flex-row gap-4 pb-2">
144138
<div className="flex-1 relative round-xl">
@@ -183,7 +177,6 @@ const ManagePositions = () => {
183177
</div>
184178
</div>
185179
186-
{/* Positions Grid */}
187180
{filteredPositions.length === 0 ? (
188181
<div className="bg-white rounded-lg p-12 text-center">
189182
<UserCheck className="w-12 h-12 text-black mx-auto mb-4" />
@@ -245,24 +238,6 @@ const ManagePositions = () => {
245238
</div>
246239
</div>
247240
248-
{/* <div className="p-4 bg-[#F5F1EC] flex justify-around text-center">
249-
<div>
250-
<span className="text-xs text-black">Events</span>
251-
<p className="text-lg font-bold text-black">
252-
{position.performance_metrics?.events_organized || 0}
253-
</p>
254-
</div>
255-
<div className="border-l border-black h-8"></div>
256-
<div>
257-
<span className="text-xs text-black">Budget</span>
258-
<p className="text-sm font-bold text-black">
259-
{formatCurrency(
260-
position.performance_metrics?.budget_utilized
261-
)}
262-
</p>
263-
</div>
264-
</div> */}
265-
266241
<div className="px-4 py-2 border-t border-black text-xs text-black flex justify-between">
267242
<span>Created: {formatDate(position.created_at)}</span>
268243
{position.updated_at !== position.created_at && (
@@ -272,10 +247,10 @@ const ManagePositions = () => {
272247
</div>
273248
))}
274249
</div>
275-
)}
250+
)} */}
276251
</div>
277252

278-
{showAddModal && (
253+
{/* {showAddModal && (
279254
<div className="fixed inset-0 bg-black bg-opacity-50 flex items-center justify-center z-50 p-4">
280255
<div className="relative w-full max-w-2xl bg-white rounded-xl shadow-lg p-6">
281256
<button
@@ -287,7 +262,7 @@ const ManagePositions = () => {
287262
<AddPositionHolder onClose={() => setShowAddModal(false)} />
288263
</div>
289264
</div>
290-
)}
265+
)} */}
291266
</div>
292267
);
293268
};

frontend/src/Components/Positions/AddPositionForm.jsx

Lines changed: 131 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,13 @@ const AddPositionForm = () => {
1818
setFormData((prev) => ({ ...prev, [field]: value }));
1919
};
2020

21+
const handleRequirementChange = (field, value) => {
22+
setFormData((prev) => ({
23+
...prev,
24+
requirements: { ...prev.requirements, [field]: value },
25+
}));
26+
};
27+
2128
const handleArrayChange = (arrayName, index, value) => {
2229
setFormData((prev) => {
2330
const updatedArray = [...prev[arrayName]];
@@ -26,26 +33,59 @@ const AddPositionForm = () => {
2633
});
2734
};
2835

36+
const handleRequirementArrayChange = (arrayName, index, value) => {
37+
setFormData((prev) => ({
38+
...prev,
39+
requirements: {
40+
...prev.requirements,
41+
[arrayName]: prev.requirements[arrayName].map((item, i) =>
42+
i === index ? value : item
43+
),
44+
},
45+
}));
46+
};
47+
2948
const addToArray = (arrayName) => {
3049
setFormData((prev) => ({
3150
...prev,
3251
[arrayName]: [...prev[arrayName], ""],
3352
}));
3453
};
3554

55+
const addToRequirementArray = (arrayName) => {
56+
setFormData((prev) => ({
57+
...prev,
58+
requirements: {
59+
...prev.requirements,
60+
[arrayName]: [...prev.requirements[arrayName], ""],
61+
},
62+
}));
63+
};
64+
3665
const removeFromArray = (arrayName, index) => {
3766
setFormData((prev) => ({
3867
...prev,
3968
[arrayName]: prev[arrayName].filter((_, i) => i !== index),
4069
}));
4170
};
4271

72+
const removeFromRequirementArray = (arrayName, index) => {
73+
setFormData((prev) => ({
74+
...prev,
75+
requirements: {
76+
...prev.requirements,
77+
[arrayName]: prev.requirements[arrayName].filter((_, i) => i !== index),
78+
},
79+
}));
80+
};
81+
4382
return (
4483
<div className="w-full bg-white flex items-center justify-center p-4">
4584
<form
4685
onSubmit={handleSubmit}
4786
className="w-full px-8 bg-white/80 backdrop-blur-sm rounded-2xl"
4887
>
88+
{/* Basic Information */}
4989
<div className="grid grid-cols-1 md:grid-cols-2 gap-4">
5090
<FormInput
5191
label="Position Title"
@@ -57,6 +97,23 @@ const AddPositionForm = () => {
5797
error={errors.title}
5898
/>
5999

100+
{/* ADDED: Organizational Unit field */}
101+
<FormSelect
102+
label="Organizational Unit"
103+
required
104+
value={formData.unit_id}
105+
onChange={(e) => handleInputChange("unit_id", e.target.value)}
106+
error={errors.unit_id}
107+
options={[
108+
{ value: "", label: "Select unit" },
109+
...scopedUnits.map((unit) => ({
110+
value: unit._id,
111+
label: unit.name,
112+
})),
113+
]}
114+
disabled={isCoordinator}
115+
/>
116+
60117
<FormSelect
61118
label="Position Type"
62119
required
@@ -75,6 +132,21 @@ const AddPositionForm = () => {
75132
]}
76133
/>
77134

135+
{/* ADDED: Custom position type field (shown when "Other" is selected) */}
136+
{formData.position_type === "Other" && (
137+
<FormInput
138+
label="Custom Position Type"
139+
required
140+
type="text"
141+
value={formData.custom_position_type}
142+
onChange={(e) =>
143+
handleInputChange("custom_position_type", e.target.value)
144+
}
145+
placeholder="Specify position type"
146+
error={errors.custom_position_type}
147+
/>
148+
)}
149+
78150
<FormInput
79151
label="Number of Positions"
80152
required
@@ -88,7 +160,65 @@ const AddPositionForm = () => {
88160
/>
89161
</div>
90162

91-
<div className="pt-4 grid grid-cols-1 md:grid-cols-2 gap-x-8 gap-y-6 border-t border-stone-200">
163+
{/* ADDED: Description field */}
164+
<div className="pt-4 border-t border-stone-200">
165+
<label className="block text-sm font-medium text-stone-700 mb-2">
166+
Description
167+
</label>
168+
<textarea
169+
value={formData.description}
170+
onChange={(e) => handleInputChange("description", e.target.value)}
171+
placeholder="Describe the position..."
172+
rows="4"
173+
className="w-full px-3 py-2 border border-stone-300 rounded-lg focus:outline-none focus:ring-2 focus:ring-stone-500"
174+
/>
175+
</div>
176+
177+
{/* ADDED: Requirements section */}
178+
<div className="pt-4 border-t border-stone-200">
179+
<h3 className="text-lg font-semibold text-stone-800 mb-4">
180+
Requirements
181+
</h3>
182+
<div className="grid grid-cols-1 md:grid-cols-2 gap-4 mb-4">
183+
<FormInput
184+
label="Minimum CGPA"
185+
type="number"
186+
step="0.1"
187+
min="0"
188+
max="10"
189+
value={formData.requirements.min_cgpa}
190+
onChange={(e) =>
191+
handleRequirementChange("min_cgpa", Number(e.target.value))
192+
}
193+
/>
194+
195+
<FormInput
196+
label="Minimum Year"
197+
type="number"
198+
min="1"
199+
max="5"
200+
value={formData.requirements.min_year}
201+
onChange={(e) =>
202+
handleRequirementChange("min_year", Number(e.target.value))
203+
}
204+
/>
205+
</div>
206+
207+
<DynamicFieldArray
208+
label="Skills Required"
209+
array={formData.requirements.skills_required}
210+
onUpdate={(index, value) =>
211+
handleRequirementArrayChange("skills_required", index, value)
212+
}
213+
onRemove={(index) =>
214+
removeFromRequirementArray("skills_required", index)
215+
}
216+
onAdd={() => addToRequirementArray("skills_required")}
217+
/>
218+
</div>
219+
220+
{/* Responsibilities */}
221+
<div className="pt-4 grid grid-cols-1 gap-y-6 border-t border-stone-200">
92222
<DynamicFieldArray
93223
label="Responsibilities"
94224
array={formData.responsibilities}

frontend/src/Components/Positions/PORs.jsx

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ import React, { useContext } from "react";
22
import { AdminContext } from "../../context/AdminContext";
33
import { CreateTenure, TenureRecords, ViewTenure } from "./TenureRecords";
44
import ManagePositions from "../ManagePosition";
5+
import ViewPositionHolder from "./ViewPositionHolder";
56

67
const PORs = () => {
78
const { isUserLoggedIn } = useContext(AdminContext);

0 commit comments

Comments
 (0)