From abc0fae2896ce738d7c9567111a33c4cca83e3f4 Mon Sep 17 00:00:00 2001 From: vishnu vinay Date: Thu, 21 Nov 2024 13:11:18 +0530 Subject: [PATCH 1/2] v0.1.3 changes --- src/components/DocumentSelector.jsx | 56 ++-- src/components/Fetch.jsx | 79 +++-- src/components/MainContent.jsx | 2 +- src/components/PrivateRoute.jsx | 12 +- src/components/ShareConfirmationDialog.jsx | 12 +- src/components/SlideMenu.jsx | 4 +- src/components/Upload.jsx | 327 +++++++++++---------- src/config.js | 61 +++- 8 files changed, 338 insertions(+), 215 deletions(-) diff --git a/src/components/DocumentSelector.jsx b/src/components/DocumentSelector.jsx index 86edb96..34860b1 100644 --- a/src/components/DocumentSelector.jsx +++ b/src/components/DocumentSelector.jsx @@ -27,26 +27,27 @@ const StyledSearchBox = styled(Paper)(({ theme }) => ({ })); const DocumentSelector = () => { - const [selectedDocs, setSelectedDocs] = useState([]); + const [selectedDocs, setSelectedDocs] = useState(new Set()); // Use Set for selected documents const [documents, setDocuments] = useState([]); + const [searchQuery, setSearchQuery] = useState(''); + const [error, setError] = useState(null); // Error state for displaying API errors + // Handle document selection const handleToggle = (id) => { - const currentIndex = selectedDocs.indexOf(id); - const newChecked = [...selectedDocs]; - - if (currentIndex === -1) { - newChecked.push(id); // Add the ID to selectedDocs if not already selected + const newSelectedDocs = new Set(selectedDocs); // Create a new Set to maintain immutability + if (newSelectedDocs.has(id)) { + newSelectedDocs.delete(id); } else { - newChecked.splice(currentIndex, 1); // Remove the ID if already selected + newSelectedDocs.add(id); } - - setSelectedDocs(newChecked); + setSelectedDocs(newSelectedDocs); }; + // Handle the import button click const handleImportClick = () => { - const selectedDocuments = documents.filter(doc => selectedDocs.includes(doc.doc_id)); + const selectedDocuments = documents.filter(doc => selectedDocs.has(doc.doc_id)); const parentAppOrigin = import.meta.env.VITE_PARENT_APP_ORIGIN; - + console.log('Selected Documents:', selectedDocuments); window.parent.postMessage( { type: 'selected-docs', data: selectedDocuments }, @@ -54,6 +55,7 @@ const DocumentSelector = () => { ); }; + // Fetch documents from API useEffect(() => { const fetchDocuments = async () => { const apiUrl = `${import.meta.env.VITE_APP_API_URL}/user-docs/fetch`; @@ -64,7 +66,7 @@ const DocumentSelector = () => { method: "GET", headers: { "Content-Type": "application/json", - "Authorization": `Bearer ${authToken}` + "Authorization": `Bearer ${authToken}`, }, }); @@ -76,12 +78,23 @@ const DocumentSelector = () => { setDocuments(data); } catch (err) { console.error("Error fetching documents:", err.message); + setError('Error fetching documents. Please try again later.'); } }; fetchDocuments(); }, []); + // Handle search input change + const handleSearchChange = (event) => { + setSearchQuery(event.target.value); + }; + + // Filter documents based on search query + const filteredDocuments = documents.filter(doc => + doc.doc_name.toLowerCase().includes(searchQuery.toLowerCase()) + ); + return ( { fullWidth placeholder="Search By Document Name" variant="standard" + value={searchQuery} + onChange={handleSearchChange} // Attach search change handler InputProps={{ disableUnderline: true, endAdornment: ( @@ -111,13 +126,20 @@ const DocumentSelector = () => { /> + {/* Error Handling */} + {error && ( + + {error} + + )} + Please choose your required document. {/* Document List */} - {documents.map((doc) => ( + {filteredDocuments.map((doc) => ( { }} > handleToggle(doc.doc_id)} /> @@ -153,10 +175,10 @@ const DocumentSelector = () => { textTransform: "none", borderRadius: 2, }} - disabled={selectedDocs.length === 0} + disabled={selectedDocs.size === 0} // Disable button if no documents are selected onClick={handleImportClick} > - + Import Documents ({selectedDocs.length}) + + Import Documents ({selectedDocs.size}) {/* Bottom Navigation */} diff --git a/src/components/Fetch.jsx b/src/components/Fetch.jsx index a3496c5..04545ad 100644 --- a/src/components/Fetch.jsx +++ b/src/components/Fetch.jsx @@ -21,11 +21,39 @@ import { useNavigate } from "react-router-dom"; import Header from "./Header"; import BottomNavigationBar from "./BottomNavigationBar"; -const Fetch = ({ documentType, onDocumentTypeChange }) => { +const Fetch = () => { const [open, setOpen] = useState(false); const navigate = useNavigate(); - const [selectedDocument, setSelectedDocument] = useState(documentType || ""); + const [selectedDocument, setSelectedDocument] = useState(null); const [docId, setDocId] = useState(""); + const [errors, setErrors] = useState({ documentType: "", docId: "" }); + + // Handle document selection + const handleDocumentChange = (e) => { + const selected = e.target.value; + const selectedDoc = documentTypes.find((doc) => doc.value === selected); + setSelectedDocument(selectedDoc); + }; + + const handleFetch = () => { + let formErrors = { documentType: "", docId: "" }; + + // Validate document type and document ID + if (!selectedDocument) { + formErrors.documentType = "Document type is required."; + } + + if (!docId) { + formErrors.docId = "Document ID is required."; + } + + setErrors(formErrors); + + // Proceed only if no errors + if (!formErrors.documentType && !formErrors.docId) { + setOpen(true); // Open the confirmation dialog + } + }; return ( @@ -54,13 +82,13 @@ const Fetch = ({ documentType, onDocumentTypeChange }) => { Select Document Type - + Select Document Type + {errors.documentType && ( + {errors.documentType} + )} {/* Document ID Input */} @@ -86,39 +117,45 @@ const Fetch = ({ documentType, onDocumentTypeChange }) => { placeholder="Paste Here" value={docId} onChange={(e) => setDocId(e.target.value)} + error={Boolean(errors.docId)} helperText={ - - - - Hint Text: Where this ID can be found - - + errors.docId && ( + + + + Hint Text: Where this ID can be found + + + ) } /> + {/* Fetch Button */} - {/* Confirmation Dialog */} + {/* ShareConfirmationDialog with necessary props */} setOpen(false)} - documentType={selectedDocument} - docId={docId} + documentType={selectedDocument?.doc_type} // Passing the document type + documentSubType={selectedDocument?.doc_subtype} // Passing the document subtype + documentName={selectedDocument?.value} // Passing the document name + docId={docId} // Passing the document ID /> diff --git a/src/components/MainContent.jsx b/src/components/MainContent.jsx index 872df7a..79914f4 100644 --- a/src/components/MainContent.jsx +++ b/src/components/MainContent.jsx @@ -82,7 +82,7 @@ const MainContent = () => { { - // const isLoggedIn = localStorage.getItem("authToken"); const navigate = useNavigate(); const { keycloak } = useKeycloak(); const location = useLocation(); const isLoggedIn = keycloak.authenticated; - if (!isLoggedIn) { - localStorage.setItem("login-redirect", location.pathname); - navigate("/"); - } + useEffect(() => { + if (!isLoggedIn) { + localStorage.setItem("login-redirect", location.pathname); // Store the current location to redirect after login + navigate("/"); // Redirect to the login page + } + }, [isLoggedIn, location.pathname, navigate]); // The effect depends on isLoggedIn, location.pathname, and navigate return children; // Render the children if authenticated }; diff --git a/src/components/ShareConfirmationDialog.jsx b/src/components/ShareConfirmationDialog.jsx index 464d3b6..01c36ae 100644 --- a/src/components/ShareConfirmationDialog.jsx +++ b/src/components/ShareConfirmationDialog.jsx @@ -16,7 +16,7 @@ import CheckCircleOutlineIcon from '@mui/icons-material/CheckCircleOutline'; import axios from 'axios'; import { useNavigate } from 'react-router-dom'; -const ShareConfirmationDialog = ({ open, onClose, documentType, docId, file }) => { +const ShareConfirmationDialog = ({ open, onClose, documentType,documentSubType,documentName, docId, file }) => { const navigate = useNavigate(); const [checked, setChecked] = useState(false); const [showSuccess, setShowSuccess] = useState(false); @@ -28,11 +28,13 @@ const ShareConfirmationDialog = ({ open, onClose, documentType, docId, file }) = try { let response; const authToken = localStorage.getItem('authToken'); + console.log(documentType,documentSubType,documentName) if (file) { const formData = new FormData(); - // formData.append('sso_id', ssoId); formData.append('doc_type', documentType); + formData.append('doc_subtype', documentSubType); + formData.append('doc_name',documentName); formData.append('file', file); // API request for upload @@ -44,6 +46,8 @@ const ShareConfirmationDialog = ({ open, onClose, documentType, docId, file }) = const data = new URLSearchParams(); // data.append('sso_id', ssoId); data.append('doc_type', documentType); + data.append('doc_subtype', documentSubType); + data.append('doc_name',documentName); data.append('doc_id', docId); // API request for fetch @@ -105,7 +109,7 @@ const ShareConfirmationDialog = ({ open, onClose, documentType, docId, file }) = } - label={documentType} + label={documentName} /> @@ -144,7 +148,7 @@ const ShareConfirmationDialog = ({ open, onClose, documentType, docId, file }) = }}> Your - {documentType} + {documentName} has been added to your documents set in the E-Wallet! diff --git a/src/components/SlideMenu.jsx b/src/components/SlideMenu.jsx index d5c0f3e..0f34746 100644 --- a/src/components/SlideMenu.jsx +++ b/src/components/SlideMenu.jsx @@ -17,11 +17,11 @@ const SlideMenu = () => { const handleLogout = () => { - keycloak.logout(); + keycloak.logout({ redirectUri: window.location.origin }); localStorage.clear(); localStorage.setItem('logout',true); // Logout from Keycloak - console.log('Logging out...'); + console.log('Logging out...',window.location.origin); }; return ( diff --git a/src/components/Upload.jsx b/src/components/Upload.jsx index c29b17a..74087c5 100644 --- a/src/components/Upload.jsx +++ b/src/components/Upload.jsx @@ -1,171 +1,178 @@ import React, { useState } from "react"; import { - Container, - Box, - IconButton, - Typography, - Select, - MenuItem, - Button, - Input, - FormHelperText, - FormControl, - InputLabel, - } from "@mui/material"; - import ArrowBackIcon from "@mui/icons-material/ArrowBack"; - import UploadFileIcon from "@mui/icons-material/UploadFile"; - import ShareConfirmationDialog from "./ShareConfirmationDialog"; - import { documentTypes } from "../config"; - import Header from "./Header"; - import BottomNavigationBar from "./BottomNavigationBar"; - import { useNavigate } from "react-router-dom"; - - const Upload = () => { - const [openDialog, setOpenDialog] = useState(false); - const [file, setFile] = useState(null); // Store the selected file - const [selectedDocument, setSelectedDocument] = useState(""); // Store the selected document type - const [errors, setErrors] = useState({ file: "", documentType: "" }); // For error handling - const navigate = useNavigate(); - - const handleFileChange = (e) => { - const selectedFile = e.target.files[0]; - if (selectedFile) { - if (selectedFile.type === "application/json") { - setFile(selectedFile); // Store the file if it's valid JSON - setErrors((prevErrors) => ({ ...prevErrors, file: "" })); - } else { - setFile(null); - setErrors((prevErrors) => ({ - ...prevErrors, - file: "Please upload a valid JSON file.", - })); - } + Container, + Box, + IconButton, + Typography, + Select, + MenuItem, + Button, + Input, + FormHelperText, + FormControl, + InputLabel, +} from "@mui/material"; +import ArrowBackIcon from "@mui/icons-material/ArrowBack"; +import UploadFileIcon from "@mui/icons-material/UploadFile"; +import ShareConfirmationDialog from "./ShareConfirmationDialog"; +import { documentTypes } from "../config"; +import Header from "./Header"; +import BottomNavigationBar from "./BottomNavigationBar"; +import { useNavigate } from "react-router-dom"; + +const Upload = () => { + const [openDialog, setOpenDialog] = useState(false); + const [file, setFile] = useState(null); // Store the selected file + const [selectedDocument, setSelectedDocument] = useState(null); // Store the selected document type + const [errors, setErrors] = useState({ file: "", documentType: "" }); // For error handling + const navigate = useNavigate(); + + const handleFileChange = (e) => { + const selectedFile = e.target.files[0]; + if (selectedFile) { + if (selectedFile.type === "application/json") { + setFile(selectedFile); // Store the file if it's valid JSON + setErrors((prevErrors) => ({ ...prevErrors, file: "" })); + } else { + setFile(null); + setErrors((prevErrors) => ({ + ...prevErrors, + file: "Please upload a valid JSON file.", + })); } - }; - - const handleUpload = () => { - // Validate document type and file - let formErrors = { file: "", documentType: "" }; - - if (!selectedDocument) { - formErrors.documentType = "Document type is required."; - } - - if (!file) { - formErrors.file = "File is required."; - } - - setErrors(formErrors); - - // If validation passes, show the confirmation dialog - if (!formErrors.documentType && !formErrors.file) { - setOpenDialog(true); - } - }; - - return ( - -
- - - navigate("/home")}> - - - - Upload New Document - - - - {/* Document Type Select */} - - - Select Document Type - - - - Select Document Type - - {errors.documentType && {errors.documentType}} - - - - {/* File Upload Section */} - - - Select a File to Upload (JSON Only) - - - {/* Hidden file input */} - - - - {/* ShareConfirmationDialog */} - setOpenDialog(false)} - documentType={selectedDocument} - file={file} - /> - - - - - ); - }; - - export default Upload; - \ No newline at end of file + + {file && ( + + Selected file: {file.name} + + )} + + {errors.file && ( + + {errors.file} + + )} + + + + Ensure that the file is in JSON format. + + + + + {/* ShareConfirmationDialog */} + setOpenDialog(false)} + documentType={selectedDocument?.doc_type} + documentSubType={selectedDocument?.doc_subtype} + documentName={selectedDocument?.value} + file={file} + /> + + + + + ); +}; + +export default Upload; diff --git a/src/config.js b/src/config.js index 1ac30c5..24126ea 100644 --- a/src/config.js +++ b/src/config.js @@ -1,9 +1,60 @@ export const documentTypes = [ - { value: "PAN Card", label: "PAN Card" }, - { value: "Aadhaar Card", label: "Aadhaar Card" }, - { value: "Marksheet", label: "Marksheet" }, - // Add other document types here -]; + { + value: "Aadhaar Card", + label: "Aadhaar Card", + doc_type: "idProof", + doc_subtype: "aadhaar" + }, + { + value: "Jan Aadhaar for (Domicile information)", + label: "Jan Aadhaar for (Domicile information)", + doc_type: "domicileProof", + doc_subtype: "domicileCertificate" + }, + { + value: "Caste Certificate", + label: "Caste Certificate", + doc_type: "casteProof", + doc_subtype: "casteCertificate" + }, + { + value: "Income Certificate", + label: "Income Certificate", + doc_type: "incomeProof", + doc_subtype: "incomeCertificate" + }, + { + value: "Enrolment Certificate (with hosteller/day scholar information)", + label: "Enrolment Certificate (with hosteller/day scholar information)", + doc_type: "associationProof", + doc_subtype: "enrolmentCertificate" + }, + { + value: "Marksheet", + label: "Marksheet", + doc_type: "marksProof", + doc_subtype: "marksheet" + }, + { + value: "Disability Certificate", + label: "Disability Certificate", + doc_type: "disabilityProof", + doc_subtype: "disabilityCertificate" + }, + { + value: "Sports Competition participation certificate", + label: "Sports Competition participation certificate", + doc_type: "participationProof", + doc_subtype: "participationCertificate" + }, + { + value: "Birth Certificate", + label: "Birth Certificate", + doc_type: "birthProof", + doc_subtype: "birthCertificate" + }, + ]; + export const languageOptions = [ { value: 'English', label: 'English' }, // { value: 'Hindi', label: 'Hindi' }, From b302dda9fdfcaf5d22d3be5393f466842e6d179b Mon Sep 17 00:00:00 2001 From: vishnu vinay Date: Fri, 22 Nov 2024 15:23:38 +0530 Subject: [PATCH 2/2] doc_name changes in drop down --- src/components/DocumentSelector.jsx | 35 ++++++----------------------- 1 file changed, 7 insertions(+), 28 deletions(-) diff --git a/src/components/DocumentSelector.jsx b/src/components/DocumentSelector.jsx index df11163..d75b3ed 100644 --- a/src/components/DocumentSelector.jsx +++ b/src/components/DocumentSelector.jsx @@ -32,12 +32,12 @@ const DocumentSelector = () => { } else { newChecked.splice(currentIndex, 1); } - setSelectedDocs(newSelectedDocs); + + setSelectedDocs(newChecked); }; - // Handle the import button click const handleImportClick = () => { - const selectedDocuments = documents.filter(doc => selectedDocs.has(doc.doc_id)); + const selectedDocuments = documents.filter(doc => selectedDocs.includes(doc.doc_id)); const parentAppOrigin = import.meta.env.VITE_PARENT_APP_ORIGIN; console.log('Selected Documents:', selectedDocuments); @@ -47,7 +47,6 @@ const DocumentSelector = () => { ); }; - // Fetch documents from API useEffect(() => { const fetchDocuments = async () => { const apiUrl = `${import.meta.env.VITE_APP_API_URL}/user-docs/fetch`; @@ -74,7 +73,6 @@ const DocumentSelector = () => { setDocuments(data); } catch (err) { console.error("Error fetching documents:", err.message); - setError('Error fetching documents. Please try again later.'); } }; @@ -112,16 +110,6 @@ const DocumentSelector = () => { } }, [authToken, isTokenReceived, isEmbedded, navigate]); - // Handle search input change - const handleSearchChange = (event) => { - setSearchQuery(event.target.value); - }; - - // Filter documents based on search query - const filteredDocuments = documents.filter(doc => - doc.doc_name.toLowerCase().includes(searchQuery.toLowerCase()) - ); - return ( { fullWidth placeholder="Search By Document Name" variant="standard" - value={searchQuery} - onChange={handleSearchChange} // Attach search change handler InputProps={{ disableUnderline: true, endAdornment: ( @@ -151,20 +137,13 @@ const DocumentSelector = () => { /> - {/* Error Handling */} - {error && ( - - {error} - - )} - Please choose your required document. {/* Document List */} - {filteredDocuments.map((doc) => ( + {documents.map((doc) => ( { /> handleToggle(doc.doc_id)} /> @@ -200,10 +179,10 @@ const DocumentSelector = () => { textTransform: "none", borderRadius: 2, }} - disabled={selectedDocs.size === 0} // Disable button if no documents are selected + disabled={selectedDocs.length === 0} onClick={handleImportClick} > - + Import Documents ({selectedDocs.size}) + + Import Documents ({selectedDocs.length})