mirror of
https://git.meshkee.com/novintrades/website.git
synced 2026-08-11 20:50:58 +04:30
Initial commit: NovinTrades website monorepo.
Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -0,0 +1,202 @@
|
||||
import { api, ApiError } from "./api";
|
||||
import { assertClientImageSize } from "./image";
|
||||
import type {
|
||||
AuthUser,
|
||||
Blog,
|
||||
Brand,
|
||||
BrandContact,
|
||||
Category,
|
||||
Reportage,
|
||||
VerificationStatus,
|
||||
} from "./types";
|
||||
|
||||
export function login(email: string, password: string) {
|
||||
return api<{ user: AuthUser }>("/api/auth/login", {
|
||||
method: "POST",
|
||||
body: JSON.stringify({ email, password }),
|
||||
});
|
||||
}
|
||||
|
||||
export function listCategories() {
|
||||
return api<Category[]>("/api/categories");
|
||||
}
|
||||
|
||||
export function listBlogs() {
|
||||
return api<Blog[]>("/api/blogs");
|
||||
}
|
||||
|
||||
export function getBlog(id: string) {
|
||||
return api<Blog>(`/api/blogs/${id}`);
|
||||
}
|
||||
|
||||
export function createBlog(input: {
|
||||
title: string;
|
||||
abstract?: string;
|
||||
content?: string;
|
||||
imageUrl?: string | null;
|
||||
tags?: string[];
|
||||
categoryIds?: string[];
|
||||
authorId: string;
|
||||
verificationStatus?: VerificationStatus;
|
||||
}) {
|
||||
return api<Blog>("/api/blogs", {
|
||||
method: "POST",
|
||||
body: JSON.stringify(input),
|
||||
});
|
||||
}
|
||||
|
||||
export function updateBlog(
|
||||
id: string,
|
||||
input: {
|
||||
title?: string;
|
||||
abstract?: string;
|
||||
content?: string;
|
||||
imageUrl?: string | null;
|
||||
tags?: string[];
|
||||
categoryIds?: string[];
|
||||
verificationStatus?: VerificationStatus;
|
||||
publishedAt?: string | null;
|
||||
},
|
||||
) {
|
||||
return api<Blog>(`/api/blogs/${id}`, {
|
||||
method: "PATCH",
|
||||
body: JSON.stringify(input),
|
||||
});
|
||||
}
|
||||
|
||||
export function listReportages() {
|
||||
return api<Reportage[]>("/api/reportages");
|
||||
}
|
||||
|
||||
export function getReportage(id: string) {
|
||||
return api<Reportage>(`/api/reportages/${id}`);
|
||||
}
|
||||
|
||||
export function createReportage(input: {
|
||||
title: string;
|
||||
businessOwner: string;
|
||||
abstract?: string;
|
||||
content?: string;
|
||||
imageUrl?: string | null;
|
||||
tags?: string[];
|
||||
categoryIds?: string[];
|
||||
authorId: string;
|
||||
verificationStatus?: VerificationStatus;
|
||||
}) {
|
||||
return api<Reportage>("/api/reportages", {
|
||||
method: "POST",
|
||||
body: JSON.stringify(input),
|
||||
});
|
||||
}
|
||||
|
||||
export function updateReportage(
|
||||
id: string,
|
||||
input: {
|
||||
title?: string;
|
||||
businessOwner?: string;
|
||||
abstract?: string;
|
||||
content?: string;
|
||||
imageUrl?: string | null;
|
||||
tags?: string[];
|
||||
categoryIds?: string[];
|
||||
verificationStatus?: VerificationStatus;
|
||||
publishedAt?: string | null;
|
||||
},
|
||||
) {
|
||||
return api<Reportage>(`/api/reportages/${id}`, {
|
||||
method: "PATCH",
|
||||
body: JSON.stringify(input),
|
||||
});
|
||||
}
|
||||
|
||||
export function listBrands() {
|
||||
return api<Brand[]>("/api/brands");
|
||||
}
|
||||
|
||||
export function getBrand(id: string) {
|
||||
return api<Brand>(`/api/brands/${id}`);
|
||||
}
|
||||
|
||||
export function createBrand(input: {
|
||||
title: string;
|
||||
abstract?: string;
|
||||
content?: string;
|
||||
imageUrl?: string | null;
|
||||
galleryUrls?: string[];
|
||||
tags?: string[];
|
||||
country: string;
|
||||
city?: string;
|
||||
address?: string;
|
||||
contacts?: BrandContact[];
|
||||
categoryIds?: string[];
|
||||
authorId: string;
|
||||
verificationStatus?: VerificationStatus;
|
||||
}) {
|
||||
return api<Brand>("/api/brands", {
|
||||
method: "POST",
|
||||
body: JSON.stringify(input),
|
||||
});
|
||||
}
|
||||
|
||||
export function updateBrand(
|
||||
id: string,
|
||||
input: {
|
||||
title?: string;
|
||||
abstract?: string;
|
||||
content?: string;
|
||||
imageUrl?: string | null;
|
||||
galleryUrls?: string[];
|
||||
tags?: string[];
|
||||
country?: string;
|
||||
city?: string;
|
||||
address?: string;
|
||||
contacts?: BrandContact[];
|
||||
categoryIds?: string[];
|
||||
verificationStatus?: VerificationStatus;
|
||||
publishedAt?: string | null;
|
||||
},
|
||||
) {
|
||||
return api<Brand>(`/api/brands/${id}`, {
|
||||
method: "PATCH",
|
||||
body: JSON.stringify(input),
|
||||
});
|
||||
}
|
||||
|
||||
export async function uploadImage(
|
||||
file: Blob,
|
||||
folder: string,
|
||||
): Promise<{ url: string; key: string; size: number }> {
|
||||
assertClientImageSize(file.size);
|
||||
|
||||
const form = new FormData();
|
||||
const filename =
|
||||
file instanceof File && file.name
|
||||
? file.name
|
||||
: `image.${file.type.includes("png") ? "png" : "jpg"}`;
|
||||
form.append("file", file, filename);
|
||||
|
||||
const response = await fetch(
|
||||
`/api/uploads?folder=${encodeURIComponent(folder)}`,
|
||||
{
|
||||
method: "POST",
|
||||
body: form,
|
||||
},
|
||||
);
|
||||
|
||||
if (!response.ok) {
|
||||
let message = "Upload failed";
|
||||
try {
|
||||
const data = (await response.json()) as { error?: string };
|
||||
if (data.error) message = data.error;
|
||||
} catch {
|
||||
// ignore
|
||||
}
|
||||
throw new ApiError(response.status, message);
|
||||
}
|
||||
|
||||
return (await response.json()) as {
|
||||
url: string;
|
||||
key: string;
|
||||
size: number;
|
||||
};
|
||||
}
|
||||
Reference in New Issue
Block a user