Skip to content

Commit dc86832

Browse files
committed
refactor: Split application submission into student and client specific functions and streamline admin dashboard application display.
1 parent e554ae7 commit dc86832

File tree

3 files changed

+243
-178
lines changed

3 files changed

+243
-178
lines changed

client/src/lib/api.js

Lines changed: 106 additions & 75 deletions
Original file line numberDiff line numberDiff line change
@@ -1,31 +1,66 @@
11
import { supabase } from './supabase';
22

33
/**
4-
* Submit a student or client application
5-
* @param {Object} data - Form data
6-
* @param {'student' | 'client'} type - Application type
4+
* Submit a student application
5+
* @param {Object} formData - Student form data
76
* @returns {Promise<{success: boolean, error?: string, data?: Object}>}
87
*/
9-
export async function submitApplication(formData, type) {
8+
export async function submitStudentApplication(formData) {
109
try {
1110
const { data, error } = await supabase
12-
.from('applications')
13-
.insert([
14-
{
15-
type,
16-
form_data: formData,
17-
status: 'pending',
18-
created_at: new Date().toISOString(),
19-
}
20-
])
11+
.from('student_applications')
12+
.insert([{
13+
name: formData.name,
14+
email: formData.email,
15+
university: formData.university || '',
16+
linkedin: formData.linkedin || '',
17+
github: formData.github || '',
18+
skills: formData.skills || '',
19+
interests: formData.interests || '',
20+
source: formData.source || '',
21+
reason: formData.reason || '',
22+
impact: formData.impact || '',
23+
}])
2124
.select()
2225
.single();
2326

2427
if (error) throw error;
2528

2629
return { success: true, data };
2730
} catch (error) {
28-
console.error('Error submitting application:', error);
31+
console.error('Error submitting student application:', error);
32+
return { success: false, error: error.message };
33+
}
34+
}
35+
36+
/**
37+
* Submit a client brief
38+
* @param {Object} formData - Client form data
39+
* @returns {Promise<{success: boolean, error?: string, data?: Object}>}
40+
*/
41+
export async function submitClientBrief(formData) {
42+
try {
43+
const { data, error } = await supabase
44+
.from('client_briefs')
45+
.insert([{
46+
name: formData.name,
47+
company: formData.company || '',
48+
email: formData.email,
49+
phone: formData.phone || '',
50+
project_type: formData.projectType || '',
51+
description: formData.description || '',
52+
budget: formData.budget || '',
53+
timeline: formData.timeline || '',
54+
tech_stack: formData.techStack || '',
55+
}])
56+
.select()
57+
.single();
58+
59+
if (error) throw error;
60+
61+
return { success: true, data };
62+
} catch (error) {
63+
console.error('Error submitting client brief:', error);
2964
return { success: false, error: error.message };
3065
}
3166
}
@@ -157,55 +192,59 @@ export async function deleteProject(id) {
157192
// ============================================
158193

159194
/**
160-
* Get all applications with optional filters
161-
* @param {Object} filters - Optional filters (type, status)
195+
* Get all applications (merges student_applications + client_briefs)
196+
* @param {Object} filters - Optional filters (type)
162197
* @returns {Promise<{success: boolean, error?: string, data?: Array}>}
163198
*/
164199
export async function getApplications(filters = {}) {
165200
try {
166-
let query = supabase
167-
.from('applications')
168-
.select('*')
169-
.order('created_at', { ascending: false });
170-
171-
if (filters.type) {
172-
query = query.eq('type', filters.type);
173-
}
174-
if (filters.status) {
175-
query = query.eq('status', filters.status);
201+
let students = [];
202+
let clients = [];
203+
204+
// Fetch student applications unless filtering to clients only
205+
if (!filters.type || filters.type === 'student') {
206+
const { data, error } = await supabase
207+
.from('student_applications')
208+
.select('*')
209+
.order('created_at', { ascending: false });
210+
if (error) throw error;
211+
students = (data || []).map(row => ({
212+
...row,
213+
type: 'student',
214+
}));
176215
}
177216

178-
const { data, error } = await query;
217+
// Fetch client briefs unless filtering to students only
218+
if (!filters.type || filters.type === 'client') {
219+
const { data, error } = await supabase
220+
.from('client_briefs')
221+
.select('*')
222+
.order('created_at', { ascending: false });
223+
if (error) throw error;
224+
clients = (data || []).map(row => ({
225+
...row,
226+
type: 'client',
227+
}));
228+
}
179229

180-
if (error) throw error;
230+
// Merge and sort by created_at descending
231+
const merged = [...students, ...clients].sort(
232+
(a, b) => new Date(b.created_at) - new Date(a.created_at)
233+
);
181234

182-
return { success: true, data };
235+
return { success: true, data: merged };
183236
} catch (error) {
184237
console.error('Error fetching applications:', error);
185238
return { success: false, error: error.message };
186239
}
187240
}
188241

189242
/**
190-
* Update application status
191-
* @param {string} id - Application ID
192-
* @param {string} status - New status
193-
* @returns {Promise<{success: boolean, error?: string}>}
243+
* Update application status (no-op — tables don't have status columns yet)
194244
*/
195245
export async function updateApplicationStatus(id, status) {
196-
try {
197-
const { error } = await supabase
198-
.from('applications')
199-
.update({ status, updated_at: new Date().toISOString() })
200-
.eq('id', id);
201-
202-
if (error) throw error;
203-
204-
return { success: true };
205-
} catch (error) {
206-
console.error('Error updating application:', error);
207-
return { success: false, error: error.message };
208-
}
246+
console.warn('updateApplicationStatus: status columns not yet added to DB');
247+
return { success: false, error: 'Status tracking not yet available' };
209248
}
210249

211250
/**
@@ -255,26 +294,32 @@ export async function markContactAsRead(id) {
255294
*/
256295
export async function getDashboardStats() {
257296
try {
258-
// Get application counts
259-
const { data: applications, error: appError } = await supabase
260-
.from('applications')
261-
.select('type, status');
262-
263-
if (appError) throw appError;
297+
// Get student application count
298+
const { data: students, error: studentError } = await supabase
299+
.from('student_applications')
300+
.select('id');
301+
if (studentError) throw studentError;
302+
303+
// Get client brief count
304+
const { data: clients, error: clientError } = await supabase
305+
.from('client_briefs')
306+
.select('id');
307+
if (clientError) throw clientError;
264308

265309
// Get contact counts
266310
const { data: contacts, error: contactError } = await supabase
267311
.from('contacts')
268312
.select('is_read');
269-
270313
if (contactError) throw contactError;
271314

272-
// Calculate stats
315+
const studentCount = students?.length || 0;
316+
const clientCount = clients?.length || 0;
317+
273318
const stats = {
274-
totalApplications: applications?.length || 0,
275-
studentApplications: applications?.filter(a => a.type === 'student').length || 0,
276-
clientApplications: applications?.filter(a => a.type === 'client').length || 0,
277-
pendingApplications: applications?.filter(a => a.status === 'pending').length || 0,
319+
totalApplications: studentCount + clientCount,
320+
studentApplications: studentCount,
321+
clientApplications: clientCount,
322+
pendingApplications: studentCount + clientCount, // all are "pending" since no status column
278323
totalContacts: contacts?.length || 0,
279324
unreadContacts: contacts?.filter(c => !c.is_read).length || 0,
280325
};
@@ -287,25 +332,11 @@ export async function getDashboardStats() {
287332
}
288333

289334
/**
290-
* Update admin notes for an application
291-
* @param {string} id - Application ID
292-
* @param {string} notes - Admin notes
293-
* @returns {Promise<{success: boolean, error?: string}>}
335+
* Update admin notes (no-op — tables don't have admin_notes columns yet)
294336
*/
295337
export async function updateApplicationNotes(id, notes) {
296-
try {
297-
const { error } = await supabase
298-
.from('applications')
299-
.update({ admin_notes: notes, updated_at: new Date().toISOString() })
300-
.eq('id', id);
301-
302-
if (error) throw error;
303-
304-
return { success: true };
305-
} catch (error) {
306-
console.error('Error updating application notes:', error);
307-
return { success: false, error: error.message };
308-
}
338+
console.warn('updateApplicationNotes: admin_notes columns not yet added to DB');
339+
return { success: false, error: 'Notes tracking not yet available' };
309340
}
310341

311342
/**

client/src/pages/JoinPage.jsx

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ import {
1010
import Footer from '../components/Footer';
1111
import { supabase } from '../lib/supabase';
1212
import { useToast } from '../components/ui/Toast';
13-
import { submitApplication } from '../lib/api';
13+
import { submitStudentApplication, submitClientBrief } from '../lib/api';
1414

1515
export default function JoinUs() {
1616
const [selectedRole, setSelectedRole] = useState(null); // 'student' | 'client' | null
@@ -270,7 +270,7 @@ function StudentApplication({ onBack }) {
270270
}
271271

272272
setIsSubmitting(true);
273-
const result = await submitApplication(formData, 'student');
273+
const result = await submitStudentApplication(formData);
274274
setIsSubmitting(false);
275275

276276
if (result.success) {
@@ -486,7 +486,7 @@ function ClientApplication({ onBack }) {
486486
}
487487

488488
setIsSubmitting(true);
489-
const result = await submitApplication(formData, 'client');
489+
const result = await submitClientBrief(formData);
490490
setIsSubmitting(false);
491491

492492
if (result.success) {
@@ -531,8 +531,8 @@ function ClientApplication({ onBack }) {
531531
<div
532532
onClick={() => onClick(value)}
533533
className={`cursor-pointer p-4 rounded-xl border transition-all duration-200 flex items-center gap-3 ${selected === value
534-
? 'bg-blue-600/20 border-blue-500 text-white'
535-
: 'bg-white/5 border-white/10 text-white/50 hover:bg-white/10 hover:border-white/30'
534+
? 'bg-blue-600/20 border-blue-500 text-white'
535+
: 'bg-white/5 border-white/10 text-white/50 hover:bg-white/10 hover:border-white/30'
536536
}`}
537537
>
538538
<Icon size={20} className={selected === value ? 'text-blue-400' : 'text-white/40'} />

0 commit comments

Comments
 (0)