File size: 2,671 Bytes
fcd4478
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
import { auth } from '@/auth';
import { redirect } from 'next/navigation';
import { v5 as uuidV5 } from 'uuid';

interface ApiResponse<T> {
	code: number; // code from server 0
	message: string;
	data: T;
}

const clefApiBuilder = <Params extends object | void, Resp>(path: string) => {
	return async (params: Params): Promise<Resp> => {
		const session = await auth();
		if (!session?.user?.email) {
			redirect('/');
		}

		const adminEmail = session.user.email;
		const sessionUser = {
			id: uuidV5(adminEmail, uuidV5.URL),
			orgId: '-1024',
			email: adminEmail,
			username: adminEmail.split('@')[0],
			userRole: 'adminPortal',
			bucket: 'fake_bucket',
		};

		const baseURL = `https://app.dev.landing.ai/${path}`;

		// Create a URL object with query params
		const url = new URL(baseURL);
		Object.entries(params ?? {}).forEach(([key, value]) =>
			url.searchParams.append(key, value),
		);

		const res = await fetch(url.toString(), {
			headers: {
				'Content-Type': 'application/json',
				sessionuser: JSON.stringify(sessionUser),
				'X-ROUTE': 'mingruizhang-landing',
			},
		});

		if (!res.ok) {
			console.error('ERROR: fetch data failure', res.status);
			// This will activate the closest `error.js` Error Boundary
			throw new Error('Failed to fetch data');
		}
		const { data }: ApiResponse<Resp> = await res.json();
		return data;
	};
};

export type ProjectBaseInfo = {
	id: number;
	name: string;
	created_at: Date;
	organization: {
		id: number;
		name: string;
	};
};
/**
 * Fetch recent projects from all organizations from past 30 days, excluding
 * 1. test organization such as bdd, cypress
 * 2. internal organization such as landing, landing-ai, orgId=1
 * 3. projects not containing media or only contain sample media
 * @author https://github.com/landing-ai/landing-platform/blob/mingrui-04-08-meaningful-project/packages/server-clef/src/main_app/controllers/admin/get_admin_meaningful_project_controller.ts
 */
export const fetchRecentProjectList = clefApiBuilder<void, ProjectBaseInfo[]>(
	'api/admin/projects/recent',
);

export type MediaDetails = {
	id: number;
	name: string;
	path: string;
	url: string;
	projectId: number;
	thumbnails: [string, string, string];
	properties: {
		width: number;
		height: number;
		format: string;
		orientation: number;
	};
};
/**
 * Randomly fetch 10 media from a given project
 * @author https://github.com/landing-ai/landing-platform/blob/mingrui-04-08-meaningful-project/packages/server-clef/src/main_app/controllers/admin/get_admin_meaningful_project_controller.ts
 */
export const fetchProjectMedia = clefApiBuilder<
	{ projectId: number },
	MediaDetails[]
>('api/admin/project/media');