setting fundraisng and donor

This commit is contained in:
Sridhar260802 2025-05-16 18:31:05 +05:30
parent 739dfc8700
commit 8720dc73fd
17 changed files with 916 additions and 558 deletions

View File

@ -1,9 +1,8 @@
import React from 'react';
//import React from 'react';
import { BrowserRouter as Router, Routes, Route } from 'react-router-dom';
import Navbar from './Components/Navbar';
import Contact from './Components/Contact';
import Footer from './Components/Footer';
import FormBuilder from './Components/FormBuilder';
import AboutUs from './Components/AboutUs';
import './App.css';
@ -17,6 +16,7 @@ function App() {
<Router>
<Navbar />
<Routes>
<Route path="/" element={<Home />} />
<Route path="/home" element={<Home />} />
<Route path="/aboutUs" element={<AboutUs />} />

View File

@ -1,17 +1,14 @@
import React from "react";
import {
Container,
Typography,
Box,
Grid,
Paper,
Button,
Icon,
} from "@mui/material";
import { useNavigate } from "react-router-dom";
const AboutUs = () => {
const navigate = useNavigate();
return (
<div style={{ padding: "40px 0", backgroundColor: "#f9f9f9" }}>
<Container maxWidth="lg">
@ -25,7 +22,7 @@ const AboutUs = () => {
<Typography variant="h5" sx={{ marginBottom: 3, fontWeight: "bold" }}>
Our History
</Typography>
<Typography variant="body1" paragraph>
<Typography variant="body1" paragraph style={{ textAlign: "justify" }}>
Vertivel Educational Trust was founded in 2010 with a vision to
provide quality education to underprivileged children in rural
and underserved areas. Over the years, the trust has grown into
@ -43,14 +40,14 @@ const AboutUs = () => {
<Typography variant="h5" sx={{ marginBottom: 3, fontWeight: "bold" }}>
Our Achievements
</Typography>
<Typography variant="body1" paragraph>
<Typography variant="body1" paragraph >
- Provided scholarships to over 100 students.
<br />
- Established 10 schools across rural regions.
<br />
- Partnered with top universities to offer vocational training.
<br />
- Awarded "Best Educational NGO" in 2018.
- Awarded &quot;Best Educational NGO&quot; in 2018.
<br />
</Typography>
</Box>

View File

@ -1,5 +1,5 @@
import React from "react";
import { Box, Typography, Grid, Paper } from "@mui/material";
//import React from "react";
import { Typography, Grid, Paper } from "@mui/material";
import './CustomerCountCard.css'
const CustomerCountCard = () => {
@ -27,7 +27,7 @@ const CustomerCountCard = () => {
</Grid>
<Grid item>
<Typography
variant="h5"
variant="h6"
sx={{
fontWeight: "medium",
}}

View File

@ -1,4 +1,3 @@
import React from 'react';
import { useNavigate } from 'react-router-dom';
import { Button, Typography, Box } from '@mui/material';
import './Donate.css'
@ -23,9 +22,13 @@ const Donate = () => {
margin: 'auto'
}}
>
<h1 className="heading-border-bottom" sx={{ marginBottom: '20px', fontWeight: 'bold' }}>
Your Donation Can Make a Difference
</h1>
<Typography
variant="h1"
className="heading-border-bottom"
sx={{ marginBottom: '20px', fontWeight: 'bold' }}
>
<h2>Your Donation Can Make a Difference</h2>
</Typography>
<Typography variant="body1" sx={{ marginBottom: '20px' }}>
Join us in our mission to help those in need. By becoming a donor, you can contribute to
creating a positive impact in the lives of many.

View File

@ -1,4 +1,3 @@
import React from "react";
import { Model } from "survey-core";
import { Survey } from "survey-react-ui";
import "survey-core/defaultV2.min.css";

View File

@ -200,6 +200,18 @@ input:focus {
.form-button:hover:not(:disabled) {
opacity: 0.9;
}
.bank-details {
text-align: left;
background-color: #f9f9f9;
padding: 15px;
margin: 15px 0;
border: 1px solid #ccc;
border-radius: 8px;
line-height: 1.6;
font-size: 0.95rem;
font-family: Arial, sans-serif;
}
@media (max-width: 600px) {
.container-box {

View File

@ -1,28 +1,50 @@
import { useState } from "react";
import "./FundDrive.css";
// Inside src/Components/FundDrive.jsx
import { submitVvvetForm } from "../vvvetApi";
//import { submitVvvetForm } from "../vvvetApi";
import axios from "axios";
import './form-step2.css';
const FundDrive = () => {
const [step, setStep] = useState(1);
const [formData, setFormData] = useState({
name: "",
email: "",
phone: "",
age: "",
dob: "",
category: "",
pan: "",
customCategory: "",
bankHolderName: "",
bankName: "",
ifscCode: "",
fundAmount: "",
accountNumber: "",
images: []
name: "",
email: "",
phone: "",
age: "",
dob: "",
category: "",
customCategory: "",
pan: "",
images: [],
bankHolderName: "",
bankName: "",
accountNumber: "",
ifscCode: "",
fundAmount: "",
paymentMethod: "",
studentName: "",
standard: "",
parentName: "",
parentPhone: "",
feeDocument: null,
patientName: "",
cause: "",
hospitalName: "",
location: "",
attenderName: "",
medicalCertificate: null,
medicalDocument: null,
disasterName: "",
disasterPlace: "",
disasterPhone: "",
disasterDocument: null,
generalName: "",
generalPlace: "",
generalPhone: "",
generalDocument: null
});
const [isPanVerified, setIsPanVerified] = useState(false); // To track PAN verification status
const [verificationError, setVerificationError] = useState("");
@ -49,10 +71,7 @@ const FundDrive = () => {
});
};
const handleImageUpload = (event) => {
const files = Array.from(event.target.files);
setFormData({ ...formData, images: [...formData.images, ...files] });
};
const handleNext = () => {
setStep(step + 1);
@ -72,53 +91,14 @@ const FundDrive = () => {
// const verifyPan = async () => {
// try {
// const formDataForPan = new FormData();
// formDataForPan.append("pan", formData.pan);
// formDataForPan.append("panImage", panImage); // panImage must be a File object
// const response = await axios.post(
// "http://localhost:5002/api/verify-pan",
// formDataForPan,
// {
// headers: {
// "Content-Type": "multipart/form-data",
// },
// withCredentials: true, // Ensures credentials (cookies) are sent
// }
// );
// console.log("vathuten da punda",response.data); // Check the backend response
// const isValid = response.data.verified;
// setIsPanVerified(isValid);
// if (!isValid) {
// setVerificationError("PAN number and uploaded image do not match.");
// }
// return isValid;
// } catch (error) {
// setVerificationError("An error occurred during PAN verification.");
// console.error(error);
// return false;
// }
// };
const verifyPan = async () => {
try {
// Validate PAN format client-side first
const panRegex = /^[A-Z]{5}[0-9]{4}[A-Z]{1}$/;
if (!panRegex.test(formData.pan)) {
setVerificationError("Invalid PAN format. It should be in the format ABCDE1234F.");
setVerificationError("Invalid PAN format.");
setIsPanVerified(false);
return false;
}
if (!panImage) {
setVerificationError("Please upload a PAN card image.");
setIsPanVerified(false);
@ -129,27 +109,17 @@ const FundDrive = () => {
formDataForPan.append("pan", formData.pan);
formDataForPan.append("panImage", panImage);
// Show loading state if needed
// setIsLoading(true);
const response = await axios.post(
"http://localhost:5002/api/verify-pan",
formDataForPan,
{
headers: {
"Content-Type": "multipart/form-data",
},
headers: { "Content-Type": "multipart/form-data" },
}
);
// Hide loading state
// setIsLoading(false);
console.log("PAN verification response:", response.data);
if (response.data.verified) {
setIsPanVerified(true);
setVerificationError(""); // Clear any previous errors
setVerificationError("");
return true;
} else {
setIsPanVerified(false);
@ -157,68 +127,123 @@ const FundDrive = () => {
return false;
}
} catch (error) {
// Hide loading state
// setIsLoading(false);
console.error("Error verifying PAN:", error);
// Handle specific error cases
if (error.response) {
// The server responded with an error status
setVerificationError(error.response.data.message || "PAN verification failed. Server returned an error.");
} else if (error.request) {
// The request was made but no response was received
setVerificationError("Cannot connect to the verification service. Please try again later.");
} else {
// Something else caused the error
setVerificationError("An error occurred during PAN verification.");
}
setVerificationError(
error.response?.data?.message || "Error connecting to PAN verification service."
);
setIsPanVerified(false);
return false;
}
};
// const handleSubmit = async (e) => {
// e.preventDefault();
// if (!isPanVerified) {
// const verified = await verifyPan();
// if (!verified) {
// alert("PAN not verified. Please verify before submitting.");
// return;
// }
// if (!verified) return;
// }
// try {
// await submitVvvetForm(formData);
// alert('Form submitted successfully');
// await axios.post("http://localhost:5002/api/users/add", formData);
// // Ensure this sends the form data to your backend
// setStep(5); // Show the thank-you screen
// } catch (error) {
// console.error("Error submitting form:", error);
// alert('Error submitting form');
// // You can optionally show an inline error message instead of alert
// }
// };
const handleSubmit = async (e) => {
e.preventDefault();
// Verify PAN first if not verified
if (!isPanVerified) {
const verified = await verifyPan();
if (!verified) {
alert("PAN not verified. Please verify before submitting.");
return;
}
if (!verified) return;
}
// Proceed with form submission (assuming `submitVvvetForm` is defined)
try {
await submitVvvetForm(formData); // Make sure this function is defined elsewhere
alert("Form submitted successfully!");
const formSubmissionData = new FormData();
// Append all string fields except files
for (const key in formData) {
const value = formData[key];
if (value !== null && value !== undefined) {
// Check if value is a File or object, skip files here
if (value instanceof File) continue;
if (typeof value === "object") continue;
formSubmissionData.append(key, value);
}
}
// Append files (file inputs) separately
const fileFields = ["feeDoc", "medicalPhoto", "medicalDoc", "document"];
fileFields.forEach((field) => {
if (formData[field]) {
formSubmissionData.append(field, formData[field]);
}
});
// Also append panImage again if you want backend to receive it on form submit
if (panImage) {
formSubmissionData.append("panImage", panImage);
}
const response = await axios.post(
"http://localhost:5002/api/fundraising/submit",
formSubmissionData,
{
headers: { "Content-Type": "multipart/form-data" },
}
);
console.log("Form submission response:", response.data);
// On success, move to thank-you step
setStep(4);
} catch (error) {
console.error("Error submitting form:", error);
alert("Error submitting form");
alert("Error submitting form. Please try again.");
}
};
const isStep2Valid = () => {
const { category, customCategory, customReason } = formData;
if (!category) return false;
if (category === "Others") {
return customCategory?.trim() && customReason?.trim();
}
const requiredFieldsByCategory = {
"Medical Fundraising": ["patientName", "cause", "hospitalName", "location", "phoneNumber", "attenderName", "amount", "medicalPhoto", "medicalDoc"],
"Education & Scholarships": ["studentName", "standard", "parentsName", "parentsPhone", "amount", "feeDoc"],
"Disaster Relief & Aid": ["name", "place", "phoneNumber", "amount", "document"],
"Memorial & Tribute Funds": ["name", "place", "phoneNumber", "amount", "document"],
"Community Development": ["name", "place", "phoneNumber", "amount", "document"],
"Social Causes": ["name", "place", "phoneNumber", "amount", "document"],
"Religious & Faith-Based Giving": ["name", "place", "phoneNumber", "amount", "document"],
"Crowdfunding for Needs": ["name", "place", "phoneNumber", "amount", "document"],
"Nonprofit & NGO Fundraising": ["name", "place", "phoneNumber", "amount", "document"]
};
const fields = requiredFieldsByCategory[category];
if (!fields) return true;
return fields.every(field => {
const value = formData[field];
return value && (typeof value === "string" ? value.trim() : true);
});
};
const handleFileChange = (e) => {
const { name, files } = e.target;
setFormData(prev => ({ ...prev, [name]: files[0] }));
};
return (
@ -339,7 +364,7 @@ const FundDrive = () => {
)}
{step === 2 && (
{/* {step === 2 && (
<div className="form-container-box">
<h4>Step 2:Select a category</h4>
{categories.map((item, index) => (
@ -377,7 +402,174 @@ const FundDrive = () => {
</button>
</div>
</div>
)}
)} */}
{step === 2 && (
<div className="form-container-box">
<h4>Step 2: Select a category</h4>
<select
name="category"
value={formData.category}
onChange={handleInputChange}
className="dropdown-input"
required
>
<option value="">-- Select a Category --</option>
{categories.map((item, index) => (
<option key={index} value={item}>{item}</option>
))}
</select>
{formData.category === "Others" && (
<>
<label>Custom Category</label>
<input
type="text"
name="customCategory"
placeholder="Specify the category"
value={formData.customCategory}
onChange={handleInputChange}
required
className="custom-category-input"
/>
</>
)}
{/* Medical Fundraising */}
{formData.category === "Medical Fundraising" && (
<>
<h5>Medical Fundraising Details</h5>
<label>Patient Name</label>
<input type="text" name="patientName" value={formData.patientName} onChange={handleInputChange} required />
<label>Cause</label>
<input type="text" name="cause" value={formData.cause} onChange={handleInputChange} required />
<label>Hospital Name</label>
<input type="text" name="hospitalName" value={formData.hospitalName} onChange={handleInputChange} required />
<label>Location</label>
<input type="text" name="location" value={formData.location} onChange={handleInputChange} required />
<label>Phone Number</label>
<input type="tel" name="phoneNumber" value={formData.phoneNumber} onChange={handleInputChange} required />
<label>Attender Name</label>
<input type="text" name="attenderName" value={formData.attenderName} onChange={handleInputChange} required />
<label>Amount Needed</label>
<input type="number" name="amount" value={formData.amount} onChange={handleInputChange} required />
<label>Medical Certificate</label>
<input type="file" name="medicalPhoto" accept="image/*" onChange={handleFileChange} required />
<label>Medical Document</label>
<input type="file" name="medicalDoc" accept=".pdf,.doc,.docx" onChange={handleFileChange} required />
</>
)}
{/* Education & Scholarships */}
{formData.category === "Education & Scholarships" && (
<>
<h5>Education & Scholarships Details</h5>
<label>Student Name</label>
<input type="text" name="studentName" value={formData.studentName} onChange={handleInputChange} required />
<label>Standard</label>
<input type="text" name="standard" value={formData.standard} onChange={handleInputChange} required />
<label>Parent&apos;s Name</label>
<input type="text" name="parentsName" value={formData.parentsName} onChange={handleInputChange} required />
<label>Parent&apos;s Phone</label>
<input type="tel" name="parentsPhone" value={formData.parentsPhone} onChange={handleInputChange} required />
<label>Amount Needed</label>
<input type="number" name="amount" value={formData.amount} onChange={handleInputChange} required />
<label>Fee Document</label>
<input type="file" name="feeDoc" accept=".pdf,.doc,.docx" onChange={handleFileChange} required />
</>
)}
{/* Disaster Relief */}
{formData.category === "Disaster Relief & Aid" && (
<>
<h5>Disaster Relief Details</h5>
<label>Name</label>
<input type="text" name="name" value={formData.name} onChange={handleInputChange} required />
<label>Place</label>
<input type="text" name="place" value={formData.place} onChange={handleInputChange} required />
<label>Phone Number</label>
<input type="tel" name="phoneNumber" value={formData.phoneNumber} onChange={handleInputChange} required />
<label>Amount Needed</label>
<input type="number" name="amount" value={formData.amount} onChange={handleInputChange} required />
<label>Relief Document</label>
<input type="file" name="document" accept=".pdf,.doc,.docx" onChange={handleFileChange} required />
</>
)}
{/* Common template for general categories */}
{[
"Memorial & Tribute Funds",
"Community Development",
"Social Causes",
"Religious & Faith-Based Giving",
"Crowdfunding for Needs",
"Nonprofit & NGO Fundraising"
].includes(formData.category) && (
<>
<h5>Fundraising Details</h5>
<label>Name</label>
<input type="text" name="name" value={formData.name} onChange={handleInputChange} required />
<label>Place</label>
<input type="text" name="place" value={formData.place} onChange={handleInputChange} required />
<label>Phone Number</label>
<input type="tel" name="phoneNumber" value={formData.phoneNumber} onChange={handleInputChange} required />
<label>Amount Needed</label>
<input type="number" name="amount" value={formData.amount} onChange={handleInputChange} required />
<label>Support Document</label>
<input type="file" name="document" accept=".pdf,.doc,.docx" onChange={handleFileChange} required />
</>
)}
{/* Others Reason */}
{formData.category === "Others" && (
<>
<h5>Other Fundraising Reason</h5>
<label>Reason</label>
<textarea
name="customReason"
placeholder="Specify your reason"
value={formData.customReason}
onChange={handleInputChange}
required
/>
</>
)}
<div className="button-group">
<button type="button" className="form-button back-button" onClick={handleBack}>Back</button>
<button
type="button"
className="form-button next-button"
onClick={handleNext}
disabled={!isStep2Valid()}
>
Next
</button>
</div>
</div>
)}
{/* {step === 3 && (
@ -399,104 +591,10 @@ const FundDrive = () => {
<img key={index} src={URL.createObjectURL(image)} alt={`Proof ${index + 1}`} className="uploaded-image" />
))}
</div> */}
{step === 3 && (
<div className="upload-section-box">
<h4>Step 3: Upload an Image</h4>
<h3 className="upload-title">
{formData.category === "Others" ? formData.customCategory : formData.category}
</h3>
{/* Common image upload */}
<div className="upload-box">
<input
type="file"
multiple
accept="image/*"
onChange={handleImageUpload}
className="file-input"
/>
<p className="upload-placeholder">Click or Drag & Drop to upload images</p>
</div>
{/* Section-specific forms with headings */}
{formData.category === "Medical Fundraising" && (
<>
<h4 className="section-heading">Upload Medical Details</h4>
<input type="text" placeholder="Patient Name" className="form-field" />
<input type="text" placeholder="Patient Contact Number" className="form-field" />
</>
)}
{formData.category === "Education & Scholarships" && (
<>
<h4 className="section-heading">Upload Student Details</h4>
<input type="text" placeholder="Student Name" className="form-field" />
<input type="text" placeholder="Standard/Class" className="form-field" />
</>
)}
{formData.category === "Disaster Relief & Aid" && (
<>
<h4 className="section-heading">Upload Relief Information</h4>
<input type="text" placeholder="Cause/Place Affected" className="form-field" />
</>
)}
{formData.category === "Memorial & Tribute Funds" && (
<>
<h4 className="section-heading">Upload Tribute Details</h4>
<input type="text" placeholder="Person Honored" className="form-field" />
</>
)}
{[
"Community Development",
"Social Causes",
"Religious & Faith-Based Giving",
"Crowdfunding for Needs",
"Nonprofit & NGO Fundraising",
].includes(formData.category) && (
<>
<h4 className="section-heading">Upload Cause Information</h4>
<input type="text" placeholder="Cause Details" className="form-field" />
</>
)}
{formData.category === "Others" && (
<>
<h4 className="section-heading">Upload Custom Details</h4>
<input type="text" placeholder="Describe your cause" className="form-field" />
<input type="file" className="form-field" />
</>
)}
{/* Image preview */}
<div className="image-preview">
{formData.images.map((image, index) => (
<img
key={index}
src={URL.createObjectURL(image)}
alt={`Proof ${index + 1}`}
className="uploaded-image"
/>
))}
</div>
<div className="button-group">
<button type="button" className="form-button back-button" onClick={handleBack}>Back</button>
<button
type="button"
className="form-button next-button"
onClick={handleNext}
disabled={!formData.category || (formData.category === "Others" && !formData.customCategory.trim())}
>
Next
</button>
</div>
</div>
)}
{step === 4 && (
<div className="bank-details-section-box">
<h4>Step 4: Banking Details</h4>
<h4>Step 3: Banking Details</h4>
<div className="form-group">
<label className="form-label">Bank Account Holder Name</label>
@ -527,8 +625,15 @@ const FundDrive = () => {
placeholder="Bank Account Number"
className="form-field"
value={formData.accountNumber}
onChange={(e) => setFormData({ ...formData, accountNumber: e.target.value })}
onChange={(e) => {
const value = e.target.value;
if (/^\d{0,17}$/.test(value)) {
setFormData({ ...formData, accountNumber: value });
}
}}
/>
{(formData.accountNumber.length < 11 || formData.accountNumber.length > 17)
}
</div>
<div className="form-group">
@ -538,9 +643,13 @@ const FundDrive = () => {
placeholder="IFSC Code"
className="form-field"
value={formData.ifscCode}
onChange={(e) => setFormData({ ...formData, ifscCode: e.target.value })}
onChange={(e) => setFormData({ ...formData, ifscCode: e.target.value.toUpperCase() })}
/>
{!/^[A-Z]{4}0[A-Z0-9]{6}$/.test(formData.ifscCode) && formData.ifscCode !== '' && (
<p className="error-message">Invalid IFSC Code format</p>
)}
</div>
<div className="form-group">
<label className="form-label">Fundraising Amount</label>
<input
@ -550,9 +659,7 @@ const FundDrive = () => {
value={formData.fundAmount}
onChange={(e) => {
const value = parseInt(e.target.value, 10);
if (!isNaN(value) && value >= 0) {
setFormData({ ...formData, fundAmount: value });
}
setFormData({ ...formData, fundAmount: isNaN(value) ? '' : value });
}}
min="1000"
/>
@ -560,11 +667,27 @@ const FundDrive = () => {
<p className="error-message">Minimum amount should be 1000</p>
)}
</div>
<div className="button-group">
<button type="button" className="form-button back-button" onClick={handleBack}>
Back
</button>
<button type="button" className="form-button submit-button" onClick={handleSubmit}>
<button
type="button"
className="form-button submit-button"
onClick={handleSubmit}
disabled={
!formData.bankHolderName ||
!formData.bankName ||
!formData.accountNumber ||
formData.accountNumber.length < 11 ||
formData.accountNumber.length > 17 ||
!formData.ifscCode ||
!/^[A-Z]{4}0[A-Z0-9]{6}$/.test(formData.ifscCode) ||
!formData.fundAmount ||
formData.fundAmount < 1000
}
>
Submit
</button>
</div>
@ -572,6 +695,20 @@ const FundDrive = () => {
)}
{step === 4 && (
<div className="form-container-box">
<h4>Thank You!</h4>
<p>Thanks for reaching out to VVET. We will review your submission and get back to you soon.</p>
<button className="form-button" onClick={() => window.location.reload()}>
Start Over
</button>
</div>
)}
</form>
</div>
</div>

View File

@ -2,7 +2,7 @@ import './Homesection1.css'
const HomeSection1 = () => {
return (
<div class="home-section">
<div className="home-section">
<div>
<h1 className='heading-border-bottom'>Welcome to Vertivel Educational Trust</h1>
<p>

View File

@ -1,4 +1,3 @@
import Navbar from "./Navbar";
import Footer from "./Footer";
import Carousel from "./Carousel";
import HomeSection1 from "./Home-Section-1";
@ -12,7 +11,6 @@ import "./Home.css";
const Home = () => {
const images = [
"https://i.postimg.cc/4NtQrKtZ/Untitled1.jpg",
"https://i.postimg.cc/MKkybWLL/Untitled2.jpg",
"https://i.postimg.cc/15pDvkh3/Untitled3.jpg",
"https://i.postimg.cc/6pcnXCQs/Untitled4.jpg",

View File

@ -1,4 +1,3 @@
import React from 'react';
import { Button, Typography, Box, Grid, Icon } from '@mui/material';
import { AccessAlarm, School, CheckCircle } from '@mui/icons-material';
import { useNavigate } from 'react-router-dom';
@ -28,7 +27,7 @@ const HomeMockSection = () => {
<Typography variant="body1" sx={{ marginBottom: '20px' }}>
Prepare for NEET with high-quality mock tests designed to give you the best practice before the big exam.
With Vidhai's mock tests, you can assess your performance and get feedback that helps you improve.
With Vidhai&apos;s mock tests, you can assess your performance and get feedback that helps you improve.
</Typography>
<Grid container spacing={2} sx={{ marginBottom: '20px' }}>

View File

@ -1,4 +1,3 @@
import React from 'react';
import './Marquee.css'; // Import the CSS file for styling
const Marquee = () => {

View File

@ -1,4 +1,4 @@
import React, { useState } from "react";
import { useState } from "react";
import { Link, useNavigate } from "react-router-dom";
import "./Navbar.css";
@ -21,7 +21,7 @@ function Navbar() {
alt="College Logo"
/>
<div className="brand-section">
<h4 className="college-name" onClick={() => navigate("/")}>
<h4 className="college-name" onClick={() => navigate("/home")}>
VETRIVEL EDUCATIONAL TRUST
</h4>
<p>A Legacy of Excellence in Education</p>
@ -34,7 +34,7 @@ function Navbar() {
</button>
{/* Links */}
<div className={`links ${menuOpen ? "open" : ""}`}>
<div className={`links ${menuOpen ? "open" : "/home"}`}>
<Link to="/home">Home</Link>
<Link to="/aboutUs">About Us</Link>

View File

@ -1,6 +1,5 @@
import React from 'react';
import { Card, CardContent, Typography } from '@mui/material';
import { Support, AttachMoney, Group } from '@mui/icons-material'; // Importing specific Material UI icons
import { AttachMoney, Group } from '@mui/icons-material'; // Importing specific Material UI icons
import PersonIcon from '@mui/icons-material/Person';
import './StatsCard.css'

View File

@ -1,354 +1,483 @@
import { useState } from "react";
import "./Supporter.css";
import "./FundDrive.css";
// Inside src/Components/FundDrive.jsx
import axios from "axios";
import './form-step2.css';
const Supporter = () => {
const FundDrive = () => {
const [step, setStep] = useState(1);
const [isSubmitting, setIsSubmitting] = useState(false);
const [formData, setFormData] = useState({
name: "",
email: "",
phone: "",
age: "",
dob: "",
aadharFront: null,
aadharBack: null,
paymentMethod: "",
paymentScreenshot: null,
email: "",
phone: "",
age: "",
dob: "",
category: "",
customCategory: "",
pan: "",
images: [],
bankHolderName: "",
bankName: "",
accountNumber: "",
ifscCode: "",
donation_Amount: "",
payment: "",
transactionScreenshot: null,
feeDoc: null,
});
const [isPanVerified, setIsPanVerified] = useState(false); // To track PAN verification status
const [verificationError, setVerificationError] = useState("");
const [panImage, setPanImage] = useState(null); // Define panImage state
const [showPaymentScreenshot, setShowPaymentScreenshot] = useState(false);
const handleChange = (e) => {
const { name, value, files } = e.target;
setFormData((prev) => ({
...prev,
[name]: files ? files[0] : value,
}));
const handleInputChange = (e) => {
const { name, value } = e.target;
setFormData({
...formData,
[name]: value,
});
};
const nextStep = () => {
if (isValid()) setStep((prev) => prev + 1);
const handleNext = () => {
setStep(step + 1);
};
const prevStep = () => setStep((prev) => prev - 1);
const isValid = () => {
if (step === 1) {
return formData.name && formData.email && formData.phone && formData.age && formData.dob;
}
if (step === 2) {
return formData.aadharFront && formData.aadharBack;
}
if (step === 3) {
return formData.paymentMethod;
}
if (step === 4 && formData.paymentMethod === "UPI") {
return formData.paymentScreenshot;
}
return true;
const handleBack = () => {
if (step > 1) setStep(step - 1);
};
const handlePanImageUpload = (e) => {
const file = e.target.files[0];
setPanImage(file); // Store PAN image in state
};
const verifyPan = async () => {
try {
// Validate PAN format client-side first
const panRegex = /^[A-Z]{5}[0-9]{4}[A-Z]{1}$/;
if (!panRegex.test(formData.pan)) {
setVerificationError("Invalid PAN format. It should be in the format ABCDE1234F.");
setIsPanVerified(false);
return false;
}
if (!panImage) {
setVerificationError("Please upload a PAN card image.");
setIsPanVerified(false);
return false;
}
const formDataForPan = new FormData();
formDataForPan.append("pan", formData.pan);
formDataForPan.append("panImage", panImage);
// Show loading state if needed
// setIsLoading(true);
const response = await axios.post(
"http://localhost:5002/api/verify-pan",
formDataForPan,
{
headers: {
"Content-Type": "multipart/form-data",
},
}
);
console.log("PAN verification response:", response.data);
if (response.data.verified) {
setIsPanVerified(true);
setVerificationError(""); // Clear any previous errors
return true;
} else {
setIsPanVerified(false);
setVerificationError(response.data.message || "PAN verification failed.");
return false;
}
} catch (error) {
// Hide loading state
// setIsLoading(false);
console.error("Error verifying PAN:", error);
// Handle specific error cases
if (error.response) {
// The server responded with an error status
setVerificationError(error.response.data.message || "PAN verification failed. Server returned an error.");
} else if (error.request) {
// The request was made but no response was received
setVerificationError("Cannot connect to the verification service. Please try again later.");
} else {
// Something else caused the error
setVerificationError("An error occurred during PAN verification.");
}
setIsPanVerified(false);
return false;
}
};
const handleFileChange = (e) => {
const { name, files } = e.target;
setFormData((prev) => ({ ...prev, [name]: files[0] }));
};
const handleSubmit = async (e) => {
e.preventDefault();
setIsSubmitting(true);
// Verify PAN first if not verified
if (!isPanVerified) {
const verified = await verifyPan();
if (!verified) return;
}
try {
console.log("Submitting Form Data:", formData);
setTimeout(() => {
alert("Form Submitted Successfully!");
setIsSubmitting(false);
setFormData({
name: "",
email: "",
phone: "",
age: "",
dob: "",
aadharFront: null,
aadharBack: null,
paymentMethod: "",
paymentScreenshot: null,
});
}, 2000);
const formSubmissionData = new FormData();
// Append non-file fields
for (const key in formData) {
if (formData[key] && !(formData[key] instanceof File)) {
formSubmissionData.append(key, formData[key]);
}
}
// Append donor-specific file fields
if (panImage) {
formSubmissionData.append("panImage", panImage);
}
if (formData.transactionScreenshot) {
formSubmissionData.append("transactionScreenshot", formData.transactionScreenshot);
}
const response = await axios.post(
"http://localhost:5002/api/donor/submit",
formSubmissionData,
{ headers: { "Content-Type": "multipart/form-data" } }
);
console.log("Donor form response:", response.data);
setStep(4); // success step
} catch (error) {
console.error("Submission Error:", error);
alert("Something went wrong. Please try again.");
setIsSubmitting(false);
console.error("Donor form submission error:", error);
alert("Error submitting donor form. Please try again.");
}
};
const handleUPIPayment = () => {
const upiUrl =
"upi://pay?pa=157511100001246@UBIN0815756.ifsc.npci&pn=Ashoka%20Windows%20and%20Annex%20Apartment%20Owners%20Association&cu=INR&am=50&tn=113%20Dec%202021%20fine&tr=202112113fine&refUrl=https%3A%2F%2Fwww.ashokawindows.com";
// Open the UPI payment app
window.location.href = upiUrl;
// Immediately show the upload screenshot field after clicking Pay via UPI
setShowPaymentScreenshot(true);
};
const handleNetBankingPayment = () => {
// Placeholder for actual Net Banking redirection or API call
alert("Redirecting to Net Banking Payment Gateway...");
};
return (
<div className="supporter-container">
<div className="step-box">
<form onSubmit={handleSubmit}>
{step === 1 && (
<div className="step1-box">
<h4>Step 1:Personal Details</h4>
<label>Name:</label>
<div className="container">
<div className="container-box">
<form>
{step === 1 && (
<div className="step-box">
<h4>Step 1: Personal Details</h4>
<div className="form-grid">
<div className="form-field">
<label>Name</label>
<input
type="text"
name="name"
value={formData.name}
onChange={handleInputChange}
required
placeholder="Full Name"
/>
</div>
<div className="form-field">
<label>Email</label>
<input
type="email"
name="email"
value={formData.email}
onChange={handleInputChange}
required
placeholder="example@domain.com"
/>
</div>
<div className="form-field">
<label>Age</label>
<input
type="number"
name="age"
value={formData.age}
onChange={handleInputChange}
required
placeholder="e.g. 25"
/>
</div>
<div className="form-field">
<label>Date of Birth</label>
<input
type="date"
name="dob"
value={formData.dob}
onChange={handleInputChange}
required
placeholder="e.g. 25"
/>
</div>
</div>
<div className="form-field">
<label>Phone Number</label>
<input
type="tel"
name="phone"
value={formData.phone}
onChange={handleInputChange}
required
placeholder="10-digit number"
/>
</div>
<div className="form-field">
<label>PAN Number</label>
<input
type="text"
name="name"
value={formData.name}
onChange={handleChange}
name="pan"
value={formData.pan}
onChange={handleInputChange}
required
maxLength={10}
placeholder="e.g. ABCDE1234F"
className="input-small"
placeholder="Enter your name"
pattern="[A-Z]{5}[0-9]{4}[A-Z]{1}"
title="Enter valid 10-character PAN (e.g. ABCDE1234F)"
/>
<label>Email:</label>
<input
type="email"
name="email"
value={formData.email}
onChange={handleChange}
required
className="input-small"
placeholder="Enter your email"
/>
<label>Phone Number:</label>
<input
type="tel"
name="phone"
value={formData.phone}
onChange={handleChange}
required
className="input-small"
placeholder="Enter phone number"
/>
<label>Age:</label>
<input
type="number"
name="age"
value={formData.age}
onChange={handleChange}
required
className="input-small"
placeholder="Enter your age"
/>
<label>Date of Birth:</label>
<input
type="date"
name="dob"
value={formData.dob}
onChange={handleChange}
required
className="input-small"
/>
<br />
<br />
</div>
<div className="form-field">
<label>Upload PAN Image</label>
<input
type="file"
accept="image/*"
onChange={handlePanImageUpload}
required
/>
{panImage && <p>{panImage.name}</p>} {/* Display image file name */}
</div>
{verificationError && <p style={{ color: 'red' }}>{verificationError}</p>}
<div className="form-field">
<button
type="button"
onClick={nextStep}
disabled={!isValid()}
className="form-button verify-button"
onClick={verifyPan}
disabled={!formData.pan || !panImage}
>
Verify PAN
</button>
{isPanVerified && <p style={{ color: 'green' }}>PAN verified successfully!</p>}
</div>
<div className="button-group">
<button
type="button"
onClick={handleNext}
className="form-button next-button"
disabled={!formData.name || !formData.email || !formData.phone || !formData.age || !formData.dob || !formData.pan || !isPanVerified}
>
Next
</button>
</div>
)}
</div>
)}
{step === 2 && (
<div className="step2-box">
<h4>Step 2:Upload a Images</h4>
<label>Aadhar Card Front:</label>
<input
type="file"
name="aadharFront"
onChange={handleChange}
required
className="input-small"
/>
<label>Aadhar Card Back:</label>
<input
type="file"
name="aadharBack"
onChange={handleChange}
required
className="input-small"
/>
<br />
<br />
<button
type="button"
onClick={prevStep}
className="form-button back-button"
>
Back
</button>
<div style={{ marginTop: "10px" }}>
<button
type="button"
onClick={nextStep}
disabled={!isValid()}
className="form-button next-button"
>
Next
</button>
</div>
</div>
)}
{step === 3 && (
<div className="step3-box">
<h4>Step 3:Select Payment Method</h4>
<label>Payment Method:</label>
<select
name="paymentMethod"
value={formData.paymentMethod}
onChange={handleChange}
required
className="input-small"
{step === 2 && (
<div className="bank-details-section-box">
<h4>Step 2: Banking Details</h4>
>
<option value="UPI">Pay by any UPI App</option>
<option value="Net Banking">Net Banking</option>
</select>
<br />
<br />
<button
type="button"
onClick={prevStep}
className="form-button back-button"
>
Back
</button>
<div style={{ marginTop: "10px" }}>
<button
type="button"
onClick={nextStep}
disabled={!isValid()}
className="form-button next-button"
>
Next
</button>
</div>
</div>
)}
{step === 4 && formData.paymentMethod === "UPI" && (
<div className="step4-box">
<h4>Step 4:Pay via UPI</h4>
<br></br>
<br></br>
<button
type="button"
onClick={handleUPIPayment}
className="form-button upi-button"
>
Pay via UPI
</button>
{/* Upload screenshot field appears after Pay via UPI is clicked */}
{showPaymentScreenshot && (
<div className="payment-screenshot">
<label>Upload Payment Screenshot:</label>
<input
type="file"
name="paymentScreenshot"
onChange={handleChange}
required
className="input-small"
/>
</div>
)}
<br />
<br />
<button
type="button"
onClick={prevStep}
className="form-button back-button"
>
Back
</button>
<div style={{ marginTop: "10px" }}>
<button
type="submit"
disabled={isSubmitting || !formData.paymentScreenshot}
className="form-button submit-button"
>
{isSubmitting ? "Submitting..." : "Submit"}
</button>
</div>
</div>
)}
{step === 4 && formData.paymentMethod === "Net Banking" && (
<div className="step4-box">
<h4>Step 4:Pay via Net banking</h4>
<br></br>
<br></br>
{/* Net Banking - Redirection or Process */}
<button
type="button"
onClick={handleNetBankingPayment}
className="form-button net-banking-button"
>
Pay via Net Banking
</button>
{/* Upload screenshot field appears after Pay via Net Banking is clicked */}
{showPaymentScreenshot && (
<div className="payment-screenshot">
<label>Upload Payment Screenshot:</label>
<input
type="file"
name="paymentScreenshot"
onChange={handleChange}
required
className="input-small"
/>
</div>
)}
<br />
<br />
<button
type="button"
onClick={prevStep}
className="form-button back-button"
>
Back
</button>
<div style={{ marginTop: "10px" }}>
<button
type="submit"
disabled={isSubmitting || !formData.paymentScreenshot}
className="form-button submit-button"
>
{isSubmitting ? "Submitting..." : "Submit"}
</button>
</div>
</div>
)}
</form>
</div>
<div className="form-group">
<label className="form-label">Bank Account Holder Name</label>
<input
type="text"
placeholder="Bank Account Holder Name"
className="form-field"
value={formData.bankHolderName}
onChange={(e) => setFormData({ ...formData, bankHolderName: e.target.value })}
/>
</div>
<div className="form-group">
<label className="form-label">Bank Name</label>
<input
type="text"
placeholder="Bank Name"
className="form-field"
value={formData.bankName}
onChange={(e) => setFormData({ ...formData, bankName: e.target.value })}
/>
</div>
<div className="form-group">
<label className="form-label">Bank Account Number</label>
<input
type="text"
placeholder="Bank Account Number"
className="form-field"
value={formData.accountNumber}
onChange={(e) => setFormData({ ...formData, accountNumber: e.target.value })}
/>
</div>
<div className="form-group">
<label className="form-label">IFSC Code</label>
<input
type="text"
placeholder="IFSC Code"
className="form-field"
value={formData.ifscCode}
onChange={(e) => setFormData({ ...formData, ifscCode: e.target.value })}
/>
</div>
<div className="form-group">
<label className="form-label">Donating Amount</label>
<input
type="number"
placeholder="Donating Amount"
className="form-field"
value={formData.donation_Amount}
onChange={(e) => {
const value = parseInt(e.target.value, 10);
if (!isNaN(value) && value >= 0) {
setFormData({ ...formData, donation_Amount: value });
}
}}
min="1000"
/>
{formData.donation_Amount > 0 && formData.donation_Amount < 1000 && (
<p className="error-message">Minimum amount should be 1000</p>
)}
</div>
<div className="button-group">
<button type="button" className="form-button back-button" onClick={handleBack}>
Back
</button>
{/* <button type="button" className="form-button submit-button" onClick={handleNext}>
Next
</button> */}
<button
type="button"
className="form-button submit-button"
onClick={handleNext}
disabled={
!formData.bankHolderName ||
!formData.bankName ||
!formData.accountNumber ||
formData.accountNumber.length < 11 ||
formData.accountNumber.length > 17 ||
!formData.ifscCode ||
!/^[A-Z]{4}0[A-Z0-9]{6}$/.test(formData.ifscCode) ||
!formData.donation_Amount||
formData.donation_Amount < 1000
}
>
Next
</button>
</div>
</div>
)}
{step === 3 && (
<div className="form-container-box">
<h4>Step 3: Payment & Upload Transaction Screenshot</h4>
<label htmlFor="payment">Select Payment Method *</label>
<select
name="payment"
value={formData.payment || ""}
onChange={handleInputChange}
required
className="form-select"
>
<option value="" disabled>Select Payment Mode</option>
<option value="UPI">UPI</option>
<option value="Bank Transfer">Bank Transfer</option>
</select>
{/* UPI QR Code */}
{formData.payment === "UPI" && (
<div className="upi-section">
<p>Scan the UPI QR code to make the payment:</p>
<img src="src/Components/upi.png" alt="UPI QR Code" className="upi-image" />
</div>
)}
{/* Bank Transfer Details */}
{formData.payment === "Bank Transfer" && (
<div className="bank-details">
<p><strong>Account No:</strong> 50200082832122</p>
<p><strong>Bank:</strong> HDFC</p>
<p><strong>Branch:</strong> DEVAKOTTAI</p>
<p><strong>Account Name:</strong> DVK VETRIVEL EDU AND WEL PUB CHAR TRUST</p>
<p><strong>Account Type:</strong> Current</p>
<p><strong>RTGS/NEFT IFSC:</strong> HDFC0002576</p>
</div>
)}
{/* Screenshot Upload */}
{formData.payment && (
<>
<label htmlFor="transactionScreenshot">Upload Transaction Screenshot *</label>
<input
type="file"
name="transactionScreenshot"
accept="image/*"
onChange={handleFileChange}
required
/>
</>
)}
<div className="button-group">
<button type="button" className="form-button back-button" onClick={handleBack}>
Back
</button>
<button
type="button"
className="form-button next-button"
onClick={handleSubmit}
disabled={!formData.payment || !formData.transactionScreenshot}
>
Submit
</button>
</div>
</div>
)}
{step === 4 && (
<div className="form-container-box">
<h4>Thank You!</h4>
<p>Thanks for reaching out to VVET. We will review your submission and get back to you soon.</p>
<button className="form-button" onClick={() => window.location.reload()}>
Start Over
</button>
</div>
)}
</form>
</div>
</div>
);
};
export default Supporter;
export default FundDrive;

View File

@ -0,0 +1,86 @@
.form-container-box {
padding: 20px;
border: 1px solid #ddd;
border-radius: 10px;
background-color: #fff;
max-width: 600px;
margin: 0 auto;
}
h4 {
margin-bottom: 20px;
font-size: 1.5rem;
color: #f3efef;
}
h5 {
margin-top: 30px;
margin-bottom: 15px;
font-size: 1.2rem;
color: #a9a3a3;
padding-bottom: 5px;
}
label {
display: block;
margin-top: 15px;
margin-bottom: 5px;
font-weight: 500;
color: #333;
text-align: left;
}
input[type="text"],
input[type="number"],
input[type="tel"],
input[type="file"],
select,
textarea {
width: 100%;
padding: 10px;
margin-bottom: 10px;
border: 1px solid #ccc;
border-radius: 6px;
font-size: 1rem;
box-sizing: border-box;
}
select.dropdown-input {
margin-top: 10px;
background-color: #f9f9f9;
}
textarea {
min-height: 100px;
resize: vertical;
}
.button-group {
display: flex;
justify-content: space-between;
margin-top: 30px;
}
.form-button {
padding: 10px 20px;
background-color: #007bff;
color: white;
border: none;
border-radius: 6px;
cursor: pointer;
font-size: 1rem;
}
.form-button:disabled {
background-color: #ccc;
cursor: not-allowed;
}
.back-button {
background-color: #6c757d;
}
.custom-category-input {
margin-top: 10px;
}

BIN
src/Components/upi.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 43 KiB

View File

@ -3,7 +3,7 @@ import axios from 'axios';
export const submitVvvetForm = async (formData) => {
try {
const response = await axios.post('http://localhost:5002/api/vvet/add', formData);
const response = await axios.post('http://localhost:5002/api/users/add', formData);
return response.data;
} catch (error) {
console.error('Error submitting form:', error);