A deployable markdown editor that connects with your self hosted files and lets you edit in a beautiful interface
0
fork

Configure Feed

Select the types of activity you want to include in your feed.

Add user repos API endpoint and update DashboardApp to use it

Backend:
- Add GET /api/user/repos endpoint in router.go:63
- Add GetUserRepos handler in auth.go:327

Frontend:
- Add UserRepo type to api.ts
- Add getUserRepos API function to auth.ts
- Add useUserRepos hook to useAuth.ts
- Update DashboardApp to:
- Fetch user repos from API
- Use repos from user_repos table as fallback
- Load most recent repo automatically on login

This ensures the dashboard loads the user's most recently used repo
from the user_repos table after login, not just from URL params.

+75 -10
+24
backend/internal/api/handlers/auth.go
··· 323 323 w.WriteHeader(http.StatusNoContent) 324 324 } 325 325 326 + // GetUserRepos returns all repositories associated with the current user 327 + func (h *AuthHandler) GetUserRepos(w http.ResponseWriter, r *http.Request) { 328 + session, err := auth.GetSession(r) 329 + if err != nil { 330 + http.Error(w, "Unauthorized", http.StatusUnauthorized) 331 + return 332 + } 333 + 334 + userID, ok := auth.GetUserID(session) 335 + if !ok { 336 + http.Error(w, "Unauthorized", http.StatusUnauthorized) 337 + return 338 + } 339 + 340 + repos, err := h.db.GetUserRepos(userID) 341 + if err != nil { 342 + http.Error(w, "Failed to get user repositories", http.StatusInternalServerError) 343 + return 344 + } 345 + 346 + w.Header().Set("Content-Type", "application/json") 347 + json.NewEncoder(w).Encode(repos) 348 + } 349 + 326 350 func (h *AuthHandler) Logout(w http.ResponseWriter, r *http.Request) { 327 351 session, err := auth.GetSession(r) 328 352 if err != nil {
+1
backend/internal/api/router.go
··· 60 60 61 61 r.Get("/api/auth/user", authHandler.GetCurrentUser) 62 62 r.Post("/api/auth/logout", authHandler.Logout) 63 + r.Get("/api/user/repos", authHandler.GetUserRepos) 63 64 r.Post("/api/user/repo", authHandler.UpdateLastRepo) 64 65 65 66 // Repository routes
+26 -9
frontend/src/components/dashboard/DashboardApp.tsx
··· 5 5 import { FileTree } from './FileTree'; 6 6 import { EditorContainer } from '../editor/EditorContainer'; 7 7 import { useFiles } from '../../lib/hooks/useRepos'; 8 - import { useCurrentUser } from '../../lib/hooks/useAuth'; 8 + import { useCurrentUser, useUserRepos } from '../../lib/hooks/useAuth'; 9 9 import { Loading } from '../ui/Loading'; 10 10 import { EmptyState } from '../ui/EmptyState'; 11 11 ··· 44 44 } | null>(null); 45 45 const [selectedFile, setSelectedFile] = useState<string | null>(null); 46 46 const { data: user, isLoading: userLoading } = useCurrentUser(); 47 + const { data: userRepos, isLoading: reposLoading } = useUserRepos(); 47 48 48 - // Check for last_repo or URL params and redirect if needed 49 + // Check for repo from URL params, user.last_repo, or user_repos table 49 50 useEffect(() => { 50 - console.log('[DEBUG] Dashboard useEffect running, userLoading:', userLoading, 'user:', user); 51 + console.log('[DEBUG] Dashboard useEffect running'); 52 + console.log('[DEBUG] userLoading:', userLoading, 'reposLoading:', reposLoading); 53 + console.log('[DEBUG] user:', user?.last_repo, 'userRepos:', userRepos?.length); 51 54 52 - if (userLoading || !user) { 53 - console.log('[DEBUG] Still loading user or no user, returning early'); 55 + if (userLoading || reposLoading || !user) { 56 + console.log('[DEBUG] Still loading, returning early'); 54 57 return; 55 58 } 56 59 ··· 60 63 console.log('[DEBUG] URL repo param:', repoParam); 61 64 62 65 if (repoParam) { 63 - // Parse repo from URL (format: owner/repo) 64 66 const [owner, repo] = repoParam.split('/'); 65 67 if (owner && repo) { 66 68 console.log('[DEBUG] Setting repo from URL param:', owner, repo); ··· 69 71 } 70 72 } 71 73 72 - // Check user's last_repo 74 + // Check user's last_repo from users table 73 75 console.log('[DEBUG] Checking user.last_repo:', user.last_repo); 74 76 if (user.last_repo) { 75 77 const [owner, repo] = user.last_repo.split('/'); ··· 80 82 } 81 83 } 82 84 85 + // Check user_repos table (sorted by most recent) 86 + console.log('[DEBUG] Checking user_repos table, count:', userRepos?.length); 87 + if (userRepos && userRepos.length > 0) { 88 + // Get the most recently used repo (first in the list from API) 89 + const mostRecentRepo = userRepos[0]; 90 + console.log('[DEBUG] Most recent repo from user_repos:', mostRecentRepo.repo_name); 91 + 92 + const [owner, repo] = mostRecentRepo.repo_name.split('/'); 93 + if (owner && repo) { 94 + console.log('[DEBUG] Setting repo from user_repos table:', owner, repo); 95 + setRepoConfig({ owner, repo, folder: '' }); 96 + return; 97 + } 98 + } 99 + 83 100 // No repo configured, redirect to select-repo page 84 101 console.log('[DEBUG] No repo found, redirecting to /select-repo'); 85 102 window.location.href = '/select-repo'; 86 - }, [user, userLoading]); 103 + }, [user, userLoading, userRepos, reposLoading]); 87 104 88 105 const { data: filesData, isLoading: filesLoading } = useFiles( 89 106 repoConfig?.owner || '', ··· 93 110 ['md', 'mdx'] 94 111 ); 95 112 96 - if (userLoading) { 113 + if (userLoading || reposLoading) { 97 114 return ( 98 115 <div className="min-h-screen bg-gray-50 flex items-center justify-center"> 99 116 <Loading size="lg" text="Loading your dashboard..." />
+6 -1
frontend/src/lib/api/auth.ts
··· 1 1 import { apiClient } from './client'; 2 - import type { User } from '../types/api'; 2 + import type { User, UserRepo } from '../types/api'; 3 3 4 4 export const authApi = { 5 5 getCurrentUser: async (): Promise<User> => { 6 6 const { data } = await apiClient.get<User>('/api/auth/user'); 7 + return data; 8 + }, 9 + 10 + getUserRepos: async (): Promise<UserRepo[]> => { 11 + const { data } = await apiClient.get<UserRepo[]>('/api/user/repos'); 7 12 return data; 8 13 }, 9 14
+8
frontend/src/lib/hooks/useAuth.ts
··· 9 9 }); 10 10 } 11 11 12 + export function useUserRepos() { 13 + return useQuery({ 14 + queryKey: ['userRepos'], 15 + queryFn: authApi.getUserRepos, 16 + retry: false, 17 + }); 18 + } 19 + 12 20 export function useLogout() { 13 21 const queryClient = useQueryClient(); 14 22
+10
frontend/src/lib/types/api.ts
··· 6 6 last_repo?: string; 7 7 } 8 8 9 + export interface UserRepo { 10 + id: number; 11 + user_id: number; 12 + repo_name: string; 13 + repo_link: string; 14 + last_used_at: string; 15 + created_at: string; 16 + updated_at: string; 17 + } 18 + 9 19 export interface Repository { 10 20 id: number; 11 21 full_name: string;