Files
portal/app/resources/js/api/reminders.ts
T
Дмитрий dc1457a008 phase2(reminders-frontend): RemindersView + DealDetailDrawer + nav-badge
P0 этап 5 — frontend для reminders (после backend-этапа 4).
Пользователь может создавать/просматривать/завершать/удалять напоминания
из UI с inline-create в DealDetailDrawer.

Frontend:
- api/reminders.ts: типизированные helpers для 5 endpoints + ensureCsrfCookie
  для mutating. Types ReminderFilter/ApiReminder/ReminderCounts.
- stores/reminders.ts: Pinia с items/counts/currentFilter +
  load/refreshCounts/create/update/complete/remove. Optimistic для
  complete/remove с revert на reject.
- components/reminders/ReminderDialog.vue: dual-mode (create/edit) modal
  с native datetime-local input. Props dealId?/reminder? (edit),
  ISO-конверсия при submit.
- views/RemindersView.vue: page-head с stats (active/overdue) + reload-btn;
  4 tabs (today/upcoming/overdue/completed) с counts на бейджах
  (overdue=error color); v-list с complete-btn / dropdown
  Изменить/Удалить с confirm-dialog; empty-state.
- router: /reminders маршрут (lazy).
- AppLayout: nav-badge «Напоминания» биндит count из store
  (replace static «12»); скрыт при count=0; polling 60 сек для
  refreshCounts.
- DealDetailDrawer: секция «Напоминания» (только при tenantId+deal):
  inline + create-btn / список / complete / встроенный ReminderDialog.

Vitest +20 (369/369 за 21.20 сек):
- reminders-store 11: initial / load+reject / refreshCounts /
  create+reject / complete optimistic+revert / remove+reject / reset.
- RemindersView 7: mount / 4 tabs / counts / empty-state /
  список / reload-btn / filter=today default.
- AppLayout +2: бейдж скрыт при count=0 / показывает count при >0.

Pest 347/347 (без изменений — backend нетронут).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-09 12:41:41 +03:00

90 lines
2.4 KiB
TypeScript

import { apiClient, ensureCsrfCookie } from './client';
/**
* Reminders API (schema v8.10 §17.5).
*
* Все endpoint'ы под Sanctum SPA auth.
* Mutating-вызовы (POST/PATCH/DELETE) делают ensureCsrfCookie().
*/
export type ReminderFilter = 'active' | 'today' | 'upcoming' | 'overdue' | 'completed';
export interface ApiReminder {
id: number;
deal_id: number;
text: string | null;
remind_at: string | null;
completed_at: string | null;
is_sent: boolean;
sent_at: string | null;
created_at: string | null;
created_by: number;
assignee_id: number | null;
creator_name: string | null;
}
export interface ReminderCounts {
active: number;
today: number;
upcoming: number;
overdue: number;
}
export interface ListRemindersResponse {
items: ApiReminder[];
counts: ReminderCounts;
}
export interface ListRemindersParams {
filter?: ReminderFilter;
dealId?: number;
limit?: number;
}
export async function listReminders(params: ListRemindersParams = {}): Promise<ListRemindersResponse> {
const { data } = await apiClient.get<ListRemindersResponse>('/api/reminders', {
params: {
filter: params.filter,
deal_id: params.dealId,
limit: params.limit,
},
});
return data;
}
export interface CreateReminderPayload {
deal_id: number;
text?: string | null;
remind_at: string;
assignee_id?: number | null;
}
export async function createReminder(payload: CreateReminderPayload): Promise<ApiReminder> {
await ensureCsrfCookie();
const { data } = await apiClient.post<{ reminder: ApiReminder }>('/api/reminders', payload);
return data.reminder;
}
export interface UpdateReminderPayload {
text?: string | null;
remind_at?: string;
assignee_id?: number | null;
}
export async function updateReminder(id: number, payload: UpdateReminderPayload): Promise<ApiReminder> {
await ensureCsrfCookie();
const { data } = await apiClient.patch<{ reminder: ApiReminder }>(`/api/reminders/${id}`, payload);
return data.reminder;
}
export async function completeReminder(id: number): Promise<ApiReminder> {
await ensureCsrfCookie();
const { data } = await apiClient.post<{ reminder: ApiReminder }>(`/api/reminders/${id}/complete`);
return data.reminder;
}
export async function deleteReminder(id: number): Promise<void> {
await ensureCsrfCookie();
await apiClient.delete(`/api/reminders/${id}`);
}