Initial commit

This commit is contained in:
2026-07-22 17:00:56 -04:00
commit 0f2d6bb738
33 changed files with 6997 additions and 0 deletions
+168
View File
@@ -0,0 +1,168 @@
import { initializeApp, getApps, getApp } from 'firebase/app';
import {
getAuth,
signInWithPopup,
GoogleAuthProvider,
onAuthStateChanged,
User,
signOut
} from 'firebase/auth';
import firebaseConfig from '../../firebase-applet-config.json';
import { JobApplication } from '../types';
const app = getApps().length === 0 ? initializeApp(firebaseConfig) : getApp();
export const auth = getAuth(app);
const provider = new GoogleAuthProvider();
// Workspace Scopes
provider.addScope('https://www.googleapis.com/auth/spreadsheets');
provider.addScope('https://www.googleapis.com/auth/drive');
provider.addScope('https://www.googleapis.com/auth/documents');
let isSigningIn = false;
let cachedAccessToken: string | null = null;
export const initAuthListener = (
onSuccess: (user: User, token: string) => void,
onFailure: () => void
) => {
return onAuthStateChanged(auth, async (user) => {
if (user) {
if (cachedAccessToken) {
onSuccess(user, cachedAccessToken);
} else if (!isSigningIn) {
// If logged in without token in memory (e.g., page refresh), trigger quick re-auth if needed
onFailure();
}
} else {
cachedAccessToken = null;
onFailure();
}
});
};
export const googleWorkspaceSignIn = async (): Promise<{ user: User; accessToken: string } | null> => {
try {
isSigningIn = true;
const result = await signInWithPopup(auth, provider);
const credential = GoogleAuthProvider.credentialFromResult(result);
if (!credential?.accessToken) {
throw new Error('Failed to obtain Google access token');
}
cachedAccessToken = credential.accessToken;
return { user: result.user, accessToken: cachedAccessToken };
} catch (error) {
console.error('Google Workspace Sign-in Error:', error);
throw error;
} finally {
isSigningIn = false;
}
};
export const getCachedAccessToken = (): string | null => {
return cachedAccessToken;
};
export const googleSignOut = async (): Promise<void> => {
await signOut(auth);
cachedAccessToken = null;
};
// Workspace Action Handlers
export async function exportApplicationsToGoogleSheets(
applications: JobApplication[],
accessToken?: string
): Promise<{ spreadsheetId: string; spreadsheetUrl: string }> {
const token = accessToken || cachedAccessToken;
const res = await fetch('/api/workspace/sheets/export', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
...(token ? { Authorization: `Bearer ${token}` } : {})
},
body: JSON.stringify({ applications, accessToken: token })
});
const data = await res.json();
if (!data.success) {
throw new Error(data.error || 'Failed to export applications to Google Sheets');
}
return { spreadsheetId: data.spreadsheetId, spreadsheetUrl: data.spreadsheetUrl };
}
export async function createTailoredGoogleDoc(
title: string,
content: string,
docType: 'resume' | 'coverLetter' | 'note',
accessToken?: string
): Promise<{ documentId: string; documentUrl: string }> {
const token = accessToken || cachedAccessToken;
const res = await fetch('/api/workspace/docs/create', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
...(token ? { Authorization: `Bearer ${token}` } : {})
},
body: JSON.stringify({ title, content, docType, accessToken: token })
});
const data = await res.json();
if (!data.success) {
throw new Error(data.error || 'Failed to create Google Doc');
}
return { documentId: data.documentId, documentUrl: data.documentUrl };
}
export async function uploadFileToGoogleDrive(
fileName: string,
fileContent: string,
mimeType: string = 'text/plain',
accessToken?: string
): Promise<{ fileId: string; driveUrl: string }> {
const token = accessToken || cachedAccessToken;
const res = await fetch('/api/workspace/drive/upload', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
...(token ? { Authorization: `Bearer ${token}` } : {})
},
body: JSON.stringify({ fileName, fileContent, mimeType, accessToken: token })
});
const data = await res.json();
if (!data.success) {
throw new Error(data.error || 'Failed to upload file to Google Drive');
}
return { fileId: data.fileId, driveUrl: data.driveUrl };
}
export async function listGoogleDriveWorkspaceFiles(accessToken?: string): Promise<any[]> {
const token = accessToken || cachedAccessToken;
const res = await fetch('/api/workspace/drive/files', {
headers: {
...(token ? { Authorization: `Bearer ${token}` } : {})
}
});
const data = await res.json();
return data.files || [];
}
export async function saveGoogleKeepNote(
title: string,
content: string,
color: string = 'DEFAULT',
accessToken?: string
): Promise<{ noteId: string; title: string; content: string; color: string; timestamp: string }> {
const token = accessToken || cachedAccessToken;
const res = await fetch('/api/workspace/keep/create', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
...(token ? { Authorization: `Bearer ${token}` } : {})
},
body: JSON.stringify({ title, content, color, accessToken: token })
});
const data = await res.json();
if (!data.success) {
throw new Error(data.error || 'Failed to create Keep note');
}
return data.note;
}