All files / src/components/projects api-adapters.ts

97.14% Statements 34/35
100% Branches 0/0
97.14% Functions 34/35
97.14% Lines 34/35

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114                  19x   1x   1x 1x   1x   1x             1x 1x   1x 1x 1x   1x     1x 1x   1x   1x                       25x   1x 1x 1x 1x 1x                                           1x                       16x     3x 1x   1x 1x 1x   1x     1x 1x   1x   1x      
// API adapters that normalize pro and admin APIs behind a common interface
import { proApi, adminApi } from "../../lib/api";
import type { ProjectApiAdapter } from "./types";
 
/**
 * Creates an API adapter for pro context
 * All operations are scoped to the pro's own data
 */
export function createProApiAdapter(proId: string): ProjectApiAdapter {
	return {
		// Project operations
		getProject: (projectId) => proApi.getProject(proId, projectId),
		updateProject: (projectId, data) =>
			proApi.updateProject(proId, projectId, data),
		deleteProject: (projectId) => proApi.deleteProject(proId, projectId),
		publishProject: (projectId) =>
			proApi.publishProject(proId, projectId),
		archiveProject: (projectId) =>
			proApi.archiveProject(proId, projectId),
		// `POST …/unarchive` sets `draft` from either `published` or
		// `archived`, so one route backs both "Move to draft" and "Unarchive".
		unarchiveProject: (projectId) =>
			proApi.unarchiveProject(proId, projectId),
 
		// Room operations - full support for pros
		getRooms: (projectId) => proApi.getRooms(proId, projectId),
		getRoom: (roomId) => proApi.getRoom(proId, roomId),
		createRoom: (projectId, data) =>
			proApi.createRoom(proId, projectId, data),
		updateRoom: (roomId, data) => proApi.updateRoom(proId, roomId, data),
		deleteRoom: (roomId) => proApi.deleteRoom(proId, roomId),
		reorderRooms: (projectId, roomIds) =>
			proApi.reorderRooms(proId, projectId, roomIds),
 
		// Media operations - full support for pros
		getMediaByRoom: (roomId) => proApi.getMediaByRoom(proId, roomId),
		deleteMedia: (mediaId) => proApi.deleteMedia(proId, mediaId),
		reorderMedia: (roomId, mediaIds) =>
			proApi.reorderMedia(proId, roomId, mediaIds),
		setRoomCover: (roomId, mediaId) =>
			proApi.setRoomCover(proId, roomId, mediaId),
 
		// Pro info - not needed for pro context (they have usePro)
		getPro: undefined,
	};
}
 
/**
 * Creates an API adapter for admin context
 * Admins can manage any project across all pros
 */
export function createAdminApiAdapter(): ProjectApiAdapter {
	return {
		// Project operations - admin doesn't need proId
		getProject: (projectId) => adminApi.getProject(projectId),
		updateProject: (projectId, data) => adminApi.updateProject(projectId, data),
		deleteProject: (projectId) => adminApi.deleteProject(projectId),
		publishProject: (projectId) => adminApi.publishProject(projectId),
		archiveProject: (projectId) => adminApi.archiveProject(projectId),
		// The admin API has no unarchive route. Left undefined rather than
		// faked through a status PUT: `project-actions.ts` prints the two
		// affected menu items with a reason, which is honest.
		unarchiveProject: undefined,
 
		// Room operations - admin uses pro API with project's proId
		// These will be set dynamically after project is loaded
		getRooms: undefined,
		getRoom: undefined,
		createRoom: undefined,
		updateRoom: undefined,
		deleteRoom: undefined,
		reorderRooms: undefined,
 
		// Media operations - same as rooms
		getMediaByRoom: undefined,
		deleteMedia: undefined,
		reorderMedia: undefined,
		setRoomCover: undefined,
 
		// Pro info - admin needs to look up pro separately
		getPro: (proId) => adminApi.getPro(proId),
	};
}
 
/**
 * Enhances an admin adapter with room operations using the project's proId
 * Call this after loading the project to enable room management
 */
export function enhanceAdminAdapterWithRooms(
	adapter: ProjectApiAdapter,
	proId: string,
): ProjectApiAdapter {
	return {
		...adapter,
		// Add room operations using pro API
		getRooms: (projectId) => proApi.getRooms(proId, projectId),
		getRoom: (roomId) => proApi.getRoom(proId, roomId),
		createRoom: (projectId, data) =>
			proApi.createRoom(proId, projectId, data),
		updateRoom: (roomId, data) => proApi.updateRoom(proId, roomId, data),
		deleteRoom: (roomId) => proApi.deleteRoom(proId, roomId),
		reorderRooms: (projectId, roomIds) =>
			proApi.reorderRooms(proId, projectId, roomIds),
 
		// Add media operations
		getMediaByRoom: (roomId) => proApi.getMediaByRoom(proId, roomId),
		deleteMedia: (mediaId) => proApi.deleteMedia(proId, mediaId),
		reorderMedia: (roomId, mediaIds) =>
			proApi.reorderMedia(proId, roomId, mediaIds),
		setRoomCover: (roomId, mediaId) =>
			proApi.setRoomCover(proId, roomId, mediaId),
	};
}