feat: implement cover image upload with canvas compression and db storage in RIT-EMS-main
This commit is contained in:
@@ -267,10 +267,69 @@ const App: React.FC = () => {
|
||||
profile = externalStudent;
|
||||
finalRole = 'STUDENT';
|
||||
} else {
|
||||
// FALLBACK: Auto-sync profile from metadata
|
||||
// FALLBACK: Auto-sync profile from metadata or auto-register from Google email format
|
||||
const meta = user.user_metadata;
|
||||
// ... (rest of metadata sync logic)
|
||||
if (meta && (meta.role === 'STUDENT' || meta.regNo)) {
|
||||
const emailLower = (user.email || '').trim().toLowerCase();
|
||||
const studentMatch = emailLower.match(/^student\.(\d{6})@([a-zA-Z0-9&-_]+)\.ritchennai\.edu\.in$/);
|
||||
|
||||
if (studentMatch) {
|
||||
const rollNo = studentMatch[1];
|
||||
const rawDept = studentMatch[2].toLowerCase();
|
||||
|
||||
// Calculate joining year and academic year (current local time is 2026-06-19)
|
||||
const joinYear = 2000 + parseInt(rollNo.substring(0, 2));
|
||||
const currentYear = new Date().getFullYear();
|
||||
const currentMonth = new Date().getMonth();
|
||||
const academicYearOffset = currentMonth >= 5 ? 1 : 0;
|
||||
const yearIndex = currentYear - joinYear + academicYearOffset;
|
||||
const years = ["1st Year", "2nd Year", "3rd Year", "4th Year"];
|
||||
const calculatedYear = years[yearIndex - 1] || "N/A";
|
||||
|
||||
// Map department
|
||||
let dept = rawDept.toUpperCase();
|
||||
if (dept === 'AIDS') dept = 'AI&DS';
|
||||
else if (dept === 'AIML') dept = 'AI&ML';
|
||||
else if (dept === 'VLSI') dept = 'EE(VLSI)';
|
||||
else if (dept === 'BIOTECH' || dept === 'BIO-TECH') dept = 'BIOTECH';
|
||||
else if (dept === 'H&S') dept = 'H&S Dept';
|
||||
|
||||
const syncData = {
|
||||
id: user.id,
|
||||
name: meta?.name || `Student ${rollNo}`,
|
||||
email: emailLower,
|
||||
reg_no: rollNo,
|
||||
phone: '',
|
||||
department: dept,
|
||||
year: calculatedYear,
|
||||
section: 'A',
|
||||
college_name: 'Rajalakshmi Institute of Technology',
|
||||
updated_at: new Date().toISOString()
|
||||
};
|
||||
|
||||
const { data: synced } = await supabase.from('Studentusers').upsert(syncData).select().single();
|
||||
profile = synced || syncData;
|
||||
finalRole = 'STUDENT';
|
||||
} else if (emailLower && !emailLower.endsWith('@ritchennai.edu.in') && !emailLower.endsWith('@rit.edu') && !HIGH_AUTH_ADMINS.includes(emailLower)) {
|
||||
// Auto-register external user if signing in via Google with a non-campus email
|
||||
const syncData = {
|
||||
id: user.id,
|
||||
name: meta?.name || emailLower.split('@')[0],
|
||||
email: emailLower,
|
||||
reg_no: 'EXT-' + Math.floor(Math.random() * 100000),
|
||||
phone: '',
|
||||
department: 'Others',
|
||||
year: 'N/A',
|
||||
section: 'N/A',
|
||||
college: 'External Institution',
|
||||
college_location: 'N/A',
|
||||
gender: 'Male',
|
||||
updated_at: new Date().toISOString()
|
||||
};
|
||||
|
||||
const { data: synced } = await supabase.from('externalusers').upsert(syncData).select().single();
|
||||
profile = synced || syncData;
|
||||
finalRole = 'STUDENT';
|
||||
} else if (meta && (meta.role === 'STUDENT' || meta.regNo)) {
|
||||
const isExternal = meta.signUpType === 'EXTERNAL';
|
||||
const table = isExternal ? 'externalusers' : 'Studentusers';
|
||||
|
||||
@@ -303,7 +362,7 @@ const App: React.FC = () => {
|
||||
finalRole = 'STUDENT';
|
||||
} else {
|
||||
console.warn("Auto-sync profile failed:", syncError?.message);
|
||||
profile = syncData; // Use metadata-based object as semi-functional fallback
|
||||
profile = syncData;
|
||||
finalRole = 'STUDENT';
|
||||
}
|
||||
} else if (meta && (meta.role === 'ADMIN' || meta.role === 'COORDINATOR')) {
|
||||
@@ -430,8 +489,36 @@ const App: React.FC = () => {
|
||||
const { data: { subscription } } = supabase.auth.onAuthStateChange((_event, session) => {
|
||||
handleAuthChange(session);
|
||||
});
|
||||
return () => subscription.unsubscribe();
|
||||
}, [handleAuthChange]);
|
||||
|
||||
// 3. Real-time Database Subscriptions
|
||||
const eventsChannel = supabase
|
||||
.channel('events-sync')
|
||||
.on('postgres_changes', { event: '*', schema: 'public', table: 'events' }, () => {
|
||||
fetchAllRegistrations();
|
||||
})
|
||||
.subscribe();
|
||||
|
||||
const specialEventsChannel = supabase
|
||||
.channel('special-events-sync')
|
||||
.on('postgres_changes', { event: '*', schema: 'public', table: 'special_events' }, () => {
|
||||
fetchSpecialEvents();
|
||||
})
|
||||
.subscribe();
|
||||
|
||||
const announcementsChannel = supabase
|
||||
.channel('announcements-sync')
|
||||
.on('postgres_changes', { event: '*', schema: 'public', table: 'announcements' }, () => {
|
||||
fetchAnnouncements();
|
||||
})
|
||||
.subscribe();
|
||||
|
||||
return () => {
|
||||
subscription.unsubscribe();
|
||||
supabase.removeChannel(eventsChannel);
|
||||
supabase.removeChannel(specialEventsChannel);
|
||||
supabase.removeChannel(announcementsChannel);
|
||||
};
|
||||
}, [handleAuthChange, fetchAllRegistrations, fetchSpecialEvents, fetchAnnouncements]);
|
||||
|
||||
// NOTE: CreateEventForm already handles the Supabase insert.
|
||||
// This callback only refreshes the local events list.
|
||||
|
||||
Reference in New Issue
Block a user