Hotfix Rule: Force Fresh Data After CRUD Mutation
Task-h not implements
This commit is contained in:
@@ -11,26 +11,57 @@ import {
|
||||
import { customerKeys } from './queries';
|
||||
import type { CustomerContactMutationPayload, CustomerMutationPayload } from './types';
|
||||
|
||||
async function invalidateCustomerLists() {
|
||||
await getQueryClient().invalidateQueries({ queryKey: customerKeys.lists() });
|
||||
}
|
||||
|
||||
async function invalidateCustomerDetail(id: string) {
|
||||
await getQueryClient().invalidateQueries({ queryKey: customerKeys.detail(id) });
|
||||
}
|
||||
|
||||
async function invalidateCustomerContacts(id: string) {
|
||||
await getQueryClient().invalidateQueries({ queryKey: customerKeys.contacts(id) });
|
||||
}
|
||||
|
||||
export async function invalidateCustomerMutationQueries(id: string) {
|
||||
await Promise.all([invalidateCustomerLists(), invalidateCustomerDetail(id)]);
|
||||
}
|
||||
|
||||
export async function invalidateCustomerContactMutationQueries(customerId: string) {
|
||||
await Promise.all([
|
||||
invalidateCustomerLists(),
|
||||
invalidateCustomerDetail(customerId),
|
||||
invalidateCustomerContacts(customerId)
|
||||
]);
|
||||
}
|
||||
|
||||
export const createCustomerMutation = mutationOptions({
|
||||
mutationFn: (data: CustomerMutationPayload) => createCustomer(data),
|
||||
onSuccess: () => {
|
||||
getQueryClient().invalidateQueries({ queryKey: customerKeys.all });
|
||||
onSettled: async (_data, error) => {
|
||||
if (!error) {
|
||||
await invalidateCustomerLists();
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
export const updateCustomerMutation = mutationOptions({
|
||||
mutationFn: ({ id, values }: { id: string; values: CustomerMutationPayload }) =>
|
||||
updateCustomer(id, values),
|
||||
onSuccess: (_data, variables) => {
|
||||
getQueryClient().invalidateQueries({ queryKey: customerKeys.all });
|
||||
getQueryClient().invalidateQueries({ queryKey: customerKeys.detail(variables.id) });
|
||||
onSettled: async (_data, error, variables) => {
|
||||
if (!error) {
|
||||
await invalidateCustomerMutationQueries(variables.id);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
export const deleteCustomerMutation = mutationOptions({
|
||||
mutationFn: (id: string) => deleteCustomer(id),
|
||||
onSuccess: () => {
|
||||
getQueryClient().invalidateQueries({ queryKey: customerKeys.all });
|
||||
onSettled: async (_data, error, id) => {
|
||||
if (!error) {
|
||||
getQueryClient().removeQueries({ queryKey: customerKeys.detail(id) });
|
||||
getQueryClient().removeQueries({ queryKey: customerKeys.contacts(id) });
|
||||
await invalidateCustomerLists();
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
@@ -42,9 +73,10 @@ export const createCustomerContactMutation = mutationOptions({
|
||||
customerId: string;
|
||||
values: CustomerContactMutationPayload;
|
||||
}) => createCustomerContact(customerId, values),
|
||||
onSuccess: (_data, variables) => {
|
||||
getQueryClient().invalidateQueries({ queryKey: customerKeys.contacts(variables.customerId) });
|
||||
getQueryClient().invalidateQueries({ queryKey: customerKeys.detail(variables.customerId) });
|
||||
onSettled: async (_data, error, variables) => {
|
||||
if (!error) {
|
||||
await invalidateCustomerContactMutationQueries(variables.customerId);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
@@ -58,17 +90,19 @@ export const updateCustomerContactMutation = mutationOptions({
|
||||
contactId: string;
|
||||
values: CustomerContactMutationPayload;
|
||||
}) => updateCustomerContact(customerId, contactId, values),
|
||||
onSuccess: (_data, variables) => {
|
||||
getQueryClient().invalidateQueries({ queryKey: customerKeys.contacts(variables.customerId) });
|
||||
getQueryClient().invalidateQueries({ queryKey: customerKeys.detail(variables.customerId) });
|
||||
onSettled: async (_data, error, variables) => {
|
||||
if (!error) {
|
||||
await invalidateCustomerContactMutationQueries(variables.customerId);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
export const deleteCustomerContactMutation = mutationOptions({
|
||||
mutationFn: ({ customerId, contactId }: { customerId: string; contactId: string }) =>
|
||||
deleteCustomerContact(customerId, contactId),
|
||||
onSuccess: (_data, variables) => {
|
||||
getQueryClient().invalidateQueries({ queryKey: customerKeys.contacts(variables.customerId) });
|
||||
getQueryClient().invalidateQueries({ queryKey: customerKeys.detail(variables.customerId) });
|
||||
onSettled: async (_data, error, variables) => {
|
||||
if (!error) {
|
||||
await invalidateCustomerContactMutationQueries(variables.customerId);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
@@ -4,9 +4,12 @@ import type { CustomerFilters } from './types';
|
||||
|
||||
export const customerKeys = {
|
||||
all: ['crm-customers'] as const,
|
||||
list: (filters: CustomerFilters) => [...customerKeys.all, 'list', filters] as const,
|
||||
detail: (id: string) => [...customerKeys.all, 'detail', id] as const,
|
||||
contacts: (id: string) => [...customerKeys.all, 'contacts', id] as const
|
||||
lists: () => [...customerKeys.all, 'list'] as const,
|
||||
list: (filters: CustomerFilters) => [...customerKeys.lists(), filters] as const,
|
||||
details: () => [...customerKeys.all, 'detail'] as const,
|
||||
detail: (id: string) => [...customerKeys.details(), id] as const,
|
||||
contactsRoot: () => [...customerKeys.all, 'contacts'] as const,
|
||||
contacts: (id: string) => [...customerKeys.contactsRoot(), id] as const
|
||||
};
|
||||
|
||||
export const customersQueryOptions = (filters: CustomerFilters) =>
|
||||
|
||||
@@ -9,6 +9,7 @@ import { Button } from '@/components/ui/button';
|
||||
import { Card, CardContent, CardDescription, CardHeader, CardTitle } from '@/components/ui/card';
|
||||
import { Separator } from '@/components/ui/separator';
|
||||
import { Tabs, TabsContent, TabsList, TabsTrigger } from '@/components/ui/tabs';
|
||||
import { formatDateTime } from '@/lib/format';
|
||||
import { customerByIdOptions } from '../api/queries';
|
||||
import type { CustomerReferenceData } from '../api/types';
|
||||
import { CustomerFormSheet } from './customer-form-sheet';
|
||||
@@ -30,6 +31,7 @@ export function CustomerDetail({
|
||||
customerId,
|
||||
referenceData,
|
||||
canUpdate,
|
||||
canReadContacts,
|
||||
canManageContacts,
|
||||
relatedEnquiries,
|
||||
relatedQuotations
|
||||
@@ -37,6 +39,7 @@ export function CustomerDetail({
|
||||
customerId: string;
|
||||
referenceData: CustomerReferenceData;
|
||||
canUpdate: boolean;
|
||||
canReadContacts: boolean;
|
||||
canManageContacts: {
|
||||
create: boolean;
|
||||
update: boolean;
|
||||
@@ -113,7 +116,7 @@ export function CustomerDetail({
|
||||
<Tabs defaultValue='overview' className='gap-4'>
|
||||
<TabsList>
|
||||
<TabsTrigger value='overview'>Overview</TabsTrigger>
|
||||
<TabsTrigger value='contacts'>Contacts</TabsTrigger>
|
||||
{canReadContacts ? <TabsTrigger value='contacts'>Contacts</TabsTrigger> : null}
|
||||
<TabsTrigger value='activity'>Activity</TabsTrigger>
|
||||
<TabsTrigger value='related'>Related Documents</TabsTrigger>
|
||||
</TabsList>
|
||||
@@ -166,14 +169,16 @@ export function CustomerDetail({
|
||||
</CardContent>
|
||||
</Card>
|
||||
</TabsContent>
|
||||
<TabsContent value='contacts'>
|
||||
<CustomerContactsTab
|
||||
customerId={customerId}
|
||||
canCreate={canManageContacts.create}
|
||||
canUpdate={canManageContacts.update}
|
||||
canDelete={canManageContacts.delete}
|
||||
/>
|
||||
</TabsContent>
|
||||
{canReadContacts ? (
|
||||
<TabsContent value='contacts'>
|
||||
<CustomerContactsTab
|
||||
customerId={customerId}
|
||||
canCreate={canManageContacts.create}
|
||||
canUpdate={canManageContacts.update}
|
||||
canDelete={canManageContacts.delete}
|
||||
/>
|
||||
</TabsContent>
|
||||
) : null}
|
||||
<TabsContent value='activity'>
|
||||
<Card>
|
||||
<CardHeader>
|
||||
@@ -202,7 +207,7 @@ export function CustomerDetail({
|
||||
</span>
|
||||
</div>
|
||||
<div className='text-muted-foreground text-xs'>
|
||||
{new Date(item.createdAt).toLocaleString()}
|
||||
{formatDateTime(item.createdAt)}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -281,8 +286,8 @@ export function CustomerDetail({
|
||||
<CardContent className='space-y-4'>
|
||||
<FieldItem label='Created By' value={customer.createdBy} />
|
||||
<FieldItem label='Updated By' value={customer.updatedBy} />
|
||||
<FieldItem label='Created At' value={new Date(customer.createdAt).toLocaleString()} />
|
||||
<FieldItem label='Updated At' value={new Date(customer.updatedAt).toLocaleString()} />
|
||||
<FieldItem label='Created At' value={formatDateTime(customer.createdAt)} />
|
||||
<FieldItem label='Updated At' value={formatDateTime(customer.updatedAt)} />
|
||||
</CardContent>
|
||||
</Card>
|
||||
</div>
|
||||
|
||||
Reference in New Issue
Block a user