Skip to content

Commit 1d33831

Browse files
committed
Fixed UploadBR
1 parent 3cf81fa commit 1d33831

3 files changed

Lines changed: 89 additions & 12 deletions

File tree

admin/public/BR.csv

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
email
2+
j.avni@iitg.ac.in

admin/src/apis/br.js

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,3 +15,48 @@ export const fetchBRs = async () => {
1515
throw error;
1616
}
1717
};
18+
19+
// Parse CSV and upload BRs
20+
export const uploadBRs = async (file) => {
21+
try {
22+
// Parse CSV file
23+
const csvText = await file.text();
24+
const lines = csvText.split("\n").filter((line) => line.trim() !== "");
25+
26+
// Skip header row and extract emails
27+
const emails = [];
28+
for (let i = 1; i < lines.length; i++) {
29+
const email = lines[i].trim().replace(/"/g, ""); // Remove quotes if any
30+
if (email && email.includes("@")) {
31+
// Basic email validation
32+
emails.push({ email: email });
33+
}
34+
}
35+
36+
if (emails.length === 0) {
37+
throw new Error("No valid emails found in the CSV file");
38+
}
39+
40+
// Call backend API
41+
const response = await fetch(`${API_BASE_URL}api/br/updateList`, {
42+
method: "POST",
43+
credentials: "include",
44+
headers: {
45+
"Content-Type": "application/json",
46+
Authorization: "Bearer admin-coursehub-cc23-golang",
47+
},
48+
body: JSON.stringify({ emails }),
49+
});
50+
51+
const result = await response.json();
52+
53+
if (!response.ok) {
54+
throw result;
55+
}
56+
57+
return result;
58+
} catch (error) {
59+
console.error("Error uploading BRs:", error);
60+
throw error;
61+
}
62+
};

admin/src/components/UploadBRs.jsx

Lines changed: 42 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,19 @@
11
import React, { useState } from "react";
2-
import axios from "axios";
32
import { Modal, ModalHeader, ModalFooter, ModalBody, ModalCloseButton } from "./ui/modal";
3+
import { uploadBRs } from "../apis/br";
44

55
const UploadBRs = ({ onUpload, onClose }) => {
66
const [file, setFile] = useState(null);
77
const [error, setError] = useState(null);
88
const [success, setSuccess] = useState(null);
9+
const [warnings, setWarnings] = useState(null);
910

1011
const handleFileChange = (e) => {
1112
setFile(e.target.files[0]);
13+
// Clear previous messages when new file is selected
14+
setError(null);
15+
setSuccess(null);
16+
setWarnings(null);
1217
};
1318

1419
const handleSubmit = async (e) => {
@@ -18,23 +23,41 @@ const UploadBRs = ({ onUpload, onClose }) => {
1823
return;
1924
}
2025

21-
const formData = new FormData();
22-
formData.append("file", file);
26+
// Validate file type
27+
if (!file.name.toLowerCase().endsWith(".csv")) {
28+
setError("Please upload a CSV file.");
29+
return;
30+
}
2331

2432
try {
25-
const response = await axios.post("/api/br/updateList", formData, {
26-
headers: {
27-
"Content-Type": "multipart/form-data",
28-
},
29-
});
30-
setSuccess(response.data.message);
33+
const response = await uploadBRs(file);
34+
setSuccess(response.message);
3135
setError(null);
36+
setWarnings(null);
3237
if (onUpload) {
3338
onUpload();
3439
}
3540
} catch (err) {
36-
setError(err.response?.data?.error || "An error occurred during file upload.");
37-
setSuccess(null);
41+
// Handle partial success (409 status)
42+
if (err.existingEmails || err.notInUsers) {
43+
let warningMessage = "";
44+
if (err.existingEmails && err.existingEmails.length > 0) {
45+
warningMessage += `Already existing BRs: ${err.existingEmails.join(", ")}. `;
46+
}
47+
if (err.notInUsers && err.notInUsers.length > 0) {
48+
warningMessage += `Emails not found in users: ${err.notInUsers.join(", ")}.`;
49+
}
50+
setWarnings(warningMessage);
51+
setError(null);
52+
setSuccess("Partial upload completed.");
53+
if (onUpload) {
54+
onUpload();
55+
}
56+
} else {
57+
setError(err.error || err.message || "An error occurred during file upload.");
58+
setSuccess(null);
59+
setWarnings(null);
60+
}
3861
}
3962
};
4063

@@ -44,11 +67,13 @@ const UploadBRs = ({ onUpload, onClose }) => {
4467
<ModalCloseButton onClose={onClose} />
4568
<ModalBody>
4669
<p className="text-sm text-gray-600 mb-4">
47-
Upload a CSV file to update the BR list.
70+
Upload a CSV file to update the BR list. The CSV should have one column named
71+
"email".
4872
</p>
4973
<form onSubmit={handleSubmit} className="space-y-4">
5074
<input
5175
type="file"
76+
accept=".csv"
5277
onChange={handleFileChange}
5378
className="block w-full text-sm text-gray-500 file:mr-4 file:py-2 file:px-4 file:rounded-full file:border-0 file:text-sm file:font-semibold file:bg-blue-100 file:text-blue-700 hover:file:bg-blue-200 transition-colors"
5479
/>
@@ -69,6 +94,11 @@ const UploadBRs = ({ onUpload, onClose }) => {
6994
{success}
7095
</p>
7196
)}
97+
{warnings && (
98+
<p className="mt-3 text-sm text-yellow-600 bg-yellow-50 p-2 rounded shadow-sm">
99+
<strong>Warning:</strong> {warnings}
100+
</p>
101+
)}
72102
</ModalBody>
73103
<ModalFooter>
74104
<button

0 commit comments

Comments
 (0)