feat(old-items): complete reuse workflow and refine miniapp home

This commit is contained in:
2026-08-15 16:38:30 +08:00
parent 65d23eab4a
commit f3737c80be
94 changed files with 7880 additions and 215 deletions
@@ -0,0 +1,57 @@
import type {
ActivateOldItemRewardConfigRequest,
AdjustOldItemPointsRequest,
OldItemCertificateItem,
OldItemPointAccountItem,
OldItemPointEntryItem,
OldItemRewardConfig,
} from '@lehuo/contracts';
import { apiRequest } from './api-client';
import type { Page } from './old-items';
export const getOldItemRewardConfig = () =>
apiRequest<{ config: OldItemRewardConfig; usesDefault: boolean }>(
'/api/v1/admin/old-items/reward-config',
);
export const activateOldItemRewardConfig = (
input: Omit<ActivateOldItemRewardConfigRequest, 'clientRequestId'>,
) =>
apiRequest<{ config: OldItemRewardConfig }>('/api/v1/admin/old-items/reward-config/activate', {
method: 'POST',
body: JSON.stringify({ ...input, clientRequestId: crypto.randomUUID() }),
});
export const listOldItemPointAccounts = () =>
apiRequest<Page<OldItemPointAccountItem>>(
'/api/v1/admin/old-items/reward-accounts?page=1&pageSize=100',
);
export const adjustOldItemPoints = (
userPublicId: string,
input: Omit<AdjustOldItemPointsRequest, 'clientRequestId'>,
) =>
apiRequest<{ entry: OldItemPointEntryItem }>(
`/api/v1/admin/old-items/reward-accounts/${userPublicId}/adjust`,
{
method: 'POST',
body: JSON.stringify({ ...input, clientRequestId: crypto.randomUUID() }),
},
);
export const listOldItemCertificates = () =>
apiRequest<Page<OldItemCertificateItem>>(
'/api/v1/admin/old-items/certificates?page=1&pageSize=100',
);
export const issueOldItemCertificate = (donationPublicId: string) =>
apiRequest<{ certificate: OldItemCertificateItem }>(
`/api/v1/admin/old-items/donations/${donationPublicId}/certificate`,
{
method: 'POST',
body: JSON.stringify({ clientRequestId: crypto.randomUUID() }),
},
);
export const revokeOldItemCertificate = (publicId: string, reason: string) =>
apiRequest<{ certificate: OldItemCertificateItem }>(
`/api/v1/admin/old-items/certificates/${publicId}/revoke`,
{
method: 'POST',
body: JSON.stringify({ clientRequestId: crypto.randomUUID(), reason }),
},
);
+135
View File
@@ -0,0 +1,135 @@
import type {
CreateOldItemNeedRequest,
OldItemDonationItem,
OldItemDonationStatus,
OldItemAssigneeOption,
DownloadUrlResponse,
OldItemNeedItem,
OldItemNeedStatus,
OldItemStats,
OldItemDropOffPoint,
CreateOldItemInventoryRequest,
ImportOldItemInventoryRequest,
OldItemInventoryExportRow,
OldItemInventoryItem,
OldItemInventoryStatus,
} from '@lehuo/contracts';
import { apiRequest } from './api-client';
export interface Page<T> {
items: T[];
page: number;
pageSize: number;
total: number;
}
export const getOldItemStats = () => apiRequest<OldItemStats>('/api/v1/old-items/stats');
export const listOldItemDonations = (status = '') =>
apiRequest<Page<OldItemDonationItem>>(
`/api/v1/admin/old-items/donations?page=1&pageSize=100${status ? `&status=${status}` : ''}`,
);
export const getOldItemDonation = (id: string) =>
apiRequest<{ donation: OldItemDonationItem }>(`/api/v1/admin/old-items/donations/${id}`);
export const transitionOldItemDonation = (
id: string,
expectedRevision: number,
targetStatus: OldItemDonationStatus,
note?: string,
assistedPeople?: number,
assignedUserPublicId?: string,
) =>
apiRequest<{ donation: OldItemDonationItem }>(
`/api/v1/admin/old-items/donations/${id}/transition`,
{
method: 'POST',
body: JSON.stringify({
clientRequestId: crypto.randomUUID(),
expectedRevision,
targetStatus,
note,
assistedPeople,
assignedUserPublicId,
}),
},
);
export const listOldItemNeeds = () =>
apiRequest<Page<OldItemNeedItem>>('/api/v1/admin/old-items/needs?page=1&pageSize=100');
export const createOldItemNeed = (input: Omit<CreateOldItemNeedRequest, 'clientRequestId'>) =>
apiRequest<{ need: OldItemNeedItem }>('/api/v1/admin/old-items/needs', {
method: 'POST',
body: JSON.stringify({ ...input, clientRequestId: crypto.randomUUID() }),
});
export const listOldItemAssignees = () =>
apiRequest<{ items: OldItemAssigneeOption[] }>('/api/v1/admin/old-items/assignees');
export const getOldItemImageUrl = (id: string) =>
apiRequest<DownloadUrlResponse>(`/api/v1/admin/old-items/media/${id}/download`);
export const listOldItemDropOffPoints = () =>
apiRequest<{ items: OldItemDropOffPoint[] }>('/api/v1/old-items/drop-off-points');
export const createOldItemDropOffPoint = (input: {
name: string;
regionText: string;
addressText: string;
openingHours: string;
sortOrder: number;
}) =>
apiRequest<{ point: OldItemDropOffPoint }>('/api/v1/admin/old-items/drop-off-points', {
method: 'POST',
body: JSON.stringify(input),
});
export const transitionOldItemNeed = (
id: string,
revision: number,
targetStatus: OldItemNeedStatus,
) =>
apiRequest<{ need: OldItemNeedItem }>(`/api/v1/admin/old-items/needs/${id}/transition`, {
method: 'POST',
body: JSON.stringify({
clientRequestId: crypto.randomUUID(),
expectedRevision: revision,
targetStatus,
}),
});
export const listOldItemInventory = (status = '') =>
apiRequest<Page<OldItemInventoryItem>>(
`/api/v1/admin/old-items/inventory?page=1&pageSize=100${status ? `&status=${status}` : ''}`,
);
export const getOldItemInventory = (id: string) =>
apiRequest<{ item: OldItemInventoryItem }>(`/api/v1/admin/old-items/inventory/${id}`);
export const createOldItemInventory = (
input: Omit<CreateOldItemInventoryRequest, 'clientRequestId'>,
) =>
apiRequest<{ item: OldItemInventoryItem }>('/api/v1/admin/old-items/inventory', {
method: 'POST',
body: JSON.stringify({ ...input, clientRequestId: crypto.randomUUID() }),
});
export const importOldItemInventory = (
input: Omit<ImportOldItemInventoryRequest, 'clientRequestId'>,
) =>
apiRequest<{ importPublicId: string; items: OldItemInventoryItem[] }>(
'/api/v1/admin/old-items/inventory/import',
{
method: 'POST',
body: JSON.stringify({ ...input, clientRequestId: crypto.randomUUID() }),
},
);
export const transitionOldItemInventory = (
id: string,
input: {
expectedRevision: number;
targetStatus: OldItemInventoryStatus;
eventAt?: string;
locationText?: string;
note?: string;
targetNeedPublicId?: string;
beneficiaryPublicId?: string;
destinationRegion?: string;
assistedPeople?: number;
},
) =>
apiRequest<{ item: OldItemInventoryItem }>(`/api/v1/admin/old-items/inventory/${id}/transition`, {
method: 'POST',
body: JSON.stringify({ ...input, clientRequestId: crypto.randomUUID() }),
});
export const exportOldItemInventory = () =>
apiRequest<{ rows: OldItemInventoryExportRow[]; exportedAt: string }>(
'/api/v1/admin/old-items/inventory-export/file?page=1&pageSize=100',
);