feat: add publication

This commit is contained in:
ghost2023
2026-09-04 14:43:17 +03:00
parent ad791e2074
commit 0dd0e8d992
28 changed files with 1323 additions and 10 deletions

View File

@@ -1,4 +1,4 @@
import type { Freight, PaginatedResponse } from "@edr/types";
import type { Freight, PaginatedResponse, Publication } from "@edr/types";
import { QUERY_KEYS } from "@/constants/QUERY_KEYS";
import type { FleetResourceSlug } from "@/pages/fleet/config/resources";
@@ -191,6 +191,7 @@ import type { EimsInvoiceStatusView, EimsModeOfPayment, EimsReceiptView, EimsVer
import { invoicesService } from "./invoices.service";
import { dropdownSettingsService } from "./dropdownSettings.service";
import { fileUploadSettingsService } from "./fileUploadSettings.service";
import { publicationsService, type UpdatePublicationPayload } from "./publications.service";
import {
fleetService,
type FleetListFilters,
@@ -2934,6 +2935,52 @@ export const api = {
),
},
publications: {
list: endpoint<void, Publication[]>(
"publications",
"list",
publicationsService.list,
),
create: endpoint<
{ file: File; meta: UpdatePublicationPayload & { title: string }; onProgress?: (percent: number | null) => void },
Publication
>(
"publications",
"create",
({ file, meta, onProgress }) => publicationsService.create(file, meta, onProgress),
undefined,
() => [["publications"]],
),
update: endpoint<{ id: string; dto: UpdatePublicationPayload }, Publication>(
"publications",
"update",
({ id, dto }) => publicationsService.update(id, dto),
undefined,
() => [["publications"]],
),
replaceFile: endpoint<
{ id: string; file: File; onProgress?: (percent: number | null) => void },
Publication
>(
"publications",
"replaceFile",
({ id, file, onProgress }) => publicationsService.replaceFile(id, file, onProgress),
undefined,
() => [["publications"]],
),
remove: endpoint<{ id: string }, void>(
"publications",
"remove",
({ id }) => publicationsService.remove(id),
undefined,
() => [["publications"]],
),
},
dropdownSettings: {
list: endpoint<void, DropdownSetting[]>(
"dropdown-settings",

View File

@@ -0,0 +1,74 @@
import type { Publication } from "@edr/types";
import { api as client } from "../auth/http";
const BASE = "/publications";
export interface UpdatePublicationPayload {
title?: string;
description?: string;
category?: string;
sortOrder?: number;
published?: boolean;
}
/**
* The freight portal's public document library (/publications), managed here.
* Every write is multipart because create/replaceFile carry a real file — the
* client's response interceptor already unwraps the `{ success, data }`
* envelope, so each method stays a one-liner.
*/
export const publicationsService = {
async list(): Promise<Publication[]> {
const { data } = await client.get<Publication[]>(`${BASE}/admin`);
return data;
},
async create(
file: File,
meta: UpdatePublicationPayload & { title: string },
onProgress?: (percent: number | null) => void,
): Promise<Publication> {
const form = new FormData();
form.append("file", file);
Object.entries(meta).forEach(([key, value]) => {
if (value !== undefined) form.append(key, String(value));
});
const { data } = await client.post<Publication>(BASE, form, {
timeout: 2 * 60 * 1000,
onUploadProgress: (event) =>
onProgress?.(
event.total ? Math.round((event.loaded / event.total) * 100) : null,
),
});
return data;
},
async update(id: string, dto: UpdatePublicationPayload): Promise<Publication> {
const { data } = await client.patch<Publication>(`${BASE}/${id}`, dto);
return data;
},
async replaceFile(
id: string,
file: File,
onProgress?: (percent: number | null) => void,
): Promise<Publication> {
const form = new FormData();
form.append("file", file);
const { data } = await client.post<Publication>(`${BASE}/${id}/file`, form, {
timeout: 2 * 60 * 1000,
onUploadProgress: (event) =>
onProgress?.(
event.total ? Math.round((event.loaded / event.total) * 100) : null,
),
});
return data;
},
async remove(id: string): Promise<void> {
await client.delete(`${BASE}/${id}`);
},
};