latest
This commit is contained in:
parent
174910e6aa
commit
6614046568
3
.env
3
.env
|
|
@ -1 +1,4 @@
|
|||
# VITE_REACT_APP_BACKEND_URL="https://sandbox.exampaper.vidh.ai"
|
||||
VITE_REACT_APP_BACKEND_URL="http://localhost:9999"
|
||||
METABASE_BASE_URL="http://metabase.usln.in/public/question/d8774923-09bb-4cd9-903b-559d417e12cf"
|
||||
# VITE_REACT_APP_BACKEND_URL="https://api.exampaper.vidh.ai"
|
||||
|
|
@ -11,6 +11,7 @@ node_modules
|
|||
dist
|
||||
dist-ssr
|
||||
*.local
|
||||
*.zip
|
||||
|
||||
# Editor directories and files
|
||||
.vscode/*
|
||||
|
|
|
|||
Binary file not shown.
Binary file not shown.
|
|
@ -18,8 +18,12 @@
|
|||
"react": "^18.2.0",
|
||||
"react-bootstrap": "^2.10.2",
|
||||
"react-dom": "^18.2.0",
|
||||
"react-medium-image-zoom": "^5.2.4",
|
||||
"react-redux": "^9.1.2",
|
||||
"react-router-dom": "^6.23.1",
|
||||
"react-toastify": "^10.0.5"
|
||||
"react-toastify": "^10.0.5",
|
||||
"react-zoom-pan-pinch": "^3.4.4",
|
||||
"redux": "^5.0.1"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/react": "^18.2.66",
|
||||
|
|
@ -1961,6 +1965,11 @@
|
|||
"@types/react": "*"
|
||||
}
|
||||
},
|
||||
"node_modules/@types/use-sync-external-store": {
|
||||
"version": "0.0.3",
|
||||
"resolved": "https://registry.npmjs.org/@types/use-sync-external-store/-/use-sync-external-store-0.0.3.tgz",
|
||||
"integrity": "sha512-EwmlvuaxPNej9+T4v5AuBPJa2x2UOJVdjCtDHgcDqitUeOtjnJKJ+apYjVcAoBEMjKW1VVFGZLUb5+qqa09XFA=="
|
||||
},
|
||||
"node_modules/@types/warning": {
|
||||
"version": "3.0.3",
|
||||
"resolved": "https://registry.npmjs.org/@types/warning/-/warning-3.0.3.tgz",
|
||||
|
|
@ -5175,6 +5184,43 @@
|
|||
"resolved": "https://registry.npmjs.org/react-lifecycles-compat/-/react-lifecycles-compat-3.0.4.tgz",
|
||||
"integrity": "sha512-fBASbA6LnOU9dOU2eW7aQ8xmYBSXUIWr+UmF9b1efZBazGNO+rcXT/icdKnYm2pTwcRylVUYwW7H1PHfLekVzA=="
|
||||
},
|
||||
"node_modules/react-medium-image-zoom": {
|
||||
"version": "5.2.4",
|
||||
"resolved": "https://registry.npmjs.org/react-medium-image-zoom/-/react-medium-image-zoom-5.2.4.tgz",
|
||||
"integrity": "sha512-XLu/fLqpbmhiDAGA6yie78tDv4kh8GxvS7kKQArSOvCvm5zvgItoh4h01NAAvnezQ60ovsTeedHiHG3eG9CcGg==",
|
||||
"funding": [
|
||||
{
|
||||
"type": "github",
|
||||
"url": "https://github.com/sponsors/rpearce"
|
||||
}
|
||||
],
|
||||
"peerDependencies": {
|
||||
"react": "^16.8.0 || ^17.0.0 || ^18.0.0",
|
||||
"react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/react-redux": {
|
||||
"version": "9.1.2",
|
||||
"resolved": "https://registry.npmjs.org/react-redux/-/react-redux-9.1.2.tgz",
|
||||
"integrity": "sha512-0OA4dhM1W48l3uzmv6B7TXPCGmokUU4p1M44DGN2/D9a1FjVPukVjER1PcPX97jIg6aUeLq1XJo1IpfbgULn0w==",
|
||||
"dependencies": {
|
||||
"@types/use-sync-external-store": "^0.0.3",
|
||||
"use-sync-external-store": "^1.0.0"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@types/react": "^18.2.25",
|
||||
"react": "^18.0",
|
||||
"redux": "^5.0.0"
|
||||
},
|
||||
"peerDependenciesMeta": {
|
||||
"@types/react": {
|
||||
"optional": true
|
||||
},
|
||||
"redux": {
|
||||
"optional": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"node_modules/react-refresh": {
|
||||
"version": "0.14.2",
|
||||
"resolved": "https://registry.npmjs.org/react-refresh/-/react-refresh-0.14.2.tgz",
|
||||
|
|
@ -5241,6 +5287,24 @@
|
|||
"react-dom": ">=16.6.0"
|
||||
}
|
||||
},
|
||||
"node_modules/react-zoom-pan-pinch": {
|
||||
"version": "3.4.4",
|
||||
"resolved": "https://registry.npmjs.org/react-zoom-pan-pinch/-/react-zoom-pan-pinch-3.4.4.tgz",
|
||||
"integrity": "sha512-lGTu7D9lQpYEQ6sH+NSlLA7gicgKRW8j+D/4HO1AbSV2POvKRFzdWQ8eI0r3xmOsl4dYQcY+teV6MhULeg1xBw==",
|
||||
"engines": {
|
||||
"node": ">=8",
|
||||
"npm": ">=5"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"react": "*",
|
||||
"react-dom": "*"
|
||||
}
|
||||
},
|
||||
"node_modules/redux": {
|
||||
"version": "5.0.1",
|
||||
"resolved": "https://registry.npmjs.org/redux/-/redux-5.0.1.tgz",
|
||||
"integrity": "sha512-M9/ELqF6fy8FwmkpnF0S3YKOqMyoWJ4+CS5Efg2ct3oY9daQvd/Pc71FpGZsVsbl3Cpb+IIcjBDUnnyBdQbq4w=="
|
||||
},
|
||||
"node_modules/reflect.getprototypeof": {
|
||||
"version": "1.0.6",
|
||||
"resolved": "https://registry.npmjs.org/reflect.getprototypeof/-/reflect.getprototypeof-1.0.6.tgz",
|
||||
|
|
@ -5874,6 +5938,14 @@
|
|||
"punycode": "^2.1.0"
|
||||
}
|
||||
},
|
||||
"node_modules/use-sync-external-store": {
|
||||
"version": "1.2.2",
|
||||
"resolved": "https://registry.npmjs.org/use-sync-external-store/-/use-sync-external-store-1.2.2.tgz",
|
||||
"integrity": "sha512-PElTlVMwpblvbNqQ82d2n6RjStvdSoNe9FG28kNfz3WiXilJm4DdNkEzRhCZuIDwY8U08WVihhGR5iRqAwfDiw==",
|
||||
"peerDependencies": {
|
||||
"react": "^16.8.0 || ^17.0.0 || ^18.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/vite": {
|
||||
"version": "5.2.11",
|
||||
"resolved": "https://registry.npmjs.org/vite/-/vite-5.2.11.tgz",
|
||||
|
|
@ -7312,6 +7384,11 @@
|
|||
"@types/react": "*"
|
||||
}
|
||||
},
|
||||
"@types/use-sync-external-store": {
|
||||
"version": "0.0.3",
|
||||
"resolved": "https://registry.npmjs.org/@types/use-sync-external-store/-/use-sync-external-store-0.0.3.tgz",
|
||||
"integrity": "sha512-EwmlvuaxPNej9+T4v5AuBPJa2x2UOJVdjCtDHgcDqitUeOtjnJKJ+apYjVcAoBEMjKW1VVFGZLUb5+qqa09XFA=="
|
||||
},
|
||||
"@types/warning": {
|
||||
"version": "3.0.3",
|
||||
"resolved": "https://registry.npmjs.org/@types/warning/-/warning-3.0.3.tgz",
|
||||
|
|
@ -9599,6 +9676,21 @@
|
|||
"resolved": "https://registry.npmjs.org/react-lifecycles-compat/-/react-lifecycles-compat-3.0.4.tgz",
|
||||
"integrity": "sha512-fBASbA6LnOU9dOU2eW7aQ8xmYBSXUIWr+UmF9b1efZBazGNO+rcXT/icdKnYm2pTwcRylVUYwW7H1PHfLekVzA=="
|
||||
},
|
||||
"react-medium-image-zoom": {
|
||||
"version": "5.2.4",
|
||||
"resolved": "https://registry.npmjs.org/react-medium-image-zoom/-/react-medium-image-zoom-5.2.4.tgz",
|
||||
"integrity": "sha512-XLu/fLqpbmhiDAGA6yie78tDv4kh8GxvS7kKQArSOvCvm5zvgItoh4h01NAAvnezQ60ovsTeedHiHG3eG9CcGg==",
|
||||
"requires": {}
|
||||
},
|
||||
"react-redux": {
|
||||
"version": "9.1.2",
|
||||
"resolved": "https://registry.npmjs.org/react-redux/-/react-redux-9.1.2.tgz",
|
||||
"integrity": "sha512-0OA4dhM1W48l3uzmv6B7TXPCGmokUU4p1M44DGN2/D9a1FjVPukVjER1PcPX97jIg6aUeLq1XJo1IpfbgULn0w==",
|
||||
"requires": {
|
||||
"@types/use-sync-external-store": "^0.0.3",
|
||||
"use-sync-external-store": "^1.0.0"
|
||||
}
|
||||
},
|
||||
"react-refresh": {
|
||||
"version": "0.14.2",
|
||||
"resolved": "https://registry.npmjs.org/react-refresh/-/react-refresh-0.14.2.tgz",
|
||||
|
|
@ -9641,6 +9733,17 @@
|
|||
"prop-types": "^15.6.2"
|
||||
}
|
||||
},
|
||||
"react-zoom-pan-pinch": {
|
||||
"version": "3.4.4",
|
||||
"resolved": "https://registry.npmjs.org/react-zoom-pan-pinch/-/react-zoom-pan-pinch-3.4.4.tgz",
|
||||
"integrity": "sha512-lGTu7D9lQpYEQ6sH+NSlLA7gicgKRW8j+D/4HO1AbSV2POvKRFzdWQ8eI0r3xmOsl4dYQcY+teV6MhULeg1xBw==",
|
||||
"requires": {}
|
||||
},
|
||||
"redux": {
|
||||
"version": "5.0.1",
|
||||
"resolved": "https://registry.npmjs.org/redux/-/redux-5.0.1.tgz",
|
||||
"integrity": "sha512-M9/ELqF6fy8FwmkpnF0S3YKOqMyoWJ4+CS5Efg2ct3oY9daQvd/Pc71FpGZsVsbl3Cpb+IIcjBDUnnyBdQbq4w=="
|
||||
},
|
||||
"reflect.getprototypeof": {
|
||||
"version": "1.0.6",
|
||||
"resolved": "https://registry.npmjs.org/reflect.getprototypeof/-/reflect.getprototypeof-1.0.6.tgz",
|
||||
|
|
@ -10080,6 +10183,12 @@
|
|||
"punycode": "^2.1.0"
|
||||
}
|
||||
},
|
||||
"use-sync-external-store": {
|
||||
"version": "1.2.2",
|
||||
"resolved": "https://registry.npmjs.org/use-sync-external-store/-/use-sync-external-store-1.2.2.tgz",
|
||||
"integrity": "sha512-PElTlVMwpblvbNqQ82d2n6RjStvdSoNe9FG28kNfz3WiXilJm4DdNkEzRhCZuIDwY8U08WVihhGR5iRqAwfDiw==",
|
||||
"requires": {}
|
||||
},
|
||||
"vite": {
|
||||
"version": "5.2.11",
|
||||
"resolved": "https://registry.npmjs.org/vite/-/vite-5.2.11.tgz",
|
||||
|
|
|
|||
|
|
@ -20,8 +20,12 @@
|
|||
"react": "^18.2.0",
|
||||
"react-bootstrap": "^2.10.2",
|
||||
"react-dom": "^18.2.0",
|
||||
"react-medium-image-zoom": "^5.2.4",
|
||||
"react-redux": "^9.1.2",
|
||||
"react-router-dom": "^6.23.1",
|
||||
"react-toastify": "^10.0.5"
|
||||
"react-toastify": "^10.0.5",
|
||||
"react-zoom-pan-pinch": "^3.4.4",
|
||||
"redux": "^5.0.1"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/react": "^18.2.66",
|
||||
|
|
|
|||
12
src/App.jsx
12
src/App.jsx
|
|
@ -10,6 +10,8 @@ import ReassignedStats from "./Components/ReassignedStats";
|
|||
import IndividualExamCentreStats from "./Components/IndividualExamCentreStats";
|
||||
import PartAReassigned from "./Components/PartAReassigned";
|
||||
import PartACorrection from "./Components/PartACorrection";
|
||||
import Verification from "./Components/Verification";
|
||||
import Statistics from "./Components/Statistics";
|
||||
|
||||
function App() {
|
||||
return (
|
||||
|
|
@ -36,15 +38,21 @@ function App() {
|
|||
element={<IndividualExamCentreStats/>}
|
||||
>
|
||||
</Route>
|
||||
{/* <Route
|
||||
<Route
|
||||
path="/anomoly/PartA"
|
||||
element={<PartAReassigned/>}
|
||||
>
|
||||
</Route>
|
||||
{/* <Route
|
||||
path="/verification"
|
||||
element={<Verification/>}
|
||||
>
|
||||
</Route> */}
|
||||
<Route path="/statistics" element={<Statistics/>}></Route>
|
||||
<Route path="/anomoly/partA/booklet"
|
||||
element={<PartACorrection/>}
|
||||
>
|
||||
</Route> */}
|
||||
</Route>
|
||||
</Routes>
|
||||
</BrowserRouter>
|
||||
</>
|
||||
|
|
|
|||
|
|
@ -22,6 +22,8 @@ import HomeIcon from "@mui/icons-material/Home";
|
|||
import ArrowBackIcon from "@mui/icons-material/ArrowBack";
|
||||
import { useNavigate } from "react-router-dom";
|
||||
import QueryStatsIcon from "@mui/icons-material/QueryStats";
|
||||
import { updateAttendenceAnomolyData } from "../redux/actions/actions";
|
||||
import { useDispatch, useSelector } from "react-redux";
|
||||
|
||||
const { Header, Content, Footer, Sider } = Layout;
|
||||
function getItem(label, key, icon, children) {
|
||||
|
|
@ -32,26 +34,24 @@ function getItem(label, key, icon, children) {
|
|||
label,
|
||||
};
|
||||
}
|
||||
// const items = [
|
||||
// getItem('Option 1', '1', <PieChartOutlined />),
|
||||
// getItem('Option 2', '2', <DesktopOutlined />),
|
||||
// getItem('User', 'sub1', <UserOutlined />, [
|
||||
// getItem('Tom', '3'),
|
||||
// getItem('Bill', '4'),
|
||||
// getItem('Alex', '5'),
|
||||
// ]),
|
||||
// getItem('Team', 'sub2', <TeamOutlined />, [getItem('Team 1', '6'), getItem('Team 2', '8')]),
|
||||
// getItem('Files', '9', <FileOutlined />),
|
||||
// ];
|
||||
|
||||
|
||||
const items = [getItem("Reassigned Booklet No", "1", <PieChartOutlined />)];
|
||||
|
||||
const AnomolyReassigned = () => {
|
||||
const [collapsed, setCollapsed] = useState(false);
|
||||
const [anomolyData, setAnomolyData] = useState([]);
|
||||
const [filteredAnomolyData,setFilterAnomolyData] = useState([])
|
||||
const [tableRowData, setTableRowData] = useState([]);
|
||||
const [isLoading, setIsLoading] = useState(false);
|
||||
const [windowWidth, setWindowWidth] = useState(window.innerWidth);
|
||||
const [distinctExamCentreCodes,setDistinctExamCentreCodes] = useState([])
|
||||
const dispatch = useDispatch();
|
||||
const reduxAnomolyData = useSelector((state) => state.attendenceAnomolyData);
|
||||
const [filterSelectedExamCentreCode,setFilterSelectedExamCentreCode] = useState("")
|
||||
|
||||
// Log Redux store state
|
||||
console.log("Redux store state after dispatch:", reduxAnomolyData);
|
||||
|
||||
useEffect(() => {
|
||||
const handleResize = () => {
|
||||
|
|
@ -95,16 +95,41 @@ const AnomolyReassigned = () => {
|
|||
};
|
||||
}
|
||||
|
||||
useEffect(()=>{
|
||||
const tmpData = [];
|
||||
for (const data of anomolyData) {
|
||||
tmpData.push(
|
||||
createData(
|
||||
data.attendence_serial_no,
|
||||
data.student_slno,
|
||||
data.exam_centre_code,
|
||||
data.exam_centre,
|
||||
data.student_name,
|
||||
data.register_number,
|
||||
data.reassigned_serial_no
|
||||
)
|
||||
);
|
||||
}
|
||||
console.log("Tmp data is : ", tmpData);
|
||||
if (tmpData.length > 0) {
|
||||
setTableRowData(tmpData);
|
||||
}
|
||||
},[anomolyData])
|
||||
|
||||
const fetchAnomalyData = () => {
|
||||
console.log("Fetching.......");
|
||||
setIsLoading(true);
|
||||
fetch(`${import.meta.env.VITE_REACT_APP_BACKEND_URL}/fetchAnamolyAttendenceData`, {
|
||||
method: "GET",
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
},
|
||||
})
|
||||
fetch(
|
||||
`${
|
||||
import.meta.env.VITE_REACT_APP_BACKEND_URL
|
||||
}/fetchAnamolyAttendenceData`,
|
||||
{
|
||||
method: "GET",
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
},
|
||||
}
|
||||
)
|
||||
.then((response) => {
|
||||
console.log("Response fetched..");
|
||||
return response.json();
|
||||
|
|
@ -113,25 +138,24 @@ const AnomolyReassigned = () => {
|
|||
console.log("Response Data is : ", responseData);
|
||||
setIsLoading(false);
|
||||
if (responseData.status === "success") {
|
||||
setAnomolyData(responseData.data);
|
||||
const tmpData = [];
|
||||
for (const data of responseData.data) {
|
||||
tmpData.push(
|
||||
createData(
|
||||
data.attendence_serial_no,
|
||||
data.student_slno,
|
||||
data.exam_centre_code,
|
||||
data.exam_centre,
|
||||
data.student_name,
|
||||
data.register_number,
|
||||
data.reassigned_serial_no
|
||||
)
|
||||
);
|
||||
}
|
||||
console.log("Tmp data is : ", tmpData);
|
||||
if (tmpData.length > 0) {
|
||||
setTableRowData(tmpData);
|
||||
setAnomolyData(responseData?.data);
|
||||
const tmpExamCentreCodes = [];
|
||||
const distinctExamCentreCodesSet = new Set(distinctExamCentreCodes);
|
||||
|
||||
for (var data of responseData?.data) {
|
||||
if (!distinctExamCentreCodesSet.has(data.exam_centre_code)) {
|
||||
distinctExamCentreCodesSet.add(data.exam_centre_code);
|
||||
tmpExamCentreCodes.push(data.exam_centre_code);
|
||||
}
|
||||
setFilterAnomolyData([...tmpExamCentreCodes])
|
||||
}
|
||||
|
||||
|
||||
setDistinctExamCentreCodes([...distinctExamCentreCodesSet]);
|
||||
console.log("Tmp exam centre code: ", tmpExamCentreCodes);
|
||||
|
||||
// console.log("Data to be stored in store : ", responseData?.data);
|
||||
dispatch(updateAttendenceAnomolyData(responseData?.data));
|
||||
}
|
||||
})
|
||||
.catch((error) => {
|
||||
|
|
@ -141,10 +165,28 @@ const AnomolyReassigned = () => {
|
|||
};
|
||||
|
||||
useEffect(() => {
|
||||
fetchAnomalyData();
|
||||
if (reduxAnomolyData.length > 0) {
|
||||
console.log("Redux anomoly data found")
|
||||
setAnomolyData(reduxAnomolyData)
|
||||
} else {
|
||||
console.log("Redux anomoly data not found")
|
||||
fetchAnomalyData();
|
||||
}
|
||||
}, []);
|
||||
|
||||
|
||||
useEffect(()=>{
|
||||
const tmpData = []
|
||||
for(var data in anomolyData){
|
||||
if(data?.exam_centre_code == filterSelectedExamCentreCode){
|
||||
tmpData.push(data)
|
||||
}
|
||||
}
|
||||
|
||||
},[filterSelectedExamCentreCode])
|
||||
|
||||
|
||||
|
||||
const {
|
||||
token: { colorBgContainer, borderRadiusLG },
|
||||
} = theme.useToken();
|
||||
|
|
@ -214,10 +256,18 @@ const AnomolyReassigned = () => {
|
|||
<Box className="w-100 d-flex justify-content-center">
|
||||
{tableRowData.length > 0 && (
|
||||
<TableComponent
|
||||
filterSelectedExamCentreCode = {filterSelectedExamCentreCode}
|
||||
setFilterSelectedExamCentreCode = {setFilterSelectedExamCentreCode}
|
||||
rows={tableRowData}
|
||||
type={"AnomolyReassigned"}
|
||||
distinctExamCentreCodes = {distinctExamCentreCodes}
|
||||
/>
|
||||
)}
|
||||
{tableRowData.length == 0 && (
|
||||
<Box className="w-100 d-flex justify-content-center py-2 align-items-center text-center">
|
||||
<h6>No Data Found !!</h6>
|
||||
</Box>
|
||||
)}
|
||||
</Box>
|
||||
</Box>
|
||||
</Content>
|
||||
|
|
|
|||
|
|
@ -17,11 +17,14 @@ import { ToastContainer, toast } from "react-toastify";
|
|||
import "react-toastify/dist/ReactToastify.css";
|
||||
import { useSearchParams } from "react-router-dom";
|
||||
import LoadingContainer from "./LoadingContainer";
|
||||
import HomeIcon from '@mui/icons-material/Home';
|
||||
import ArrowBackIcon from '@mui/icons-material/ArrowBack';
|
||||
import HomeIcon from "@mui/icons-material/Home";
|
||||
import ArrowBackIcon from "@mui/icons-material/ArrowBack";
|
||||
import { useNavigate } from "react-router-dom";
|
||||
import QueryStatsIcon from '@mui/icons-material/QueryStats';
|
||||
|
||||
import QueryStatsIcon from "@mui/icons-material/QueryStats";
|
||||
import { useDispatch, useSelector } from "react-redux";
|
||||
import { updateAttendenceAnomolyData } from "../redux/actions/actions";
|
||||
import RotateLeftIcon from "@mui/icons-material/RotateLeft";
|
||||
import RotateRightIcon from "@mui/icons-material/RotateRight";
|
||||
|
||||
const { Header, Content, Footer, Sider } = Layout;
|
||||
function getItem(label, key, icon, children) {
|
||||
|
|
@ -47,6 +50,7 @@ function getItem(label, key, icon, children) {
|
|||
const items = [getItem("Reassigned Booklet No", "1", <PieChartOutlined />)];
|
||||
|
||||
const AttendenceCorrection = () => {
|
||||
console.log("Checking1 ...");
|
||||
const [collapsed, setCollapsed] = useState(false);
|
||||
const [bookletInput, setBookletInput] = useState(null);
|
||||
const [dataFetched, setDataFetched] = useState(false);
|
||||
|
|
@ -54,10 +58,29 @@ const AttendenceCorrection = () => {
|
|||
const [updateReassigned, setUpdateReassigned] = useState(false);
|
||||
const [reasssingedSno, setReassignedSno] = useState(null);
|
||||
const [isLoading, setIsLoading] = useState(false);
|
||||
const navigate = useNavigate()
|
||||
const [registerNumber, setRegisterNumber] = useState(null);
|
||||
const [backgroundPosition, setBackgroundPosition] = useState("0% 0%");
|
||||
const [zoomed, setZoomed] = useState(false);
|
||||
const dispatch = useDispatch();
|
||||
const [scaleWidthValue, setScaleWidthValue] = useState(80);
|
||||
const [rotateValue, setRotateValue] = useState(0);
|
||||
|
||||
const reduxAnomolyData = useSelector((state) => state.attendenceAnomolyData);
|
||||
// console.log("Anomoly Data is : ", reduxAnomolyData);
|
||||
const [anomolyData, setAnomolyData] = useState([]);
|
||||
|
||||
const handleMouseMove = (e) => {
|
||||
const { left, top, width, height } = e.target.getBoundingClientRect();
|
||||
const x = ((e.pageX - left) / width) * 100;
|
||||
const y = ((e.pageY - top) / height) * 100;
|
||||
setBackgroundPosition(`${x}% ${y}%`);
|
||||
setZoomed(true);
|
||||
};
|
||||
|
||||
const navigate = useNavigate();
|
||||
let [searchParams, setSearchParams] = useSearchParams();
|
||||
const searchParamsBookletSerialNo = searchParams.get("sno");
|
||||
console.log("Serach parmas sno : ", searchParamsBookletSerialNo);
|
||||
// console.log("Serach parmas sno : ", searchParamsBookletSerialNo);
|
||||
const [windowWidth, setWindowWidth] = useState(window.innerWidth);
|
||||
|
||||
useEffect(() => {
|
||||
|
|
@ -65,19 +88,19 @@ const AttendenceCorrection = () => {
|
|||
setWindowWidth(window.innerWidth);
|
||||
};
|
||||
|
||||
window.addEventListener('resize', handleResize);
|
||||
window.addEventListener("resize", handleResize);
|
||||
|
||||
return () => {
|
||||
window.removeEventListener('resize', handleResize);
|
||||
window.removeEventListener("resize", handleResize);
|
||||
};
|
||||
}, []);
|
||||
|
||||
useEffect(() => {
|
||||
if (windowWidth < 800) {
|
||||
setCollapsed(true)
|
||||
setCollapsed(true);
|
||||
}
|
||||
if(windowWidth > 800){
|
||||
setCollapsed(false)
|
||||
if (windowWidth > 800) {
|
||||
setCollapsed(false);
|
||||
}
|
||||
}, [windowWidth]);
|
||||
|
||||
|
|
@ -91,29 +114,68 @@ const AttendenceCorrection = () => {
|
|||
submitBookletInput();
|
||||
}, [bookletInput]);
|
||||
|
||||
|
||||
|
||||
const {
|
||||
token: { colorBgContainer, borderRadiusLG },
|
||||
} = theme.useToken();
|
||||
|
||||
useEffect(() => {
|
||||
if (reduxAnomolyData.length === 0) {
|
||||
fetchAnomalyData();
|
||||
}
|
||||
}, []);
|
||||
|
||||
const fetchAnomalyData = () => {
|
||||
console.log("Fetching.......");
|
||||
setIsLoading(true);
|
||||
fetch(
|
||||
`${
|
||||
import.meta.env.VITE_REACT_APP_BACKEND_URL
|
||||
}/fetchAnamolyAttendenceData`,
|
||||
{
|
||||
method: "GET",
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
},
|
||||
}
|
||||
)
|
||||
.then((response) => {
|
||||
console.log("Response fetched..");
|
||||
return response.json();
|
||||
})
|
||||
.then((responseData) => {
|
||||
console.log("Response Data is : ", responseData);
|
||||
setIsLoading(false);
|
||||
if (responseData.status === "success") {
|
||||
setAnomolyData(responseData?.data);
|
||||
console.log("Data to be stored in store : ", responseData?.data);
|
||||
dispatch(updateAttendenceAnomolyData(responseData?.data));
|
||||
}
|
||||
})
|
||||
.catch((error) => {
|
||||
console.error("Error fetching data: ", error);
|
||||
setIsLoading(false);
|
||||
});
|
||||
};
|
||||
|
||||
const submitBookletInput = async () => {
|
||||
setIsLoading(true);
|
||||
setStudentData(null);
|
||||
if (!bookletInput) {
|
||||
console.log("Returning");
|
||||
return;
|
||||
}
|
||||
const payload = {
|
||||
bookletInput,
|
||||
};
|
||||
const response = await fetch(`${import.meta.env.VITE_REACT_APP_BACKEND_URL}/fetchBookletInfo`, {
|
||||
method: "POST",
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
},
|
||||
body: JSON.stringify(payload),
|
||||
});
|
||||
const response = await fetch(
|
||||
`${import.meta.env.VITE_REACT_APP_BACKEND_URL}/fetchBookletInfo`,
|
||||
{
|
||||
method: "POST",
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
},
|
||||
body: JSON.stringify(payload),
|
||||
}
|
||||
);
|
||||
const responseData = await response.json();
|
||||
console.log("Response Data is : ", responseData);
|
||||
setDataFetched(true);
|
||||
|
|
@ -125,26 +187,133 @@ const AttendenceCorrection = () => {
|
|||
}
|
||||
if (responseData.data) {
|
||||
setStudentData(responseData.data[0]);
|
||||
const student_data = responseData.data[0];
|
||||
setRegisterNumber(student_data?.register_number);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
const url = `https://docs.exampaper.vidh.ai/${studentData?.s3_path}`;
|
||||
// console.log("Url is : ", url);
|
||||
const figureStyle = {
|
||||
backgroundImage: `url(${url})`,
|
||||
backgroundPosition: zoomed ? backgroundPosition : "center",
|
||||
backgroundSize: zoomed ? "200%" : "cover",
|
||||
height: "100%", // Adjust the height as needed
|
||||
width: "60%", // Adjust the width as needed
|
||||
border: "1px solid #ddd",
|
||||
overflow: "hidden",
|
||||
};
|
||||
|
||||
const ZoomInImage = () => {
|
||||
console.log("Zooming In Image ....");
|
||||
const elements = document.getElementsByClassName("scanned-img");
|
||||
for (var ele of elements) {
|
||||
console.log("Ele is : ", ele);
|
||||
const newScaleWidthValue = scaleWidthValue + 10;
|
||||
setScaleWidthValue(newScaleWidthValue);
|
||||
// ele.style.transform = `scale(${newScaleValue})`;
|
||||
ele.style.width = `${newScaleWidthValue}%`;
|
||||
}
|
||||
};
|
||||
|
||||
const ZoomOutImage = () => {
|
||||
console.log("Zooming Out Image ....");
|
||||
const elements = document.getElementsByClassName("scanned-img");
|
||||
for (var ele of elements) {
|
||||
console.log("Ele is : ", ele);
|
||||
const newScaleWidthValue = scaleWidthValue - 10;
|
||||
setScaleWidthValue(newScaleWidthValue);
|
||||
// ele.style.transform = `scale(${newScaleValue})`;
|
||||
ele.style.width = `${newScaleWidthValue}%`;
|
||||
}
|
||||
};
|
||||
|
||||
const RotateImageLeft = () => {
|
||||
const elements = document.getElementsByClassName("scanned-img");
|
||||
for (var ele of elements) {
|
||||
console.log("Ele is : ", ele);
|
||||
const newRotateValue = rotateValue - 90;
|
||||
setRotateValue(newRotateValue);
|
||||
ele.style.transform = `rotate(${newRotateValue}deg)`;
|
||||
}
|
||||
};
|
||||
|
||||
const RotateImageRight = () => {
|
||||
const elements = document.getElementsByClassName("scanned-img");
|
||||
for (var ele of elements) {
|
||||
console.log("Ele is : ", ele);
|
||||
const newRotateValue = rotateValue + 90;
|
||||
setRotateValue(newRotateValue);
|
||||
ele.style.transform = `rotate(${newRotateValue}deg)`;
|
||||
}
|
||||
};
|
||||
|
||||
const ImageStyle = {
|
||||
// transform: `scale(${scaleValue})`,
|
||||
transformOrigin: "left", // Adjust the zoom origin as needed
|
||||
transition: "transform 0.2s ease-in-out",
|
||||
};
|
||||
|
||||
const containerStyle = {
|
||||
width: "auto", // Set the width and height as needed
|
||||
maxHeight: "90%",
|
||||
overflowX: "scroll",
|
||||
position: "relative",
|
||||
};
|
||||
|
||||
const handleMouseLeave = () => {
|
||||
setBackgroundPosition("0% 0%");
|
||||
setZoomed(false);
|
||||
};
|
||||
|
||||
const updateReassignedSno = async () => {
|
||||
setIsLoading(true);
|
||||
// if(reduxAnomolyData.length === 0){
|
||||
// console.log("Redux anomoly data length is 0.......")
|
||||
// fetchAnomalyData()
|
||||
// }
|
||||
console.log("Reassgined Sno : ", reasssingedSno);
|
||||
const payload = {
|
||||
bookletInput,
|
||||
reasssingedSno,
|
||||
registerNumber,
|
||||
};
|
||||
const response = await fetch(`${import.meta.env.VITE_REACT_APP_BACKEND_URL}/updateReassingedSno`, {
|
||||
method: "POST",
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
},
|
||||
body: JSON.stringify(payload),
|
||||
});
|
||||
const response = await fetch(
|
||||
`${import.meta.env.VITE_REACT_APP_BACKEND_URL}/updateReassingedSno`,
|
||||
{
|
||||
method: "POST",
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
},
|
||||
body: JSON.stringify(payload),
|
||||
}
|
||||
);
|
||||
const responseData = await response.json();
|
||||
setIsLoading(false);
|
||||
setReassignedSno(null);
|
||||
if (responseData.status === "success" && responseData?.status_code == 200) {
|
||||
console.log("Updation success");
|
||||
toast.success("Record Updated Successfully !!");
|
||||
var index = 0
|
||||
var RecordIndex = 0
|
||||
const filteredData = reduxAnomolyData.filter((data) => {
|
||||
if (data?.student_slno === searchParamsBookletSerialNo) {
|
||||
RecordIndex = index
|
||||
console.log("data matched : ", data);
|
||||
return false; // Return false to remove the matched item
|
||||
}
|
||||
index += 1
|
||||
return true; // Keep the unmatched items
|
||||
});
|
||||
|
||||
console.log("Filtered Data: ", filteredData);
|
||||
dispatch(updateAttendenceAnomolyData(filteredData));
|
||||
if (filteredData.length > 0) {
|
||||
navigate(
|
||||
`/anomoly/reassigned/booklet?sno=${filteredData[RecordIndex].student_slno}`
|
||||
);
|
||||
}
|
||||
} else if (
|
||||
responseData.status === "success" &&
|
||||
responseData?.status_code == 405
|
||||
|
|
@ -154,6 +323,45 @@ const AttendenceCorrection = () => {
|
|||
}
|
||||
};
|
||||
|
||||
const markAsAssigned = async () => {
|
||||
setIsLoading(true);
|
||||
const payload = { bookletInput };
|
||||
const response = await fetch(
|
||||
`${import.meta.env.VITE_REACT_APP_BACKEND_URL}/markAsAssigned`,
|
||||
{
|
||||
method: "POST",
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
},
|
||||
body: JSON.stringify(payload),
|
||||
}
|
||||
);
|
||||
const responseData = await response.json();
|
||||
setIsLoading(false);
|
||||
if (responseData.status === "success") {
|
||||
toast.success("Record Updated Successfully !!");
|
||||
var index = 0
|
||||
var RecordIndex = 0
|
||||
const filteredData = reduxAnomolyData.filter((data) => {
|
||||
if (data?.student_slno === searchParamsBookletSerialNo) {
|
||||
RecordIndex = index
|
||||
console.log("data matched : ", data);
|
||||
return false; // Return false to remove the matched item
|
||||
}
|
||||
index += 1
|
||||
return true; // Keep the unmatched items
|
||||
});
|
||||
|
||||
console.log("Filtered Data: ", filteredData);
|
||||
dispatch(updateAttendenceAnomolyData(filteredData));
|
||||
if (filteredData.length > 0) {
|
||||
navigate(
|
||||
`/anomoly/reassigned/booklet?sno=${filteredData[RecordIndex].student_slno}`
|
||||
);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
<Layout
|
||||
style={{
|
||||
|
|
@ -181,7 +389,7 @@ const AttendenceCorrection = () => {
|
|||
background: colorBgContainer,
|
||||
}}
|
||||
>
|
||||
<Box className="d-flex justify-content-between h-100 py-1 px-2">
|
||||
<Box className="d-flex justify-content-between h-100 py-1 px-2">
|
||||
<Button
|
||||
className="bg-primary p-1 text-light"
|
||||
onClick={() => {
|
||||
|
|
@ -237,102 +445,96 @@ const AttendenceCorrection = () => {
|
|||
<Box className="w-100 d-flex flex-column flex-md-row justify-content-between">
|
||||
<Box className="w-25 d-none d-md-flex flex-column">
|
||||
<Box className="d-flex justify-content-between">
|
||||
<BookletInput
|
||||
{/* <BookletInput
|
||||
className="d-flex flex-1"
|
||||
setBookletInput={setBookletInput}
|
||||
bookletInput={bookletInput}
|
||||
setDataFetched={setDataFetched}
|
||||
/>
|
||||
<Button
|
||||
/> */}
|
||||
|
||||
{/* <Button
|
||||
className="px-md-5 px-2 mx-1 mx-md-2 text-light bg-primary"
|
||||
onClick={submitBookletInput}
|
||||
>
|
||||
Submit
|
||||
</Button>
|
||||
</Button> */}
|
||||
</Box>
|
||||
{!isLoading && !studentData && (
|
||||
{/* {!isLoading && !studentData && (
|
||||
<Box className="w-100 py-5">
|
||||
<h6>Invalid Booklet Serial No !!</h6>
|
||||
</Box>
|
||||
)}
|
||||
{dataFetched && studentData && (
|
||||
)} */}
|
||||
{studentData && (
|
||||
<>
|
||||
<Box>
|
||||
<Box className="d-flex justify-content-start px-2 py-3">
|
||||
<h6>Booklet Info:</h6>
|
||||
<h6>
|
||||
<u>Booklet Info:</u>
|
||||
</h6>
|
||||
</Box>
|
||||
|
||||
<Box className="px-2">
|
||||
<Box className="d-flex flex-column align-items-start gap-2 py-2">
|
||||
<label for="student-name-input">Student Name:</label>
|
||||
<TextField
|
||||
id="student-name-input"
|
||||
disabled="true"
|
||||
className="w-100"
|
||||
value={studentData.student_name}
|
||||
/>
|
||||
</Box>
|
||||
<Box className="d-flex flex-column align-items-start gap-2 py-2">
|
||||
<label for="exam-centre-code-input">
|
||||
Exam Center Code:
|
||||
<label for="student-name-input" className="h6">
|
||||
<u>Booklet Serial No:</u>
|
||||
</label>
|
||||
<TextField
|
||||
id="exam-centre-code-input"
|
||||
disabled="true"
|
||||
className="w-100"
|
||||
value={studentData.exam_centre_code}
|
||||
/>
|
||||
<h5>{bookletInput}</h5>
|
||||
</Box>
|
||||
<Box className="d-flex flex-column align-items-start gap-2 py-2">
|
||||
<label for="exam-centre-input">Exam Centre:</label>
|
||||
<TextField
|
||||
id="exam-centre-input"
|
||||
disabled="true"
|
||||
className="w-100"
|
||||
value={studentData.exam_centre}
|
||||
/>
|
||||
<label for="student-name-input" className="h6">
|
||||
<u>Student Name:</u>
|
||||
</label>
|
||||
<h5>{studentData?.student_name}</h5>
|
||||
</Box>
|
||||
<Box className="d-flex flex-column align-items-start gap-2 py-2">
|
||||
<label for="exam-date-input">Exam Date:</label>
|
||||
<TextField
|
||||
id="exam-date-input"
|
||||
disabled="true"
|
||||
className="w-100"
|
||||
value={studentData.exam_date}
|
||||
/>
|
||||
<label for="exam-centre-code-input" className="h6">
|
||||
<u>Exam Center Code:</u>
|
||||
</label>
|
||||
<h5>{studentData?.exam_centre_code}</h5>
|
||||
</Box>
|
||||
<Box className="d-flex flex-column align-items-start gap-2 py-2">
|
||||
<label for="exam-centre-input" className="h6">
|
||||
<u>Exam Centre:</u>
|
||||
</label>
|
||||
<h5>{studentData.exam_centre}</h5>
|
||||
</Box>
|
||||
<Box className="d-flex flex-column align-items-start gap-2 py-2">
|
||||
<label for="exam-date-input" className="h6">
|
||||
<u>Exam Date:</u>
|
||||
</label>
|
||||
<h5>{studentData?.exam_date}</h5>
|
||||
</Box>
|
||||
<Box className="d-flex flex-column align-items-start gap-2 py-2">
|
||||
<label for="reassigned-serial-no-input">
|
||||
Reassigned Serial No:
|
||||
<u>Reassigned Serial No:</u>
|
||||
</label>
|
||||
<Box className="d-flex justify-content-between w-100">
|
||||
<TextField
|
||||
id="reassigned-serial-no-input"
|
||||
disabled={!updateReassigned}
|
||||
className="w-100"
|
||||
value={studentData.reassigned_serial_no}
|
||||
placeholder={`Please enter the SNo.${studentData?.rownumber} Answer Booklet No`}
|
||||
autoComplete="off"
|
||||
onChange={(e) => {
|
||||
setReassignedSno(e.target.value);
|
||||
}}
|
||||
/>
|
||||
<Button
|
||||
onClick={() => {
|
||||
setUpdateReassigned(!updateReassigned);
|
||||
}}
|
||||
>
|
||||
<EditButton />
|
||||
</Button>
|
||||
</Box>
|
||||
</Box>
|
||||
<Box className="py-2 d-flex justify-content-start">
|
||||
<Box className="py-2 d-flex justify-content-start flex-column gap-2">
|
||||
<Button
|
||||
className="text-light bg-primary p-3"
|
||||
disabled={!updateReassigned}
|
||||
className="text-light bg-primary p-3 w-100"
|
||||
disabled={!reasssingedSno}
|
||||
onClick={updateReassignedSno}
|
||||
>
|
||||
Update
|
||||
</Button>
|
||||
<Button
|
||||
className="text-light bg-primary p-3 w-100"
|
||||
onClick={markAsAssigned}
|
||||
>
|
||||
Mark As Assigned
|
||||
</Button>
|
||||
</Box>
|
||||
</Box>
|
||||
</Box>
|
||||
|
|
@ -340,125 +542,163 @@ const AttendenceCorrection = () => {
|
|||
)}
|
||||
</Box>
|
||||
<Box className="w-md-25 d-flex d-md-none flex-column">
|
||||
<Box className="d-flex justify-content-between">
|
||||
<BookletInput
|
||||
className="d-flex flex-1"
|
||||
setBookletInput={setBookletInput}
|
||||
bookletInput={bookletInput}
|
||||
setDataFetched={setDataFetched}
|
||||
/>
|
||||
<Button
|
||||
className="px-md-5 px-2 mx-1 mx-md-2 text-light bg-primary"
|
||||
onClick={submitBookletInput}
|
||||
>
|
||||
Submit
|
||||
</Button>
|
||||
</Box>
|
||||
{!isLoading && !studentData && (
|
||||
{/* {!isLoading && !studentData && (
|
||||
<Box className="w-100 py-5">
|
||||
<h6>Invalid Booklet Serial No !!</h6>
|
||||
</Box>
|
||||
)}
|
||||
{dataFetched && studentData && (
|
||||
)} */}
|
||||
{studentData && (
|
||||
<>
|
||||
<Box>
|
||||
<Box className="d-flex justify-content-start px-2 py-3">
|
||||
<h6>Booklet Info:</h6>
|
||||
<h6>
|
||||
<u>Booklet Info:</u>
|
||||
</h6>
|
||||
</Box>
|
||||
|
||||
<Box className="px-2">
|
||||
<Box className="d-flex flex-column align-items-start gap-2 py-2">
|
||||
<label for="student-name-input">Student Name:</label>
|
||||
<TextField
|
||||
id="student-name-input"
|
||||
disabled="true"
|
||||
className="w-100"
|
||||
value={studentData.student_name}
|
||||
/>
|
||||
</Box>
|
||||
<Box className="d-flex flex-column align-items-start gap-2 py-2">
|
||||
<label for="exam-centre-code-input">
|
||||
Exam Center Code:
|
||||
<label for="student-name-input" className="h6">
|
||||
<u>Booklet Serial No:</u>
|
||||
</label>
|
||||
<TextField
|
||||
id="exam-centre-code-input"
|
||||
disabled="true"
|
||||
className="w-100"
|
||||
value={studentData.exam_centre_code}
|
||||
/>
|
||||
<h5>{bookletInput}</h5>
|
||||
</Box>
|
||||
<Box className="d-flex flex-column align-items-start gap-2 py-2">
|
||||
<label for="exam-centre-input">Exam Centre:</label>
|
||||
<TextField
|
||||
id="exam-centre-input"
|
||||
disabled="true"
|
||||
className="w-100"
|
||||
value={studentData.exam_centre}
|
||||
/>
|
||||
<label for="student-name-input" className="h6">
|
||||
<u>Student Name:</u>
|
||||
</label>
|
||||
<h5>{studentData?.student_name}</h5>
|
||||
</Box>
|
||||
<Box className="d-flex flex-column align-items-start gap-2 py-2">
|
||||
<label for="exam-date-input">Exam Date:</label>
|
||||
<TextField
|
||||
id="exam-date-input"
|
||||
disabled="true"
|
||||
className="w-100"
|
||||
value={studentData.exam_date}
|
||||
/>
|
||||
<label for="exam-centre-code-input" className="h6">
|
||||
<u>Exam Center Code:</u>
|
||||
</label>
|
||||
<h5>{studentData?.exam_centre_code}</h5>
|
||||
</Box>
|
||||
<Box className="d-flex flex-column align-items-start gap-2 py-2">
|
||||
<label for="exam-centre-input" className="h6">
|
||||
<u>Exam Centre:</u>
|
||||
</label>
|
||||
<h5>{studentData.exam_centre}</h5>
|
||||
</Box>
|
||||
<Box className="d-flex flex-column align-items-start gap-2 py-2">
|
||||
<label for="exam-date-input" className="h6">
|
||||
<u>Exam Date:</u>
|
||||
</label>
|
||||
<h5>{studentData?.exam_date}</h5>
|
||||
</Box>
|
||||
<Box className="d-flex flex-column align-items-start gap-2 py-2">
|
||||
<label for="reassigned-serial-no-input">
|
||||
Reassigned Serial No:
|
||||
<u>Reassigned Serial No:</u>
|
||||
</label>
|
||||
<Box className="d-flex justify-content-between w-100">
|
||||
<TextField
|
||||
id="reassigned-serial-no-input"
|
||||
disabled={!updateReassigned}
|
||||
className="w-100"
|
||||
value={studentData.reassigned_serial_no}
|
||||
placeholder={`Please enter the SNo.${studentData?.rownumber} Answer Booklet No`}
|
||||
autoComplete="off"
|
||||
onChange={(e) => {
|
||||
setReassignedSno(e.target.value);
|
||||
}}
|
||||
/>
|
||||
<Button
|
||||
onClick={() => {
|
||||
setUpdateReassigned(!updateReassigned);
|
||||
}}
|
||||
>
|
||||
<EditButton />
|
||||
</Button>
|
||||
</Box>
|
||||
</Box>
|
||||
<Box className="py-2 d-flex justify-content-start">
|
||||
<Box className="py-2 d-flex justify-content-start flex-column gap-2">
|
||||
<Button
|
||||
className="text-light bg-primary p-3"
|
||||
disabled={!updateReassigned}
|
||||
className="text-light bg-primary p-3 w-100"
|
||||
disabled={!reasssingedSno}
|
||||
onClick={updateReassignedSno}
|
||||
>
|
||||
Update
|
||||
</Button>
|
||||
<Button
|
||||
className="text-light bg-primary p-3 w-100"
|
||||
onClick={markAsAssigned}
|
||||
>
|
||||
Mark As Assigned
|
||||
</Button>
|
||||
</Box>
|
||||
</Box>
|
||||
</Box>
|
||||
</>
|
||||
)}
|
||||
</Box>
|
||||
<Box className="w-75 d-none d-md-block">
|
||||
{dataFetched && studentData && (
|
||||
<img
|
||||
src={`https://docs.exampaper.vidh.ai/${studentData.s3_path}`}
|
||||
width="60%"
|
||||
height="auto"
|
||||
/>
|
||||
<Box
|
||||
className="w-75 d-none d-md-block"
|
||||
style={{ height: "800px", overflow: "auto" }}
|
||||
>
|
||||
{studentData && (
|
||||
<>
|
||||
<Box className="py-2">
|
||||
<Button
|
||||
className="bg-primary text-light p-3 mx-1"
|
||||
onClick={ZoomInImage}
|
||||
>
|
||||
ZoomIn
|
||||
</Button>
|
||||
<Button
|
||||
className="bg-primary text-light p-3 mx-1"
|
||||
onClick={ZoomOutImage}
|
||||
>
|
||||
ZoomOut
|
||||
</Button>
|
||||
<Button
|
||||
className="bg-primary text-light p-3 mx-1"
|
||||
onClick={RotateImageLeft}
|
||||
>
|
||||
<RotateLeftIcon />
|
||||
</Button>
|
||||
<Button
|
||||
className="bg-primary text-light p-3 mx-1"
|
||||
onClick={RotateImageRight}
|
||||
>
|
||||
<RotateRightIcon />
|
||||
</Button>
|
||||
</Box>
|
||||
<img
|
||||
className="scanned-img"
|
||||
src={`https://docs.exampaper.vidh.ai/${studentData?.s3_path}`}
|
||||
width={`${scaleWidthValue}%`}
|
||||
/>
|
||||
</>
|
||||
)}
|
||||
</Box>
|
||||
<Box className="w-md-75 d-block d-md-none">
|
||||
{dataFetched && studentData && (
|
||||
<img
|
||||
src={`https://docs.exampaper.vidh.ai/${studentData.s3_path}`}
|
||||
width="60%"
|
||||
height="auto"
|
||||
/>
|
||||
<Box className="w-100 d-md-none overflow-auto">
|
||||
{studentData && (
|
||||
<>
|
||||
<Box className="py-2">
|
||||
<Button
|
||||
className="bg-primary text-light p-3 mx-1"
|
||||
onClick={ZoomInImage}
|
||||
>
|
||||
ZoomIn
|
||||
</Button>
|
||||
<Button
|
||||
className="bg-primary text-light p-3 mx-1"
|
||||
onClick={ZoomOutImage}
|
||||
>
|
||||
ZoomOut
|
||||
</Button>
|
||||
<Button
|
||||
className="bg-primary text-light p-3 mx-1"
|
||||
onClick={RotateImageLeft}
|
||||
>
|
||||
<RotateLeftIcon />
|
||||
</Button>
|
||||
<Button
|
||||
className="bg-primary text-light p-3 mx-1"
|
||||
onClick={RotateImageRight}
|
||||
>
|
||||
<RotateRightIcon />
|
||||
</Button>
|
||||
</Box>
|
||||
<img
|
||||
className="scanned-img"
|
||||
src={`https://docs.exampaper.vidh.ai/${studentData.s3_path}`}
|
||||
width={`${scaleWidthValue}%`}
|
||||
/>
|
||||
</>
|
||||
)}
|
||||
</Box>
|
||||
</Box>
|
||||
|
|
|
|||
|
|
@ -11,6 +11,7 @@ const BarcodeInput = ({setBookletInput,setDataFetched,bookletInput}) =>{
|
|||
// }}
|
||||
// noValidate
|
||||
autoComplete="off"
|
||||
className = "w-100"
|
||||
>
|
||||
<TextField id="outlined-basic" label="Barcode" variant="outlined" className='w-100' autoComplete="off" value={bookletInput} onChange={(e)=>{
|
||||
setBookletInput(e.target.value)
|
||||
|
|
|
|||
|
|
@ -1,23 +1,32 @@
|
|||
import * as React from 'react';
|
||||
import Box from '@mui/material/Box';
|
||||
import TextField from '@mui/material/TextField';
|
||||
import * as React from "react";
|
||||
import Box from "@mui/material/Box";
|
||||
import TextField from "@mui/material/TextField";
|
||||
|
||||
const BookletInput = ({setBookletInput,setDataFetched,bookletInput}) =>{
|
||||
return (
|
||||
<Box
|
||||
// component="form"
|
||||
// sx={{
|
||||
// '& > :not(style)': { m: 1, width: '25ch' },
|
||||
// }}
|
||||
// noValidate
|
||||
autoComplete="off"
|
||||
>
|
||||
<TextField id="outlined-basic" label="Booklet Serial No" variant="outlined" className='w-100' autoComplete="off" value={bookletInput} onChange={(e)=>{
|
||||
setBookletInput(e.target.value)
|
||||
setDataFetched(false)
|
||||
}}/>
|
||||
</Box>
|
||||
);
|
||||
}
|
||||
const BookletInput = ({ setBookletInput, setDataFetched, bookletInput }) => {
|
||||
return (
|
||||
<Box
|
||||
// component="form"
|
||||
// sx={{
|
||||
// '& > :not(style)': { m: 1, width: '25ch' },
|
||||
// }}
|
||||
// noValidate
|
||||
className="w-100"
|
||||
autoComplete="off"
|
||||
>
|
||||
<TextField
|
||||
id="outlined-basic"
|
||||
label="Booklet Serial No"
|
||||
variant="outlined"
|
||||
className="w-100"
|
||||
autoComplete="off"
|
||||
value={bookletInput}
|
||||
onChange={(e) => {
|
||||
setBookletInput(e.target.value);
|
||||
setDataFetched(false);
|
||||
}}
|
||||
/>
|
||||
</Box>
|
||||
);
|
||||
};
|
||||
|
||||
export default BookletInput;
|
||||
export default BookletInput;
|
||||
|
|
|
|||
|
|
@ -1,23 +1,40 @@
|
|||
import { Box } from "@mui/material";
|
||||
import HomepageCard from "./HomepageCard";
|
||||
|
||||
import {useState,useEffect} from "react"
|
||||
|
||||
const Home = () => {
|
||||
// const cards = [
|
||||
// {
|
||||
// title: "Reassingned Serial No Anomoly Manual Updation",
|
||||
// url: "/anomoly/reassigned",
|
||||
// },
|
||||
// {
|
||||
// title: "Part A OCR Anomoly Manual Updation",
|
||||
// url: "/anomoly/partA",
|
||||
// }
|
||||
// ];
|
||||
const cards = [
|
||||
{
|
||||
title: "Reassingned Serial No Anomoly Manual Updation",
|
||||
url: "/anomoly/reassigned",
|
||||
}]
|
||||
},
|
||||
// {
|
||||
// title: "Part A OCR Anomoly - Batch 2022",
|
||||
// url: "/anomoly/partA",
|
||||
// },
|
||||
{
|
||||
title: "Part A OCR Anomoly Dummy",
|
||||
url: "/anomoly/partA?type=new",
|
||||
},
|
||||
{
|
||||
title: "Part A OCR Anomoly - Old Dummy",
|
||||
url: "/anomoly/partA?type=old",
|
||||
},
|
||||
// {
|
||||
// title:"Verification",
|
||||
// url:"/verification"
|
||||
// }
|
||||
{
|
||||
title:"Statistics",
|
||||
url:"/statistics"
|
||||
}
|
||||
];
|
||||
|
||||
// const cards = [
|
||||
// {
|
||||
// title: "Reassingned Serial No Anomoly Manual Updation",
|
||||
// url: "/anomoly/reassigned",
|
||||
// }]
|
||||
return (
|
||||
<>
|
||||
<Box>
|
||||
|
|
|
|||
|
|
@ -1,17 +1,32 @@
|
|||
import React from "react";
|
||||
import React, { useEffect } from "react";
|
||||
import { Box } from "@mui/material";
|
||||
import Spinner from "react-bootstrap/Spinner";
|
||||
|
||||
const LoadingContainer = ({ loadingText }) => {
|
||||
const LoadingContainerStyle = {
|
||||
backgroundColor: "rgba(0,0,0,0.5)",
|
||||
overflow: "auto",
|
||||
overflow: "hidden",
|
||||
position: "fixed",
|
||||
top: 0,
|
||||
left: 0,
|
||||
width: "100vw",
|
||||
height: "100vh",
|
||||
zIndex: 1000, // Ensure it appears above other content
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
const body = document.querySelector("body");
|
||||
body.scrollTop = 0;
|
||||
body.style.overflow = "hidden";
|
||||
return () => {
|
||||
body.style.overflow = "auto";
|
||||
};
|
||||
}, []);
|
||||
|
||||
return (
|
||||
<>
|
||||
<Box
|
||||
className="d-flex justify-content-center position-absolute w-100 h-100 align-items-center"
|
||||
className="d-flex justify-content-center align-items-center"
|
||||
style={LoadingContainerStyle}
|
||||
>
|
||||
<Spinner animation="border" variant="light" role="status">
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load Diff
|
|
@ -22,6 +22,16 @@ import HomeIcon from "@mui/icons-material/Home";
|
|||
import ArrowBackIcon from "@mui/icons-material/ArrowBack";
|
||||
import { useNavigate } from "react-router-dom";
|
||||
import QueryStatsIcon from "@mui/icons-material/QueryStats";
|
||||
import { useSearchParams } from "react-router-dom";
|
||||
import { updatePartAanomolyData } from "../redux/actions/actions";
|
||||
import {
|
||||
useSelector,
|
||||
useDispatch,
|
||||
ReactReduxContext,
|
||||
batch,
|
||||
} from "react-redux";
|
||||
import useEnhancedEffect from "@mui/material/utils/useEnhancedEffect";
|
||||
import SystemNumberDialog from "./SystemNumberDialog";
|
||||
|
||||
const { Header, Content, Footer, Sider } = Layout;
|
||||
function getItem(label, key, icon, children) {
|
||||
|
|
@ -32,17 +42,6 @@ function getItem(label, key, icon, children) {
|
|||
label,
|
||||
};
|
||||
}
|
||||
// const items = [
|
||||
// getItem('Option 1', '1', <PieChartOutlined />),
|
||||
// getItem('Option 2', '2', <DesktopOutlined />),
|
||||
// getItem('User', 'sub1', <UserOutlined />, [
|
||||
// getItem('Tom', '3'),
|
||||
// getItem('Bill', '4'),
|
||||
// getItem('Alex', '5'),
|
||||
// ]),
|
||||
// getItem('Team', 'sub2', <TeamOutlined />, [getItem('Team 1', '6'), getItem('Team 2', '8')]),
|
||||
// getItem('Files', '9', <FileOutlined />),
|
||||
// ];
|
||||
|
||||
const items = [getItem("Reassigned Booklet No", "1", <PieChartOutlined />)];
|
||||
|
||||
|
|
@ -52,6 +51,68 @@ const PartAReassigned = () => {
|
|||
const [tableRowData, setTableRowData] = useState([]);
|
||||
const [isLoading, setIsLoading] = useState(false);
|
||||
const [windowWidth, setWindowWidth] = useState(window.innerWidth);
|
||||
let [searchParams, setSearchParams] = useSearchParams();
|
||||
const [showSystemNoContainer, setShowSystemNoContainer] = useState(false);
|
||||
const searchParamsType = searchParams.get("type");
|
||||
const dispatch = useDispatch();
|
||||
const reduxPartA2023AnomolyData = useSelector(
|
||||
(state) => state?.partABatchAnomolyData
|
||||
);
|
||||
const reduxSystemNo = useSelector((state) => state?.systemNumber);
|
||||
console.log("Redux partA 2023 anomoly data : ", reduxPartA2023AnomolyData);
|
||||
|
||||
useEffect(() => {
|
||||
if (!reduxSystemNo) {
|
||||
setShowSystemNoContainer(true);
|
||||
} else {
|
||||
let localstorageRecords;
|
||||
// if (searchParamsType === "old") {
|
||||
// localstorageRecords = localStorage.getItem("part-a-old-anomoly");
|
||||
// if (localstorageRecords) {
|
||||
// localstorageRecords = JSON.parse(localstorageRecords);
|
||||
// }
|
||||
// } else if (searchParamsType !== "old") {
|
||||
// localstorageRecords = localStorage.getItem("part-a-anomoly");
|
||||
// if (localstorageRecords) {
|
||||
// localstorageRecords = JSON.parse(localstorageRecords);
|
||||
// }
|
||||
// }
|
||||
fetchAnomalyData(reduxSystemNo)
|
||||
// if (localstorageRecords && localstorageRecords.length > 0) {
|
||||
// console.log(
|
||||
// "Length of local storage records is high so aborting fetching ..."
|
||||
// );
|
||||
// console.log("The local storage records are ... ", localstorageRecords);
|
||||
// setAnomolyData(localstorageRecords);
|
||||
// dispatch(updatePartAanomolyData(localstorageRecords));
|
||||
// const tmpData = [];
|
||||
// for (const data of localstorageRecords) {
|
||||
// tmpData.push(
|
||||
// createData(
|
||||
// data.s3_path,
|
||||
// data.barcode,
|
||||
// data.register_number,
|
||||
// data.subject_code,
|
||||
// data.type,
|
||||
// reduxSystemNo
|
||||
// )
|
||||
// );
|
||||
// }
|
||||
// // console.log("Tmp data is : ", tmpData);
|
||||
// if (tmpData.length > 0) {
|
||||
// setTableRowData(tmpData);
|
||||
// }
|
||||
// } else {
|
||||
// fetchAnomalyData(reduxSystemNo);
|
||||
// }
|
||||
|
||||
// if(searchParamsType==="old"){
|
||||
// const sytemData = localStorage.get("part-a-anomoly")
|
||||
// }else if(searchParamsType !== "old"){
|
||||
// const sytemData = localStorage.get("part-a-old-anomoly")
|
||||
// }
|
||||
}
|
||||
}, [reduxSystemNo]);
|
||||
|
||||
useEffect(() => {
|
||||
const handleResize = () => {
|
||||
|
|
@ -75,17 +136,58 @@ const PartAReassigned = () => {
|
|||
}, [windowWidth]);
|
||||
|
||||
const navigate = useNavigate();
|
||||
function createData(barcode,register_number,subject_code,type) {
|
||||
function createData(
|
||||
s3_path,
|
||||
barcode,
|
||||
register_number,
|
||||
subject_code,
|
||||
type,
|
||||
systemNo
|
||||
) {
|
||||
return {
|
||||
barcode,register_number,subject_code,type
|
||||
s3_path,
|
||||
barcode,
|
||||
register_number,
|
||||
subject_code,
|
||||
type,
|
||||
systemNo,
|
||||
};
|
||||
}
|
||||
|
||||
const fetchAnomalyData = () => {
|
||||
const updateSystemReservationStatus = async (systemRecords) => {
|
||||
const payload = {
|
||||
systemRecords,
|
||||
sysNo:reduxSystemNo
|
||||
};
|
||||
try {
|
||||
fetch(
|
||||
`${
|
||||
import.meta.env.VITE_REACT_APP_BACKEND_URL
|
||||
}/updateSystemReservationStatus`,
|
||||
{
|
||||
method: "POST",
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
},
|
||||
body: JSON.stringify(payload),
|
||||
}
|
||||
)
|
||||
.then((response) => response.json())
|
||||
.then((responseData) => {
|
||||
console.log("response from updation : ", responseData);
|
||||
});
|
||||
} catch (error) {
|
||||
throw new Error("Error in update system records : ", systemRecords);
|
||||
}
|
||||
};
|
||||
|
||||
const fetchAnomalyData = (reduxSystemNo) => {
|
||||
console.log("Fetching.......");
|
||||
setIsLoading(true);
|
||||
fetch(
|
||||
`${import.meta.env.VITE_REACT_APP_BACKEND_URL}/fetchAnamolyPartAData`,
|
||||
`${
|
||||
import.meta.env.VITE_REACT_APP_BACKEND_URL
|
||||
}/fetchAnamolyPartAData?type=${searchParamsType}&sysNo=${reduxSystemNo}`,
|
||||
{
|
||||
method: "GET",
|
||||
headers: {
|
||||
|
|
@ -101,12 +203,43 @@ const PartAReassigned = () => {
|
|||
console.log("Response Data is : ", responseData);
|
||||
setIsLoading(false);
|
||||
if (responseData.status === "success") {
|
||||
setAnomolyData(responseData.data);
|
||||
const tmpData = [];
|
||||
for (const data of responseData.data) {
|
||||
tmpData.push(createData(data.barcode,data.register_number,data.subject_code,data.type));
|
||||
console.log("System record ====== ",responseData.systemRecord)
|
||||
var systemRecords = responseData?.data
|
||||
if(!responseData.systemRecord){
|
||||
systemRecords = getRecordsBySystemId(
|
||||
responseData?.data,
|
||||
reduxSystemNo
|
||||
);
|
||||
}
|
||||
console.log("Tmp data is : ", tmpData);
|
||||
updateSystemReservationStatus(systemRecords);
|
||||
console.log("System records : ", systemRecords);
|
||||
if (searchParamsType === "old") {
|
||||
localStorage.setItem(
|
||||
"part-a-old-anomoly",
|
||||
JSON.stringify(systemRecords)
|
||||
);
|
||||
} else if (searchParamsType !== "old") {
|
||||
localStorage.setItem(
|
||||
"part-a-anomoly",
|
||||
JSON.stringify(systemRecords)
|
||||
);
|
||||
}
|
||||
setAnomolyData(systemRecords);
|
||||
dispatch(updatePartAanomolyData(systemRecords));
|
||||
const tmpData = [];
|
||||
for (const data of systemRecords) {
|
||||
tmpData.push(
|
||||
createData(
|
||||
data.s3_path,
|
||||
data.barcode,
|
||||
data.register_number,
|
||||
data.subject_code,
|
||||
data.type,
|
||||
reduxSystemNo
|
||||
)
|
||||
);
|
||||
}
|
||||
// console.log("Tmp data is : ", tmpData);
|
||||
if (tmpData.length > 0) {
|
||||
setTableRowData(tmpData);
|
||||
}
|
||||
|
|
@ -118,9 +251,29 @@ const PartAReassigned = () => {
|
|||
});
|
||||
};
|
||||
|
||||
// useEffect(() => {
|
||||
// fetchAnomalyData();
|
||||
// }, []);
|
||||
|
||||
function getRecordsBySystemId(records, systemId) {
|
||||
const new_data = [];
|
||||
for (var i = 0; i < records.length; i++) {
|
||||
var count = i % 5;
|
||||
if (count === systemId - 1) {
|
||||
new_data.push(records[i]);
|
||||
}
|
||||
}
|
||||
return new_data;
|
||||
}
|
||||
|
||||
const handleSystemNoChange = () => {
|
||||
console.log("System No Change is called");
|
||||
setShowSystemNoContainer(true);
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
fetchAnomalyData();
|
||||
}, []);
|
||||
console.log("System no container show status : ", showSystemNoContainer);
|
||||
}, [showSystemNoContainer]);
|
||||
|
||||
const {
|
||||
token: { colorBgContainer, borderRadiusLG },
|
||||
|
|
@ -171,14 +324,25 @@ const PartAReassigned = () => {
|
|||
>
|
||||
<QueryStatsIcon />
|
||||
</Button> */}
|
||||
<Button
|
||||
className="bg-primary p-1 text-light"
|
||||
onClick={() => {
|
||||
navigate("/");
|
||||
}}
|
||||
>
|
||||
<HomeIcon />
|
||||
</Button>
|
||||
<Box className="d-flex justify-content-between gap-md-4 gap-1 align-items-center">
|
||||
{reduxSystemNo && (
|
||||
<Box
|
||||
className="h6 p-0 m-0 text-light bg-primary rounded h-100 d-flex align-items-center px-3"
|
||||
style={{ cursor: "pointer" }}
|
||||
onClick={handleSystemNoChange}
|
||||
>
|
||||
<b>System No : </b> {reduxSystemNo}
|
||||
</Box>
|
||||
)}
|
||||
<Button
|
||||
className="bg-primary p-1 text-light rounded h-100"
|
||||
onClick={() => {
|
||||
navigate("/");
|
||||
}}
|
||||
>
|
||||
<HomeIcon />
|
||||
</Button>
|
||||
</Box>
|
||||
</Box>
|
||||
</Box>
|
||||
</Header>
|
||||
|
|
@ -191,10 +355,16 @@ const PartAReassigned = () => {
|
|||
<Box className="w-100 d-flex justify-content-center">
|
||||
{tableRowData.length > 0 && (
|
||||
<TableComponent
|
||||
batchType={searchParamsType}
|
||||
rows={tableRowData}
|
||||
type={"PartAReassigned"}
|
||||
/>
|
||||
)}
|
||||
{tableRowData.length == 0 && (
|
||||
<Box className="w-100 d-flex justify-content-center py-2 align-items-center text-center">
|
||||
<h6>No Data Found !!</h6>
|
||||
</Box>
|
||||
)}
|
||||
</Box>
|
||||
</Box>
|
||||
</Content>
|
||||
|
|
@ -207,6 +377,12 @@ const PartAReassigned = () => {
|
|||
</Footer>
|
||||
</Layout>
|
||||
{isLoading && <LoadingContainer loadingText={"Loading"} />}
|
||||
{showSystemNoContainer && (
|
||||
<SystemNumberDialog
|
||||
setShowSystemNoContainer={setShowSystemNoContainer}
|
||||
showSystemNoContainer={showSystemNoContainer}
|
||||
/>
|
||||
)}
|
||||
</Layout>
|
||||
);
|
||||
};
|
||||
|
|
|
|||
|
|
@ -0,0 +1,86 @@
|
|||
import React, { useState,useEffect } from "react";
|
||||
import Dialog from "@mui/material/Dialog";
|
||||
import DialogContent from "@mui/material/DialogContent";
|
||||
import DialogContentText from "@mui/material/DialogContentText";
|
||||
import DialogTitle from "@mui/material/DialogTitle";
|
||||
import { Button,Box } from "@mui/material";
|
||||
import TextField from "@mui/material/TextField";
|
||||
import { NavLink,Link } from "react-router-dom";
|
||||
|
||||
|
||||
const SimpleDialog = ({dialogBoxConsent,setDialogBoxConsent,showDialogBox,setShowDialogBox,dialogText,batchType}) => {
|
||||
const [open, setOpen] = useState(true); // Set open state to true by default
|
||||
const [examCentreCode,setExamCentreCode] = useState(null)
|
||||
const [examDate,setExamDate] = useState(null)
|
||||
const [metaDataLink,setMetaDataLink] = useState(null)
|
||||
const MetabaseLink = "http://metabase.usln.in/public/question/d8774923-09bb-4cd9-903b-559d417e12cf"
|
||||
console.log("MetabaseLink : ",MetabaseLink)
|
||||
console.log(import.meta.env)
|
||||
const handleClose = () => {
|
||||
setOpen(false);
|
||||
};
|
||||
|
||||
const handleYes = () =>{
|
||||
console.log("Consent is : ", dialogBoxConsent);
|
||||
console.log("Dialog text before if condition :: ",dialogText)
|
||||
console.log("showDialog Box : ",showDialogBox)
|
||||
console.log("Setting Conset Yes")
|
||||
setDialogBoxConsent("Yes")
|
||||
setShowDialogBox(false)
|
||||
}
|
||||
const handleNo = () =>{
|
||||
console.log("Consent is : ", dialogBoxConsent);
|
||||
console.log("Dialog text before if condition :: ",dialogText)
|
||||
console.log("showDialog Box : ",showDialogBox)
|
||||
console.log("Setting consent NO")
|
||||
setDialogBoxConsent("No")
|
||||
setShowDialogBox(false)
|
||||
}
|
||||
|
||||
useEffect(()=>{
|
||||
if(examCentreCode && examDate){
|
||||
setMetaDataLink(`http://metabase.usln.in/public/question/d8774923-09bb-4cd9-903b-559d417e12cf?internal_exam_centre_code=${examCentreCode}&ref_exam_date=${examDate}`)
|
||||
}
|
||||
},[examDate,examCentreCode])
|
||||
|
||||
return (
|
||||
<Dialog open={open} onClose={handleClose}>
|
||||
<DialogTitle>Error :</DialogTitle>
|
||||
<DialogContent>
|
||||
<DialogContentText>
|
||||
<h6>Missing Data - {dialogText}</h6>
|
||||
Data Entered Is Not found in the DB.Do you want to Continue editing ??
|
||||
{batchType == "new" && <Box className="d-flex gap-4 my-4">
|
||||
|
||||
{/* <Link to={MetabaseLink} target="_blank">{MetabaseLink}</Link> */}
|
||||
{/* <TextField
|
||||
value={examCentreCode}
|
||||
onChange={(e)=>{
|
||||
setExamCentreCode(e.target.value)
|
||||
}}
|
||||
label={"Exam Centre Code"}
|
||||
autoComplete="off"
|
||||
/>
|
||||
<TextField
|
||||
value={examDate}
|
||||
onChange={(e)=>{
|
||||
setExamDate(e.target.value)
|
||||
}}
|
||||
label={"Exam Date"}
|
||||
autoComplete="off"
|
||||
/> */}
|
||||
</Box>}
|
||||
{/* {
|
||||
metaDataLink && <iframe width="1000px" height="800px" src={metaDataLink}/>
|
||||
} */}
|
||||
<Box className="d-flex justify-content-end gap-2 my-3">
|
||||
<Button className="bg-primary p-2 text-light" onClick={handleYes}>YES</Button>
|
||||
<Button className="bg-primary p-2 text-light" onClick={handleNo}>NO</Button>
|
||||
</Box>
|
||||
</DialogContentText>
|
||||
</DialogContent>
|
||||
</Dialog>
|
||||
);
|
||||
}
|
||||
|
||||
export default SimpleDialog;
|
||||
|
|
@ -0,0 +1,410 @@
|
|||
import React, { useState, useRef } from "react";
|
||||
import {
|
||||
DesktopOutlined,
|
||||
FileOutlined,
|
||||
PieChartOutlined,
|
||||
TeamOutlined,
|
||||
UserOutlined,
|
||||
} from "@ant-design/icons";
|
||||
import {
|
||||
Breadcrumb,
|
||||
Layout,
|
||||
Menu,
|
||||
Typography,
|
||||
theme,
|
||||
Select,
|
||||
DatePicker,
|
||||
} from "antd";
|
||||
import { Box, Button } from "@mui/material";
|
||||
import { useEffect } from "react";
|
||||
import TextField from "@mui/material/TextField";
|
||||
import EditButton from "./EditButton";
|
||||
import { width } from "@mui/system";
|
||||
import { ToastContainer, toast } from "react-toastify";
|
||||
import "react-toastify/dist/ReactToastify.css";
|
||||
import { useSearchParams } from "react-router-dom";
|
||||
import LoadingContainer from "./LoadingContainer";
|
||||
import HomeIcon from "@mui/icons-material/Home";
|
||||
import ArrowBackIcon from "@mui/icons-material/ArrowBack";
|
||||
import { useNavigate } from "react-router-dom";
|
||||
import QueryStatsIcon from "@mui/icons-material/QueryStats";
|
||||
import RotateLeftIcon from "@mui/icons-material/RotateLeft";
|
||||
import RotateRightIcon from "@mui/icons-material/RotateRight";
|
||||
import { useSelector, useDispatch } from "react-redux";
|
||||
import {
|
||||
updatePartAanomolyData,
|
||||
updateSystemNo,
|
||||
} from "../redux/actions/actions";
|
||||
import SimpleDialog from "./SimpleDialog";
|
||||
import SystemNumberDialog from "./SystemNumberDialog";
|
||||
import ValidationContainer from "./ValidationContainer";
|
||||
import { Height } from "@mui/icons-material";
|
||||
import StatsCard from "./StatsCard";
|
||||
import ArrowUpwardIcon from "@mui/icons-material/ArrowUpward";
|
||||
import ArrowDownwardIcon from "@mui/icons-material/ArrowDownward";
|
||||
|
||||
const { Header, Content, Footer, Sider } = Layout;
|
||||
function getItem(label, key, icon, children) {
|
||||
return {
|
||||
key,
|
||||
icon,
|
||||
children,
|
||||
label,
|
||||
};
|
||||
}
|
||||
|
||||
const Statistics = () => {
|
||||
const navigate = useNavigate();
|
||||
const [part, setPart] = useState(null);
|
||||
const [collapsed, setCollapsed] = useState(false);
|
||||
const [isLoading, setIsLoading] = useState(false);
|
||||
const [examCentreCode, setExamCentreCode] = useState(null);
|
||||
const [isManualVerificationNeeded, setIsManualVerificationNeeded] =
|
||||
useState(false);
|
||||
const [recordsData, setRecordsData] = useState([]);
|
||||
const [isCoverPage, setIsCoverPage] = useState(false);
|
||||
const [isBackPage, setIsBackPage] = useState(false);
|
||||
const [totalPages, setTotalPages] = useState(0);
|
||||
const [startDate,setStartDate] = useState(null);
|
||||
const [endDate,setEndDate] = useState(null);
|
||||
const [pageNumber, setPageNumber] = useState(1);
|
||||
const [currentPageRecords, setCurrentPageRecords] = useState(0);
|
||||
const [distinctExamCentreCodes, setDistinctExamCentreCodes] = useState([]);
|
||||
const items = [getItem("Reassigned Booklet No", "1", <PieChartOutlined />)];
|
||||
const {
|
||||
token: { colorBgContainer, borderRadiusLG },
|
||||
} = theme.useToken();
|
||||
const recordsPerPage = 5;
|
||||
|
||||
const fetchDistinctInternalExamCentreCode = () => {
|
||||
try {
|
||||
fetch(
|
||||
`${
|
||||
import.meta.env.VITE_REACT_APP_BACKEND_URL
|
||||
}/fetchDistinctExamCentreCodes`,
|
||||
{
|
||||
method: "GET",
|
||||
}
|
||||
)
|
||||
.then((response) => response.json())
|
||||
.then((responseData) => {
|
||||
console.log("ResponseData :: ", responseData);
|
||||
if (responseData?.status === "success") {
|
||||
setDistinctExamCentreCodes(responseData?.results);
|
||||
}
|
||||
});
|
||||
} catch (error) {
|
||||
throw new Error(error);
|
||||
}
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
fetchDistinctInternalExamCentreCode();
|
||||
}, []);
|
||||
|
||||
useEffect(() => {
|
||||
console.log("Distinct exam centre codes : ", distinctExamCentreCodes);
|
||||
}, [distinctExamCentreCodes]);
|
||||
|
||||
const handleBackpageChange = (e) => {
|
||||
if (e === "yes") {
|
||||
setIsBackPage(1);
|
||||
} else {
|
||||
setIsBackPage(0);
|
||||
}
|
||||
};
|
||||
|
||||
const handleManualVerificatonChange = (e) => {
|
||||
if (e === "yes") {
|
||||
setIsManualVerificationNeeded(1);
|
||||
} else {
|
||||
setIsManualVerificationNeeded(0);
|
||||
}
|
||||
};
|
||||
|
||||
const handleCoverChange = (e) => {
|
||||
console.log("Cover change : ", e);
|
||||
if (e === "yes") {
|
||||
setIsCoverPage(1);
|
||||
} else {
|
||||
setIsCoverPage(0);
|
||||
}
|
||||
};
|
||||
|
||||
const submitStatistics = async () => {
|
||||
setIsLoading(true);
|
||||
const payload = {
|
||||
examCentreCode,
|
||||
isBackPage,
|
||||
isCoverPage,
|
||||
isManualVerificationNeeded,
|
||||
part,
|
||||
startDate,
|
||||
endDate
|
||||
};
|
||||
try {
|
||||
const responseData = await fetch(
|
||||
`${import.meta.env.VITE_REACT_APP_BACKEND_URL}/fetchStatsData`,
|
||||
{
|
||||
method: "POST",
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
},
|
||||
body: JSON.stringify(payload),
|
||||
}
|
||||
);
|
||||
setIsLoading(false);
|
||||
const response = await responseData.json();
|
||||
console.log("Response data in fetchStatsdata : ", response);
|
||||
if (response?.status === "success") {
|
||||
setRecordsData(response?.results);
|
||||
if (response.results !== 0) {
|
||||
setTotalPages(Math.ceil(response?.results.length / recordsPerPage));
|
||||
const startIndex = (pageNumber - 1) * recordsPerPage;
|
||||
const endIndex = startIndex + recordsPerPage;
|
||||
const newRecords = response.results.splice(startIndex, endIndex);
|
||||
setCurrentPageRecords(newRecords);
|
||||
}
|
||||
}
|
||||
} catch (err) {
|
||||
throw new Error(err);
|
||||
}
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
console.log("Record Data in useeffeect : ", recordsData);
|
||||
}, [recordsData]);
|
||||
|
||||
useEffect(() => {
|
||||
console.log("Page number : ", pageNumber);
|
||||
const startIndex = (pageNumber - 1) * recordsPerPage;
|
||||
console.log("Start Index :: ", startIndex);
|
||||
const endIndex = startIndex + recordsPerPage;
|
||||
console.log("End index : ", endIndex);
|
||||
const newPageRecords = recordsData.slice(startIndex, endIndex);
|
||||
console.log("recordsData : ", recordsData);
|
||||
console.log("New records : ", newPageRecords);
|
||||
setCurrentPageRecords(newPageRecords);
|
||||
const body = document.querySelector("body");
|
||||
window.scrollTo(0, 0);
|
||||
}, [pageNumber]);
|
||||
|
||||
return (
|
||||
<div>
|
||||
<Layout
|
||||
style={{
|
||||
minHeight: "100vh",
|
||||
}}
|
||||
>
|
||||
<ToastContainer />
|
||||
<Sider
|
||||
collapsible
|
||||
collapsed={collapsed}
|
||||
onCollapse={(value) => setCollapsed(value)}
|
||||
>
|
||||
<div className="demo-logo-vertical" />
|
||||
<Menu
|
||||
theme="dark"
|
||||
defaultSelectedKeys={["1"]}
|
||||
mode="inline"
|
||||
items={items}
|
||||
/>
|
||||
</Sider>
|
||||
<Layout>
|
||||
<Header
|
||||
style={{
|
||||
padding: 0,
|
||||
background: colorBgContainer,
|
||||
}}
|
||||
>
|
||||
<div className="d-flex justify-content-between h-100 py-1 px-2">
|
||||
<Button
|
||||
className="bg-primary p-1 text-light"
|
||||
onClick={() => {
|
||||
navigate(-1);
|
||||
}}
|
||||
>
|
||||
<ArrowBackIcon />
|
||||
</Button>
|
||||
<div className="d-flex justify-content-between gap-2">
|
||||
<div className="d-flex justify-content-between gap-md-4 gap-1 align-items-center">
|
||||
<Button
|
||||
className="bg-primary p-1 text-light rounded h-100"
|
||||
onClick={() => {
|
||||
navigate("/");
|
||||
}}
|
||||
>
|
||||
<HomeIcon />
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</Header>
|
||||
<Content
|
||||
style={{
|
||||
margin: "16px 16px",
|
||||
}}
|
||||
>
|
||||
{/* Add the dropdowns and select buttons here */}
|
||||
<div className="d-flex flex-wrap gap-4 align-items-center">
|
||||
<div
|
||||
className="dropdown-item mx-2"
|
||||
style={{ width: "fit-content" }}
|
||||
>
|
||||
<label>Exam Centre Code:</label>
|
||||
<Select
|
||||
placeholder="Select Exam Centre Code"
|
||||
style={{ width: 200 }}
|
||||
onChange={(e) => {
|
||||
console.log("Exam centre code : ", e);
|
||||
setExamCentreCode(e);
|
||||
}}
|
||||
>
|
||||
{distinctExamCentreCodes.length > 0 &&
|
||||
distinctExamCentreCodes.map((code) => (
|
||||
<Option value={code?.internal_exam_centre_code}>
|
||||
{code?.internal_exam_centre_code}
|
||||
</Option>
|
||||
))}
|
||||
</Select>
|
||||
</div>
|
||||
<div
|
||||
className="dropdown-item mx-2"
|
||||
style={{ width: "fit-content" }}
|
||||
>
|
||||
<label>Manual Verification Needed:</label>
|
||||
<Select
|
||||
placeholder="Select Verification Status"
|
||||
style={{ width: 200 }}
|
||||
onChange={handleManualVerificatonChange}
|
||||
>
|
||||
<Option value="yes">Yes</Option>
|
||||
<Option value="no">No</Option>
|
||||
</Select>
|
||||
</div>
|
||||
<div
|
||||
className="dropdown-item mx-2"
|
||||
style={{ width: "fit-content" }}
|
||||
>
|
||||
<label>Is Cover:</label>
|
||||
<Select
|
||||
placeholder="Select Cover Status"
|
||||
style={{ width: 200 }}
|
||||
onChange={handleCoverChange}
|
||||
>
|
||||
<Option value="yes">Yes</Option>
|
||||
<Option value="no">No</Option>
|
||||
</Select>
|
||||
</div>
|
||||
<div
|
||||
className="dropdown-item mx-2"
|
||||
style={{ width: "fit-content" }}
|
||||
>
|
||||
<label>Is Backpage:</label>
|
||||
<Select
|
||||
placeholder="Select Backpage Status"
|
||||
style={{ width: 200 }}
|
||||
onChange={handleBackpageChange}
|
||||
>
|
||||
<Option value="yes">Yes</Option>
|
||||
<Option value="no">No</Option>
|
||||
</Select>
|
||||
</div>
|
||||
<div
|
||||
className="dropdown-item mx-2"
|
||||
style={{ width: "fit-content" }}
|
||||
>
|
||||
<label>Part:</label>
|
||||
<Select
|
||||
placeholder="Select Part"
|
||||
style={{ width: 200 }}
|
||||
onChange={(e) => {
|
||||
setPart(e);
|
||||
}}
|
||||
>
|
||||
<Option value="partA">Part-A</Option>
|
||||
<Option value="partC">Part-C</Option>
|
||||
</Select>
|
||||
</div>
|
||||
<div
|
||||
className="dropdown-item mx-2"
|
||||
style={{ width: "fit-content" }}
|
||||
>
|
||||
<label>Date Range:</label>
|
||||
<DatePicker.RangePicker onChange={(e)=>{
|
||||
console.log("E ==== ",e)
|
||||
if(e.length == 2){
|
||||
setStartDate(`${e[0].$y}-${e[0].$M}-${e[0].$D}`)
|
||||
setEndDate(`${e[1].$y}-${e[1].$M}-${e[1].$D}`)
|
||||
}
|
||||
}}/>
|
||||
</div>
|
||||
<div className="dropdown-item" style={{ width: "fit-content" }}>
|
||||
<Button
|
||||
class="btn bg-primary text-light px-5 rounded"
|
||||
onClick={submitStatistics}
|
||||
>
|
||||
Submit
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
{currentPageRecords.length > 0 &&
|
||||
currentPageRecords.map((data, index) => (
|
||||
<StatsCard
|
||||
data={data}
|
||||
records={currentPageRecords}
|
||||
part={part}
|
||||
/>
|
||||
))}
|
||||
</div>
|
||||
{recordsData.length > 0 && (
|
||||
<div>
|
||||
<Button
|
||||
class="btn btn-primary p-2 mx-2"
|
||||
onClick={() => {
|
||||
if (pageNumber > 1) {
|
||||
setPageNumber((prev) => prev - 1);
|
||||
}
|
||||
}}
|
||||
>
|
||||
Previous
|
||||
</Button>
|
||||
{pageNumber}/{totalPages}
|
||||
<Button
|
||||
class="btn btn-primary p-2 mx-2"
|
||||
onClick={() => {
|
||||
if (pageNumber >= 0) {
|
||||
setPageNumber((prev) => prev + 1);
|
||||
}
|
||||
}}
|
||||
>
|
||||
Next
|
||||
</Button>
|
||||
</div>
|
||||
)}
|
||||
<Box style={{ bottom: "10px", right: "10px", position: "fixed" }}>
|
||||
<Button className="bg-primary text-light rounded" onClick={()=>{
|
||||
console.log("Going down ..")
|
||||
const body = document.body
|
||||
window.scrollTo(0,body.scrollHeight)
|
||||
}}>
|
||||
<ArrowDownwardIcon />
|
||||
</Button>
|
||||
</Box>
|
||||
</Content>
|
||||
<Footer
|
||||
style={{
|
||||
textAlign: "center",
|
||||
}}
|
||||
>
|
||||
exampaper.vidh.ai ©{new Date().getFullYear()}
|
||||
</Footer>
|
||||
</Layout>
|
||||
{isLoading && <LoadingContainer loadingText={"Loading"} />}
|
||||
</Layout>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default Statistics;
|
||||
|
|
@ -0,0 +1,80 @@
|
|||
import { Box } from "@mui/material";
|
||||
|
||||
const StatsCard = ({ records, data, part }) => {
|
||||
console.log("Records : ", records);
|
||||
// console.log("data ================ : ", data);
|
||||
const keys = Object.keys(data);
|
||||
// console.log("Part : ", part);
|
||||
// // const Values = Object.Values(data)
|
||||
// console.log("values ====== ", Object.values(data));
|
||||
const values = Object.values(data);
|
||||
// console.log("keys : ", keys);
|
||||
const PartCKeysToCapture = [
|
||||
"barcode",
|
||||
"exam_centre_code",
|
||||
"booklet_serial_no",
|
||||
"subject_code",
|
||||
"marks",
|
||||
"manual_verification_needed",
|
||||
"error",
|
||||
"error_reason",
|
||||
"error"
|
||||
];
|
||||
const PartAKeysToCapture = [
|
||||
"barcode",
|
||||
"exam_centre_code",
|
||||
"booklet_serial_no",
|
||||
"subject_code",
|
||||
"manual_verification_needed",
|
||||
"error",
|
||||
"error_reason",
|
||||
"error",
|
||||
"type",
|
||||
];
|
||||
return (
|
||||
<>
|
||||
<Box class="d-flex flex-md-row flex-column justify-content-center align-items-center gap-2 my-5 border border-dark rounded">
|
||||
<Box class="text-left d-flex flex-column justify-content-center mx-3">
|
||||
{part === "partC" && (
|
||||
<>
|
||||
<Box class="my-3">
|
||||
<h6>
|
||||
<u>
|
||||
<b>Record Data:</b>
|
||||
</u>
|
||||
</h6>
|
||||
</Box>
|
||||
|
||||
{PartCKeysToCapture.map((key, index) => (
|
||||
<h6 key={index}>
|
||||
<b>{key}</b>: {data[key]}
|
||||
</h6>
|
||||
))}
|
||||
</>
|
||||
)}
|
||||
|
||||
{part === "partA" && (
|
||||
<>
|
||||
{PartAKeysToCapture.map((key, index) => (
|
||||
<h6>
|
||||
<b>{key}</b> : {data[key]}
|
||||
{/* <h3>{key}</h3>
|
||||
<h3>{index}</h3> */}
|
||||
</h6>
|
||||
))}
|
||||
</>
|
||||
)}
|
||||
</Box>
|
||||
<Box style={{width:"fit-content"}}>
|
||||
<img
|
||||
src={`https://docs.exampaper.vidh.ai/${data?.s3_path}`}
|
||||
width="90%"
|
||||
height="auto"
|
||||
/>
|
||||
</Box>
|
||||
</Box>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
export default StatsCard;
|
||||
|
|
@ -0,0 +1,80 @@
|
|||
import React, { useState, useEffect } from "react";
|
||||
import Dialog from "@mui/material/Dialog";
|
||||
import DialogContent from "@mui/material/DialogContent";
|
||||
import DialogContentText from "@mui/material/DialogContentText";
|
||||
import DialogTitle from "@mui/material/DialogTitle";
|
||||
import { Button, Box } from "@mui/material";
|
||||
import TextField from "@mui/material/TextField";
|
||||
import { NavLink, Link, useNavigate } from "react-router-dom";
|
||||
import InputLabel from "@mui/material/InputLabel";
|
||||
import MenuItem from "@mui/material/MenuItem";
|
||||
import FormControl from "@mui/material/FormControl";
|
||||
import Select from "@mui/material/Select";
|
||||
import { useDispatch,useSelector } from "react-redux";
|
||||
import { updateSystemNo } from "../redux/actions/actions";
|
||||
|
||||
|
||||
const SystemNumberDialog = (setShowSystemNoContainer,showSystemNoContainer) => {
|
||||
const dispatch = useDispatch();
|
||||
const navigate = useNavigate()
|
||||
const [open, setOpen] = useState(true); // Set open state to true by default
|
||||
const reduxSystemNo = useSelector((state)=>state?.systemNumber)
|
||||
console.log("Redux system No : ",reduxSystemNo)
|
||||
const [systemNo, setSystemNo] = useState(1);
|
||||
const handleClose = () => {
|
||||
setOpen(false);
|
||||
};
|
||||
|
||||
const handleSubmit = () => {
|
||||
console.log("Handling submit")
|
||||
dispatch(updateSystemNo(systemNo));
|
||||
navigate("/")
|
||||
handleClose(true)
|
||||
};
|
||||
|
||||
useEffect(()=>{
|
||||
console.log("System No in useEffect : ",systemNo)
|
||||
},[systemNo])
|
||||
|
||||
const numberOfSystems = 5;
|
||||
const selectValues = [];
|
||||
for (var i = 1; i <= numberOfSystems; i++) {
|
||||
selectValues.push({ value: Number(i), systemLabel: `System ${i}` });
|
||||
}
|
||||
|
||||
return (
|
||||
<Dialog open={open} onClose={handleClose}>
|
||||
<DialogTitle>Choose Your System Number:</DialogTitle>
|
||||
<DialogContent>
|
||||
<DialogContentText>
|
||||
<Select
|
||||
labelId="system-no-select-label"
|
||||
id="system-no-select"
|
||||
className="w-100"
|
||||
label="System No"
|
||||
value={systemNo}
|
||||
onChange={(e) => {
|
||||
setSystemNo(e.target.value);
|
||||
}}
|
||||
>
|
||||
{selectValues.length > 0 &&
|
||||
selectValues.map((value) => (
|
||||
<MenuItem value={value.value}>{value.systemLabel}</MenuItem>
|
||||
))}
|
||||
</Select>
|
||||
|
||||
<Box className="d-flex justify-content-end gap-2 my-3">
|
||||
<Button
|
||||
className="bg-primary p-2 text-light"
|
||||
onClick={handleSubmit}
|
||||
>
|
||||
Submit
|
||||
</Button>
|
||||
</Box>
|
||||
</DialogContentText>
|
||||
</DialogContent>
|
||||
</Dialog>
|
||||
);
|
||||
};
|
||||
|
||||
export default SystemNumberDialog;
|
||||
|
|
@ -4,10 +4,25 @@ import {
|
|||
TablePagination,
|
||||
tablePaginationClasses as classes,
|
||||
} from "@mui/base/TablePagination";
|
||||
import { Link } from "react-router-dom";
|
||||
import TextField from "@mui/material/TextField";
|
||||
import { Box } from "@mui/material";
|
||||
import InputLabel from "@mui/material/InputLabel";
|
||||
import MenuItem from "@mui/material/MenuItem";
|
||||
import FormControl from "@mui/material/FormControl";
|
||||
import Select from "@mui/material/Select";
|
||||
|
||||
export default function TableComponent({ rows, type }) {
|
||||
export default function TableComponent({
|
||||
filterSelectedExamCentreCode,
|
||||
setFilterSelectedExamCentreCode,
|
||||
rows,
|
||||
type,
|
||||
distinctExamCentreCodes,
|
||||
batchType
|
||||
}) {
|
||||
// console.log("Exam centre code in table component : ",distinctExamCentreCodes)
|
||||
console.log("Rows in table component : ", rows);
|
||||
console.log("Type is : ", type);
|
||||
// console.log("Type is : ", type);
|
||||
const [page, setPage] = React.useState(0);
|
||||
const [rowsPerPage, setRowsPerPage] = React.useState(5);
|
||||
|
||||
|
|
@ -24,11 +39,33 @@ export default function TableComponent({ rows, type }) {
|
|||
setPage(0);
|
||||
};
|
||||
|
||||
const handleFilterExamCentreCode = (e) => {
|
||||
const ExamCentreCode = e.target.value;
|
||||
setFilterSelectedExamCentreCode(ExamCentreCode);
|
||||
};
|
||||
|
||||
return (
|
||||
<Root className="overflow-auto" sx={{ maxWidth: "100%", width: 1200 }}>
|
||||
{type === "AnomolyReassigned" && (
|
||||
<>
|
||||
<h5 className="py-2">Manual Verification Needed Students :</h5>
|
||||
{/* <Box className="py-2">
|
||||
<FormControl fullWidth>
|
||||
<InputLabel id="demo-simple-select-label">Exam Centre Code</InputLabel>
|
||||
<Select
|
||||
labelId="demo-simple-select-label"
|
||||
id="demo-simple-select"
|
||||
label="Exam Centre Code"
|
||||
onChange={handleFilterExamCentreCode}
|
||||
>
|
||||
{distinctExamCentreCodes.length > 0 && (
|
||||
distinctExamCentreCodes.map((exam_centre_code)=>(
|
||||
<MenuItem key={exam_centre_code} value={exam_centre_code}>{exam_centre_code}</MenuItem>
|
||||
))
|
||||
)}
|
||||
</Select>
|
||||
</FormControl>
|
||||
</Box> */}
|
||||
<table aria-label="custom pagination table">
|
||||
<thead>
|
||||
<tr>
|
||||
|
|
@ -52,11 +89,11 @@ export default function TableComponent({ rows, type }) {
|
|||
<tr key={row.attendence_serial_no}>
|
||||
<td>{row.attendence_serial_no}</td>
|
||||
<td style={{ width: 160 }} align="right">
|
||||
<a
|
||||
href={`/anomoly/reassigned/booklet?sno=${row.student_slno}`}
|
||||
<Link
|
||||
to={`/anomoly/reassigned/booklet?sno=${row.student_slno}`}
|
||||
>
|
||||
{row.student_slno}
|
||||
</a>
|
||||
</Link>
|
||||
</td>
|
||||
<td style={{ width: 160 }} align="right">
|
||||
{row.exam_centre_code}
|
||||
|
|
@ -248,6 +285,7 @@ export default function TableComponent({ rows, type }) {
|
|||
<table aria-label="custom pagination table">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>s3_path</th>
|
||||
<th>Barcode</th>
|
||||
<th>Subject Code</th>
|
||||
<th>Register Number</th>
|
||||
|
|
@ -263,8 +301,13 @@ export default function TableComponent({ rows, type }) {
|
|||
: rows
|
||||
).map((row) => (
|
||||
<tr key={row.exam_centre_code}>
|
||||
<td style={{ width: 160 }} align="right">
|
||||
<Link to={`/anomoly/partA/booklet?batchType=${batchType}&barcode=${row.barcode}&s3Path=${row.s3_path}&sysNo=${row.systemNo}`}>
|
||||
{row?.s3_path}
|
||||
</Link>
|
||||
</td>
|
||||
<td style={{ width: 160 }} align="right">
|
||||
<a href={`/anomoly/partA/booklet?barcode=${row.barcode}`}>{row.barcode}</a>
|
||||
{row.barcode}
|
||||
</td>
|
||||
<td style={{ width: 160 }} align="right">
|
||||
{row.subject_code}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,95 @@
|
|||
import React, { useState, useEffect } from "react";
|
||||
import Dialog from "@mui/material/Dialog";
|
||||
import DialogContent from "@mui/material/DialogContent";
|
||||
import DialogContentText from "@mui/material/DialogContentText";
|
||||
import DialogTitle from "@mui/material/DialogTitle";
|
||||
import { Button, Box } from "@mui/material";
|
||||
import TextField from "@mui/material/TextField";
|
||||
import { NavLink, Link } from "react-router-dom";
|
||||
|
||||
const ValidationContainer = ({
|
||||
showValidationContainer,
|
||||
setShowValidationContainer,
|
||||
validateContainerData,
|
||||
s3Path,
|
||||
updatePartAanomoly
|
||||
}) => {
|
||||
const [open, setOpen] = useState(true); // Set open state to true by default
|
||||
console.log("Validate Container Data : ", validateContainerData);
|
||||
// const [examCentreCode,setExamCentreCode] = useState(null)
|
||||
// const [examDate,setExamDate] = useState(null)
|
||||
// const [metaDataLink,setMetaDataLink] = useState(null)
|
||||
// const MetabaseLink = "http://metabase.usln.in/public/question/d8774923-09bb-4cd9-903b-559d417e12cf"
|
||||
// console.log("MetabaseLink : ",MetabaseLink)
|
||||
// console.log(import.meta.env)
|
||||
const handleClose = () => {
|
||||
setOpen(false);
|
||||
};
|
||||
|
||||
return (
|
||||
<Dialog open={open} onClose={handleClose}>
|
||||
<DialogTitle>
|
||||
<u>Students Data's :</u>
|
||||
</DialogTitle>
|
||||
<DialogContent>
|
||||
<DialogContentText>
|
||||
{validateContainerData.length > 0 ? (
|
||||
<>
|
||||
<Box className="d-flex">
|
||||
<Box className="p-3">
|
||||
<h6>
|
||||
<strong>Student Name : </strong>
|
||||
{validateContainerData[0]?.candidate_name}
|
||||
</h6>
|
||||
<h6>
|
||||
<strong>Register Number : </strong>
|
||||
{validateContainerData[0]?.register_number}
|
||||
</h6>
|
||||
<h6>
|
||||
<strong>Subject Code : </strong>
|
||||
{validateContainerData[0]?.subject_code}
|
||||
</h6>
|
||||
<h6>
|
||||
<strong>Exam Centre Code : </strong>
|
||||
{validateContainerData[0]?.exam_centre_code}
|
||||
</h6>
|
||||
<h6>
|
||||
<strong>Exam Date : </strong>
|
||||
{validateContainerData[0]?.exam_date}
|
||||
</h6>
|
||||
</Box>
|
||||
{/* <Box>
|
||||
<img src = {`https://docs.exampaper.vidh.ai/${s3Path}`}/>
|
||||
</Box> */}
|
||||
</Box>
|
||||
</>
|
||||
) : (
|
||||
<Box className="p-3">
|
||||
<h6>No student Record Found !!</h6>
|
||||
</Box>
|
||||
)}
|
||||
<Box className="d-flex justify-content-between gap-2 my-3">
|
||||
<Button
|
||||
className="bg-primary p-2 text-light"
|
||||
disabled={validateContainerData.length === 0}
|
||||
onClick={()=>{
|
||||
setShowValidationContainer(false)
|
||||
updatePartAanomoly()
|
||||
}}
|
||||
>
|
||||
Submit
|
||||
</Button>
|
||||
<Button
|
||||
className="bg-primary p-2 text-light"
|
||||
onClick={() => setShowValidationContainer(false)}
|
||||
>
|
||||
Close
|
||||
</Button>
|
||||
</Box>
|
||||
</DialogContentText>
|
||||
</DialogContent>
|
||||
</Dialog>
|
||||
);
|
||||
};
|
||||
|
||||
export default ValidationContainer;
|
||||
|
|
@ -0,0 +1,335 @@
|
|||
import React, { useState } from "react";
|
||||
import {
|
||||
DesktopOutlined,
|
||||
FileOutlined,
|
||||
PieChartOutlined,
|
||||
TeamOutlined,
|
||||
UserOutlined,
|
||||
} from "@ant-design/icons";
|
||||
import { Breadcrumb, Layout, Menu, Typography, theme } from "antd";
|
||||
import BookletInput from "./BookletInput";
|
||||
import { Box, Button } from "@mui/material";
|
||||
import { useEffect } from "react";
|
||||
import TextField from "@mui/material/TextField";
|
||||
import EditButton from "./EditButton";
|
||||
import { width } from "@mui/system";
|
||||
import { ToastContainer, toast } from "react-toastify";
|
||||
import "react-toastify/dist/ReactToastify.css";
|
||||
import { TablePagination } from "@mui/base/TablePagination";
|
||||
import TableComponent from "./TableComponent";
|
||||
import LoadingContainer from "./LoadingContainer";
|
||||
import HomeIcon from "@mui/icons-material/Home";
|
||||
import ArrowBackIcon from "@mui/icons-material/ArrowBack";
|
||||
import { useNavigate } from "react-router-dom";
|
||||
import QueryStatsIcon from "@mui/icons-material/QueryStats";
|
||||
import { useSearchParams } from "react-router-dom";
|
||||
import { updatePartAanomolyData } from "../redux/actions/actions";
|
||||
import { useSelector, useDispatch, ReactReduxContext } from "react-redux";
|
||||
import useEnhancedEffect from "@mui/material/utils/useEnhancedEffect";
|
||||
import SystemNumberDialog from "./SystemNumberDialog";
|
||||
|
||||
const { Header, Content, Footer, Sider } = Layout;
|
||||
function getItem(label, key, icon, children) {
|
||||
return {
|
||||
key,
|
||||
icon,
|
||||
children,
|
||||
label,
|
||||
};
|
||||
}
|
||||
|
||||
const items = [getItem("Reassigned Booklet No", "1", <PieChartOutlined />)];
|
||||
|
||||
const Verification = () => {
|
||||
const [collapsed, setCollapsed] = useState(false);
|
||||
const [anomolyData, setAnomolyData] = useState([]);
|
||||
const [tableRowData, setTableRowData] = useState([]);
|
||||
const [isLoading, setIsLoading] = useState(false);
|
||||
const [windowWidth, setWindowWidth] = useState(window.innerWidth);
|
||||
let [searchParams, setSearchParams] = useSearchParams();
|
||||
const [showSystemNoContainer, setShowSystemNoContainer] = useState(false);
|
||||
const searchParamsType = searchParams.get("type");
|
||||
const dispatch = useDispatch();
|
||||
const reduxPartA2023AnomolyData = useSelector(
|
||||
(state) => state?.partABatchAnomolyData
|
||||
);
|
||||
const reduxSystemNo = useSelector((state) => state?.systemNumber);
|
||||
console.log("Redux partA 2023 anomoly data : ", reduxPartA2023AnomolyData);
|
||||
|
||||
useEffect(() => {
|
||||
if (!reduxSystemNo) {
|
||||
setShowSystemNoContainer(true);
|
||||
} else {
|
||||
fetchAnomalyData(reduxSystemNo);
|
||||
// if(searchParamsType==="old"){
|
||||
// const sytemData = localStorage.get("part-a-anomoly")
|
||||
// }else if(searchParamsType !== "old"){
|
||||
// const sytemData = localStorage.get("part-a-old-anomoly")
|
||||
// }
|
||||
}
|
||||
}, [reduxSystemNo]);
|
||||
|
||||
useEffect(() => {
|
||||
const handleResize = () => {
|
||||
setWindowWidth(window.innerWidth);
|
||||
};
|
||||
|
||||
window.addEventListener("resize", handleResize);
|
||||
|
||||
return () => {
|
||||
window.removeEventListener("resize", handleResize);
|
||||
};
|
||||
}, []);
|
||||
|
||||
useEffect(() => {
|
||||
if (windowWidth < 800) {
|
||||
setCollapsed(true);
|
||||
}
|
||||
if (windowWidth > 800) {
|
||||
setCollapsed(false);
|
||||
}
|
||||
}, [windowWidth]);
|
||||
|
||||
const navigate = useNavigate();
|
||||
function createData(
|
||||
s3_path,
|
||||
barcode,
|
||||
register_number,
|
||||
subject_code,
|
||||
type,
|
||||
systemNo
|
||||
) {
|
||||
return {
|
||||
s3_path,
|
||||
barcode,
|
||||
register_number,
|
||||
subject_code,
|
||||
type,
|
||||
systemNo,
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
const updateSystemReservationStatus = async (systemRecords) => {
|
||||
const payload={
|
||||
systemRecords,
|
||||
}
|
||||
try {
|
||||
fetch(`${import.meta.env.VITE_REACT_APP_BACKEND_URL}/updateSystemReservationStatus`,{
|
||||
method:"POST",
|
||||
headers:{
|
||||
"Content-Type":"application/json"
|
||||
},
|
||||
body:JSON.stringify(payload)
|
||||
}).then(response=>response.json()).then(responseData=>{
|
||||
console.log("response from updation : ",responseData)
|
||||
})
|
||||
} catch (error) {
|
||||
throw new Error("Error in update system records : ",systemRecords)
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
||||
const fetchAnomalyData = (reduxSystemNo) => {
|
||||
console.log("Fetching.......");
|
||||
setIsLoading(true);
|
||||
fetch(
|
||||
`${
|
||||
import.meta.env.VITE_REACT_APP_BACKEND_URL
|
||||
}/fetchAnamolyPartAData?type=${searchParamsType}`,
|
||||
{
|
||||
method: "GET",
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
},
|
||||
}
|
||||
)
|
||||
.then((response) => {
|
||||
console.log("Response fetched..");
|
||||
return response.json();
|
||||
})
|
||||
.then((responseData) => {
|
||||
console.log("Response Data is : ", responseData);
|
||||
setIsLoading(false);
|
||||
if (responseData.status === "success") {
|
||||
const systemRecords = getRecordsBySystemId(
|
||||
responseData?.data,
|
||||
reduxSystemNo
|
||||
);
|
||||
updateSystemReservationStatus(systemRecords)
|
||||
console.log("System records : ", systemRecords);
|
||||
if (searchParamsType === "old") {
|
||||
localStorage.setItem(
|
||||
"part-a-old-anomoly",
|
||||
JSON.stringify(systemRecords)
|
||||
);
|
||||
} else if (searchParamsType !== "old") {
|
||||
localStorage.setItem(
|
||||
"part-a-anomoly",
|
||||
JSON.stringify(systemRecords)
|
||||
);
|
||||
}
|
||||
setAnomolyData(systemRecords);
|
||||
dispatch(updatePartAanomolyData(systemRecords));
|
||||
const tmpData = [];
|
||||
for (const data of systemRecords) {
|
||||
tmpData.push(
|
||||
createData(
|
||||
data.s3_path,
|
||||
data.barcode,
|
||||
data.register_number,
|
||||
data.subject_code,
|
||||
data.type,
|
||||
reduxSystemNo
|
||||
)
|
||||
);
|
||||
}
|
||||
// console.log("Tmp data is : ", tmpData);
|
||||
if (tmpData.length > 0) {
|
||||
setTableRowData(tmpData);
|
||||
}
|
||||
}
|
||||
})
|
||||
.catch((error) => {
|
||||
console.error("Error fetching data: ", error);
|
||||
setIsLoading(false);
|
||||
});
|
||||
};
|
||||
|
||||
// useEffect(() => {
|
||||
// fetchAnomalyData();
|
||||
// }, []);
|
||||
|
||||
function getRecordsBySystemId(records, systemId) {
|
||||
const new_data = [];
|
||||
for (var i = 0; i < records.length; i++) {
|
||||
var count = i % 5;
|
||||
if (count === systemId - 1) {
|
||||
new_data.push(records[i]);
|
||||
}
|
||||
}
|
||||
return new_data;
|
||||
}
|
||||
|
||||
const handleSystemNoChange = () => {
|
||||
console.log("System No Change is called");
|
||||
setShowSystemNoContainer(true);
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
console.log("System no container show status : ", showSystemNoContainer);
|
||||
}, [showSystemNoContainer]);
|
||||
|
||||
const {
|
||||
token: { colorBgContainer, borderRadiusLG },
|
||||
} = theme.useToken();
|
||||
|
||||
return (
|
||||
<Layout
|
||||
style={{
|
||||
minHeight: "100vh",
|
||||
}}
|
||||
>
|
||||
<ToastContainer />
|
||||
<Sider
|
||||
collapsible
|
||||
collapsed={collapsed}
|
||||
onCollapse={(value) => setCollapsed(value)}
|
||||
>
|
||||
<div className="demo-logo-vertical" />
|
||||
<Menu
|
||||
theme="dark"
|
||||
defaultSelectedKeys={["1"]}
|
||||
mode="inline"
|
||||
items={items}
|
||||
/>
|
||||
</Sider>
|
||||
<Layout>
|
||||
<Header
|
||||
style={{
|
||||
padding: 0,
|
||||
background: colorBgContainer,
|
||||
}}
|
||||
>
|
||||
<Box className="d-flex justify-content-between h-100 py-1 px-2">
|
||||
<Button
|
||||
className="bg-primary p-1 text-light"
|
||||
onClick={() => {
|
||||
navigate(-1);
|
||||
}}
|
||||
>
|
||||
<ArrowBackIcon />
|
||||
</Button>
|
||||
<Box className="d-flex justify-content-between gap-2">
|
||||
{/* <Button
|
||||
className="bg-primary p-1 text-light"
|
||||
onClick={() => {
|
||||
navigate("/anomoly/reassigned/stats");
|
||||
}}
|
||||
>
|
||||
<QueryStatsIcon />
|
||||
</Button> */}
|
||||
<Box className="d-flex justify-content-between gap-md-4 gap-1 align-items-center">
|
||||
{reduxSystemNo && (
|
||||
<Box
|
||||
className="h6 p-0 m-0 text-light bg-primary rounded h-100 d-flex align-items-center px-3"
|
||||
style={{ cursor: "pointer" }}
|
||||
onClick={handleSystemNoChange}
|
||||
>
|
||||
<b>System No : </b> {reduxSystemNo}
|
||||
</Box>
|
||||
)}
|
||||
<Button
|
||||
className="bg-primary p-1 text-light rounded h-100"
|
||||
onClick={() => {
|
||||
navigate("/");
|
||||
}}
|
||||
>
|
||||
<HomeIcon />
|
||||
</Button>
|
||||
</Box>
|
||||
</Box>
|
||||
</Box>
|
||||
</Header>
|
||||
<Content
|
||||
style={{
|
||||
margin: "16px 16px",
|
||||
}}
|
||||
>
|
||||
<Box className="w-100 d-flex justify-content-between">
|
||||
<Box className="w-100 d-flex justify-content-center">
|
||||
{tableRowData.length > 0 && (
|
||||
<TableComponent
|
||||
batchType={searchParamsType}
|
||||
rows={tableRowData}
|
||||
type={"PartAReassigned"}
|
||||
/>
|
||||
)}
|
||||
{tableRowData.length == 0 && (
|
||||
<Box className="w-100 d-flex justify-content-center py-2 align-items-center text-center">
|
||||
<h6>No Data Found !!</h6>
|
||||
</Box>
|
||||
)}
|
||||
</Box>
|
||||
</Box>
|
||||
</Content>
|
||||
<Footer
|
||||
style={{
|
||||
textAlign: "center",
|
||||
}}
|
||||
>
|
||||
exampaper.vidh.ai ©{new Date().getFullYear()}
|
||||
</Footer>
|
||||
</Layout>
|
||||
{isLoading && <LoadingContainer loadingText={"Loading"} />}
|
||||
{showSystemNoContainer && (
|
||||
<SystemNumberDialog
|
||||
setShowSystemNoContainer={setShowSystemNoContainer}
|
||||
showSystemNoContainer={showSystemNoContainer}
|
||||
/>
|
||||
)}
|
||||
</Layout>
|
||||
);
|
||||
};
|
||||
export default Verification;
|
||||
23
src/main.jsx
23
src/main.jsx
|
|
@ -1,12 +1,15 @@
|
|||
import React from 'react'
|
||||
import ReactDOM from 'react-dom/client'
|
||||
import App from './App.jsx'
|
||||
import './index.css'
|
||||
import 'bootstrap/dist/css/bootstrap.min.css';
|
||||
import React from "react";
|
||||
import ReactDOM from "react-dom/client";
|
||||
import App from "./App.jsx";
|
||||
import "./index.css";
|
||||
import "bootstrap/dist/css/bootstrap.min.css";
|
||||
import { Provider } from "react-redux";
|
||||
import store from "./redux/store/store";
|
||||
|
||||
|
||||
ReactDOM.createRoot(document.getElementById('root')).render(
|
||||
ReactDOM.createRoot(document.getElementById("root")).render(
|
||||
<React.StrictMode>
|
||||
<App />
|
||||
</React.StrictMode>,
|
||||
)
|
||||
<Provider store={store}>
|
||||
<App />
|
||||
</Provider>
|
||||
</React.StrictMode>
|
||||
);
|
||||
|
|
|
|||
|
|
@ -0,0 +1,14 @@
|
|||
export const updateAttendenceAnomolyData = (data) =>({
|
||||
type:"UPDATE_ATTENDENCE_ANOMOLY_DATA",
|
||||
payload:data,
|
||||
})
|
||||
|
||||
export const updatePartAanomolyData = (data) =>({
|
||||
type:"UPDATE_PART-A_ANOMOLY_DATA",
|
||||
payload:data
|
||||
})
|
||||
|
||||
export const updateSystemNo = (data) => ({
|
||||
type:"UPDATE_SYSTEM_NO",
|
||||
payload:data
|
||||
})
|
||||
|
|
@ -0,0 +1,22 @@
|
|||
|
||||
const initialState = {
|
||||
attendenceAnomolyData : [],
|
||||
partABatchAnomolyData : [],
|
||||
systemNumber : null
|
||||
};
|
||||
|
||||
const reducer = (state = initialState, action) => {
|
||||
switch (action.type) {
|
||||
case 'UPDATE_ATTENDENCE_ANOMOLY_DATA':
|
||||
return { ...state, attendenceAnomolyData:action?.payload};
|
||||
case 'UPDATE_PART-A_ANOMOLY_DATA':
|
||||
return { ...state, partABatchAnomolyData:action?.payload};
|
||||
case 'UPDATE_SYSTEM_NO':
|
||||
return { ...state,systemNumber:action?.payload}
|
||||
default:
|
||||
return state;
|
||||
}
|
||||
};
|
||||
|
||||
export default reducer;
|
||||
|
||||
|
|
@ -0,0 +1,7 @@
|
|||
// store.js
|
||||
import { createStore } from 'redux';
|
||||
import reducer from '../reducers/Reducer'; // Import your reducer
|
||||
|
||||
const store = createStore(reducer); // Create store with single reducer
|
||||
|
||||
export default store;
|
||||
Loading…
Reference in New Issue