feat(phase-b): Supabase navigation store, snapshot service, auth wiring

navigationStore: rewritten off Neo4j db names — Supabase whiteboard_rooms table,
  setAuthInfo(token, userId) pattern, auto-creates default room per context on first use
snapshotService: rewritten to Supabase Storage REST (/storage/v1/object/authenticated/cc.users/…),
  setAccessToken() instance method, static methods take accessToken not dbName
AuthContext/NeoUserContext: auth injected into nav store, no Neo4j db names required
singlePlayerPage: loadNodeData no longer calls Neo4j; snapshot wired via accessToken
navigation types: NeoGraphNode updated for Supabase-backed tree structure
transcriptionStore/Service: getSession() removed, accessToken via AuthContext
LLMConfigModal: auth context wiring fixes
GraphNavigator/GraphSidebar: updated nav components

Co-Authored-By: Claude Sonnet 4.6 <[email protected]>
This commit is contained in:
2026-05-26 01:25:15 +01:00
co-authored by Claude Sonnet 4.6
parent 3a65cf436b
commit b0c7758135
11 changed files with 1641 additions and 1892 deletions
+28 -32
View File
@@ -3,7 +3,6 @@ import { useAuth } from './AuthContext';
import { useUser } from './UserContext';
import { logger } from '../debugConfig';
import { CCUserNodeProps, CCCalendarNodeProps, CCUserTeacherTimetableNodeProps } from '../utils/tldraw/cc-base/cc-graph/cc-graph-types';
import { DatabaseNameService } from '../services/graph/databaseNameService';
import { CalendarStructure, WorkerStructure } from '../types/navigation';
import { useNavigationStore } from '../stores/navigationStore';
@@ -131,7 +130,7 @@ const NeoUserContext = createContext<NeoUserContextType>({
});
export const NeoUserProvider: React.FC<{ children: ReactNode }> = ({ children }) => {
const { user } = useAuth();
const { user, accessToken } = useAuth();
const { profile, isInitialized: isUserInitialized } = useUser();
const navigationStore = useNavigationStore();
@@ -215,12 +214,9 @@ export const NeoUserProvider: React.FC<{ children: ReactNode }> = ({ children })
setIsLoading(true);
setError(null);
// Set database names
const userDb = profile.user_db_name || (user?.email ?
DatabaseNameService.getStoredUserDatabase() || null : null);
if (!userDb) {
throw new Error('No user database name available');
// Inject auth into navigation store so Supabase queries work
if (user?.id && accessToken) {
navigationStore.setAuthInfo(accessToken, user.id);
}
// Initialize user node in profile context
@@ -236,7 +232,7 @@ export const NeoUserProvider: React.FC<{ children: ReactNode }> = ({ children })
main: 'profile',
base: 'profile',
extended: 'overview'
}, userDb, profile.school_db_name),
}, null, null),
switchTimeout
]);
@@ -271,9 +267,9 @@ export const NeoUserProvider: React.FC<{ children: ReactNode }> = ({ children })
// Continue without user node - this is not critical for basic functionality
}
// Set final state
setUserDbName(userDb);
setWorkerDbName(profile.school_db_name);
// Set final state — userDbName signals auth availability for UI guards
setUserDbName(user?.id || null);
setWorkerDbName(null);
setIsInitialized(true);
setIsLoading(false);
initializationRef.current.isComplete = true;
@@ -294,13 +290,13 @@ export const NeoUserProvider: React.FC<{ children: ReactNode }> = ({ children })
// Calendar Navigation Functions
const navigateToDay = async (id: string) => {
if (!userDbName) return;
if (!user?.id) return;
setIsLoading(true);
try {
await navigationStore.switchContext({
base: 'calendar',
extended: 'day'
}, userDbName, workerDbName);
}, null, null);
const node = navigationStore.context.node;
if (node?.data) {
@@ -334,13 +330,13 @@ export const NeoUserProvider: React.FC<{ children: ReactNode }> = ({ children })
};
const navigateToWeek = async (id: string) => {
if (!userDbName) return;
if (!user?.id) return;
setIsLoading(true);
try {
await navigationStore.switchContext({
base: 'calendar',
extended: 'week'
}, userDbName, workerDbName);
}, null, null);
const node = navigationStore.context.node;
if (node?.data) {
@@ -374,13 +370,13 @@ export const NeoUserProvider: React.FC<{ children: ReactNode }> = ({ children })
};
const navigateToMonth = async (id: string) => {
if (!userDbName) return;
if (!user?.id) return;
setIsLoading(true);
try {
await navigationStore.switchContext({
base: 'calendar',
extended: 'month'
}, userDbName, workerDbName);
}, null, null);
const node = navigationStore.context.node;
if (node?.data) {
@@ -414,13 +410,13 @@ export const NeoUserProvider: React.FC<{ children: ReactNode }> = ({ children })
};
const navigateToYear = async (id: string) => {
if (!userDbName) return;
if (!user?.id) return;
setIsLoading(true);
try {
await navigationStore.switchContext({
base: 'calendar',
extended: 'year'
}, userDbName, workerDbName);
}, null, null);
const node = navigationStore.context.node;
if (node?.data) {
@@ -455,13 +451,13 @@ export const NeoUserProvider: React.FC<{ children: ReactNode }> = ({ children })
// Worker Navigation Functions
const navigateToTimetable = async (id: string) => {
if (!userDbName) return;
if (!user?.id) return;
setIsLoading(true);
try {
await navigationStore.switchContext({
base: 'teaching',
extended: 'timetable'
}, userDbName, workerDbName);
}, null, null);
const node = navigationStore.context.node;
if (node?.data) {
@@ -492,13 +488,13 @@ export const NeoUserProvider: React.FC<{ children: ReactNode }> = ({ children })
};
const navigateToJournal = async (id: string) => {
if (!userDbName) return;
if (!user?.id) return;
setIsLoading(true);
try {
await navigationStore.switchContext({
base: 'teaching',
extended: 'journal'
}, userDbName, workerDbName);
}, null, null);
const node = navigationStore.context.node;
if (node?.data) {
@@ -529,13 +525,13 @@ export const NeoUserProvider: React.FC<{ children: ReactNode }> = ({ children })
};
const navigateToPlanner = async (id: string) => {
if (!userDbName) return;
if (!user?.id) return;
setIsLoading(true);
try {
await navigationStore.switchContext({
base: 'teaching',
extended: 'planner'
}, userDbName, workerDbName);
}, null, null);
const node = navigationStore.context.node;
if (node?.data) {
@@ -566,14 +562,14 @@ export const NeoUserProvider: React.FC<{ children: ReactNode }> = ({ children })
};
const navigateToClass = async (id: string) => {
if (!userDbName) return;
if (!user?.id) return;
setIsLoading(true);
try {
await navigationStore.switchContext({
base: 'teaching',
extended: 'classes'
}, userDbName, workerDbName);
await navigationStore.navigate(id, userDbName);
}, null, null);
await navigationStore.navigate(id, '');
const node = navigationStore.context.node;
if (node?.data) {
@@ -604,14 +600,14 @@ export const NeoUserProvider: React.FC<{ children: ReactNode }> = ({ children })
};
const navigateToLesson = async (id: string) => {
if (!userDbName) return;
if (!user?.id) return;
setIsLoading(true);
try {
await navigationStore.switchContext({
base: 'teaching',
extended: 'lessons'
}, userDbName, workerDbName);
await navigationStore.navigate(id, userDbName);
}, null, null);
await navigationStore.navigate(id, '');
const node = navigationStore.context.node;
if (node?.data) {