task-d5.5.1
This commit is contained in:
@@ -14,7 +14,7 @@ export default async function CustomerDetailRoute({ params }: PageProps) {
|
||||
return (
|
||||
<PageContainer
|
||||
pageTitle='Customer Detail'
|
||||
pageDescription='Overview, contacts, shared contacts, enquiries, quotations, and activity log'
|
||||
pageDescription='Overview, contacts, shared contacts, opportunities, quotations, and activity log'
|
||||
>
|
||||
<HydrationBoundary state={dehydrate(queryClient)}>
|
||||
<CustomerDetailPage id={id} />
|
||||
@@ -22,3 +22,4 @@ export default async function CustomerDetailRoute({ params }: PageProps) {
|
||||
</PageContainer>
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@@ -1,24 +1,25 @@
|
||||
import { HydrationBoundary, dehydrate } from '@tanstack/react-query';
|
||||
import PageContainer from '@/components/layout/page-container';
|
||||
import { enquiryByIdOptions } from '@/features/crm-demo/api/queries';
|
||||
import { EnquiryDetailPage } from '@/features/crm-demo/components/enquiry-detail';
|
||||
import { opportunityByIdOptions } from '@/features/crm-demo/api/queries';
|
||||
import { OpportunityDetailPage } from '@/features/crm-demo/components/opportunity-detail';
|
||||
import { getQueryClient } from '@/lib/query-client';
|
||||
|
||||
type PageProps = { params: Promise<{ id: string }> };
|
||||
|
||||
export default async function EnquiryDetailRoute({ params }: PageProps) {
|
||||
export default async function OpportunityDetailRoute({ params }: PageProps) {
|
||||
const { id } = await params;
|
||||
const queryClient = getQueryClient();
|
||||
void queryClient.prefetchQuery(enquiryByIdOptions(id));
|
||||
void queryClient.prefetchQuery(opportunityByIdOptions(id));
|
||||
|
||||
return (
|
||||
<PageContainer
|
||||
pageTitle='Enquiry Detail'
|
||||
pageTitle='Opportunity Detail'
|
||||
pageDescription='Header summary, customer/contact, requirement summary, timeline, and related quotations'
|
||||
>
|
||||
<HydrationBoundary state={dehydrate(queryClient)}>
|
||||
<EnquiryDetailPage id={id} />
|
||||
<OpportunityDetailPage id={id} />
|
||||
</HydrationBoundary>
|
||||
</PageContainer>
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@@ -1,16 +1,16 @@
|
||||
import { HydrationBoundary, dehydrate } from '@tanstack/react-query';
|
||||
import type { SearchParams } from 'nuqs/server';
|
||||
import PageContainer from '@/components/layout/page-container';
|
||||
import { crmReferenceQueryOptions, enquiriesQueryOptions } from '@/features/crm-demo/api/queries';
|
||||
import { EnquiriesTablePage } from '@/features/crm-demo/components/enquiries-table';
|
||||
import { crmReferenceQueryOptions, opportunitiesQueryOptions } from '@/features/crm-demo/api/queries';
|
||||
import { OpportunitiesTablePage } from '@/features/crm-demo/components/opportunities-table';
|
||||
import { getQueryClient } from '@/lib/query-client';
|
||||
import { searchParamsCache } from '@/lib/searchparams';
|
||||
|
||||
export const metadata = {
|
||||
title: 'Dashboard: CRM Enquiries'
|
||||
title: 'Dashboard: CRM Opportunities'
|
||||
};
|
||||
|
||||
export default async function EnquiriesRoute({
|
||||
export default async function OpportunitiesRoute({
|
||||
searchParams
|
||||
}: {
|
||||
searchParams: Promise<SearchParams>;
|
||||
@@ -29,7 +29,7 @@ export default async function EnquiriesRoute({
|
||||
|
||||
void queryClient.prefetchQuery(crmReferenceQueryOptions());
|
||||
void queryClient.prefetchQuery(
|
||||
enquiriesQueryOptions({
|
||||
opportunitiesQueryOptions({
|
||||
page,
|
||||
limit: perPage,
|
||||
...(search && { search }),
|
||||
@@ -44,12 +44,13 @@ export default async function EnquiriesRoute({
|
||||
|
||||
return (
|
||||
<PageContainer
|
||||
pageTitle='Enquiries'
|
||||
pageTitle='Opportunities'
|
||||
pageDescription='List ของ sales opportunity พร้อม filter, date range และ convert to quotation'
|
||||
>
|
||||
<HydrationBoundary state={dehydrate(queryClient)}>
|
||||
<EnquiriesTablePage />
|
||||
<OpportunitiesTablePage />
|
||||
</HydrationBoundary>
|
||||
</PageContainer>
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@@ -15,7 +15,7 @@ export default function CrmDashboardRoute() {
|
||||
return (
|
||||
<PageContainer
|
||||
pageTitle='CRM Dashboard'
|
||||
pageDescription='ภาพรวม workflow ของ Customer → Enquiry → Quotation → Approval → Won/Lost'
|
||||
pageDescription='ภาพรวม workflow ของ Customer → Opportunity → Quotation → Approval → Won/Lost'
|
||||
>
|
||||
<HydrationBoundary state={dehydrate(queryClient)}>
|
||||
<CrmDashboardPage />
|
||||
@@ -23,3 +23,4 @@ export default function CrmDashboardRoute() {
|
||||
</PageContainer>
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@@ -7,7 +7,7 @@ import {
|
||||
getCustomerDetail,
|
||||
getCustomerReferenceData
|
||||
} from '@/features/crm/customers/server/service';
|
||||
import { listCustomerEnquiryRelations } from '@/features/crm/enquiries/server/service';
|
||||
import { listCustomerOpportunityRelations } from '@/features/crm/opportunities/server/service';
|
||||
import { listCustomerQuotationRelations } from '@/features/crm/quotations/server/service';
|
||||
import { PERMISSIONS } from '@/lib/auth/rbac';
|
||||
import { getQueryClient } from '@/lib/query-client';
|
||||
@@ -100,9 +100,9 @@ export default async function CustomerDetailRoute({ params }: PageProps) {
|
||||
resolvedCanRead && session?.user?.activeOrganizationId
|
||||
? await getCustomerReferenceData(session.user.activeOrganizationId)
|
||||
: null;
|
||||
const relatedEnquiries =
|
||||
const relatedOpportunities =
|
||||
resolvedCanRead && session?.user?.activeOrganizationId && accessContext
|
||||
? await listCustomerEnquiryRelations(id, session.user.activeOrganizationId, accessContext)
|
||||
? await listCustomerOpportunityRelations(id, session.user.activeOrganizationId, accessContext)
|
||||
: [];
|
||||
const relatedQuotations =
|
||||
resolvedCanRead && session?.user?.activeOrganizationId && accessContext
|
||||
@@ -135,7 +135,7 @@ export default async function CustomerDetailRoute({ params }: PageProps) {
|
||||
canReadContactShares={canContactShareRead}
|
||||
canManageContactShares={canContactShareManage}
|
||||
canManageOwner={canOwnerManage}
|
||||
relatedEnquiries={relatedEnquiries}
|
||||
relatedOpportunities={relatedOpportunities}
|
||||
relatedQuotations={relatedQuotations}
|
||||
/>
|
||||
</HydrationBoundary>
|
||||
@@ -143,3 +143,4 @@ export default async function CustomerDetailRoute({ params }: PageProps) {
|
||||
</PageContainer>
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@@ -1,83 +0,0 @@
|
||||
import { auth } from '@/auth';
|
||||
import PageContainer from '@/components/layout/page-container';
|
||||
import EnquiryListing from '@/features/crm/enquiries/components/enquiry-listing';
|
||||
import { EnquiryFormSheetTrigger } from '@/features/crm/enquiries/components/enquiry-form-sheet';
|
||||
import { getEnquiryReferenceData } from '@/features/crm/enquiries/server/service';
|
||||
import { PERMISSIONS } from '@/lib/auth/rbac';
|
||||
import type { SearchParams } from 'nuqs/server';
|
||||
|
||||
export const metadata = {
|
||||
title: 'Dashboard: CRM Opportunities'
|
||||
};
|
||||
|
||||
type PageProps = {
|
||||
searchParams: Promise<SearchParams>;
|
||||
};
|
||||
|
||||
export default async function EnquiriesRoute(props: PageProps) {
|
||||
await props.searchParams;
|
||||
const session = await auth();
|
||||
|
||||
const canRead =
|
||||
session?.user?.systemRole === 'super_admin' ||
|
||||
(!!session?.user?.activeOrganizationId &&
|
||||
(session.user.activeMembershipRole === 'admin' ||
|
||||
session.user.activePermissions.includes(PERMISSIONS.crmEnquiryRead)));
|
||||
|
||||
const canCreate =
|
||||
session?.user?.systemRole === 'super_admin' ||
|
||||
(!!session?.user?.activeOrganizationId &&
|
||||
(session.user.activeMembershipRole === 'admin' ||
|
||||
session.user.activePermissions.includes(PERMISSIONS.crmEnquiryCreate)));
|
||||
|
||||
const canUpdate =
|
||||
session?.user?.systemRole === 'super_admin' ||
|
||||
(!!session?.user?.activeOrganizationId &&
|
||||
(session.user.activeMembershipRole === 'admin' ||
|
||||
session.user.activePermissions.includes(PERMISSIONS.crmEnquiryUpdate)));
|
||||
|
||||
const canDelete =
|
||||
session?.user?.systemRole === 'super_admin' ||
|
||||
(!!session?.user?.activeOrganizationId &&
|
||||
(session.user.activeMembershipRole === 'admin' ||
|
||||
session.user.activePermissions.includes(PERMISSIONS.crmEnquiryDelete)));
|
||||
|
||||
const canAssign =
|
||||
session?.user?.systemRole === 'super_admin' ||
|
||||
(!!session?.user?.activeOrganizationId &&
|
||||
(session.user.activeMembershipRole === 'admin' ||
|
||||
session.user.activePermissions.includes(PERMISSIONS.crmEnquiryAssign)));
|
||||
|
||||
const canReassign =
|
||||
session?.user?.systemRole === 'super_admin' ||
|
||||
(!!session?.user?.activeOrganizationId &&
|
||||
(session.user.activeMembershipRole === 'admin' ||
|
||||
session.user.activePermissions.includes(PERMISSIONS.crmEnquiryReassign)));
|
||||
|
||||
if (!canRead || !session?.user?.activeOrganizationId) {
|
||||
return (
|
||||
<PageContainer access={false} pageTitle='CRM Opportunities'>
|
||||
{null}
|
||||
</PageContainer>
|
||||
);
|
||||
}
|
||||
|
||||
const referenceData = await getEnquiryReferenceData(session.user.activeOrganizationId);
|
||||
|
||||
return (
|
||||
<PageContainer
|
||||
pageTitle='CRM Opportunities'
|
||||
pageDescription='Sales execution workspace for opportunities created directly or handed off from marketing leads.'
|
||||
pageHeaderAction={canCreate ? <EnquiryFormSheetTrigger referenceData={referenceData} /> : null}
|
||||
>
|
||||
<EnquiryListing
|
||||
referenceData={referenceData}
|
||||
workspace='enquiry'
|
||||
canUpdate={canUpdate}
|
||||
canDelete={canDelete}
|
||||
canAssign={canAssign}
|
||||
canReassign={canReassign}
|
||||
/>
|
||||
</PageContainer>
|
||||
);
|
||||
}
|
||||
@@ -64,7 +64,7 @@ export default async function LeadsRoute(props: PageProps) {
|
||||
return (
|
||||
<PageContainer
|
||||
pageTitle="CRM Leads"
|
||||
pageDescription="Marketing-qualified lead workspace before handoff into sales enquiries."
|
||||
pageDescription="Marketing-qualified lead workspace before handoff into sales opportunities."
|
||||
pageHeaderAction={
|
||||
canCreate ? <LeadFormTrigger referenceData={referenceData} /> : null
|
||||
}
|
||||
@@ -80,3 +80,4 @@ export default async function LeadsRoute(props: PageProps) {
|
||||
</PageContainer>
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@@ -3,14 +3,14 @@ import { HydrationBoundary, dehydrate } from '@tanstack/react-query';
|
||||
import { notFound } from 'next/navigation';
|
||||
import PageContainer from '@/components/layout/page-container';
|
||||
import {
|
||||
enquiryByIdOptions,
|
||||
enquiryFollowupsOptions,
|
||||
enquiryProjectPartiesOptions
|
||||
} from '@/features/crm/enquiries/api/queries';
|
||||
import { EnquiryDetail } from '@/features/crm/enquiries/components/enquiry-detail';
|
||||
import { getEnquiryDetail, getEnquiryReferenceData } from '@/features/crm/enquiries/server/service';
|
||||
opportunityByIdOptions,
|
||||
opportunityFollowupsOptions,
|
||||
opportunityProjectPartiesOptions
|
||||
} from '@/features/crm/opportunities/api/queries';
|
||||
import { OpportunityDetail } from '@/features/crm/opportunities/components/opportunity-detail';
|
||||
import { getOpportunityDetail, getOpportunityReferenceData } from '@/features/crm/opportunities/server/service';
|
||||
import { getLeadById } from '@/features/crm/leads/server/service';
|
||||
import { listEnquiryQuotationRelations } from '@/features/crm/quotations/server/service';
|
||||
import { listOpportunityQuotationRelations } from '@/features/crm/quotations/server/service';
|
||||
import { getQuotationReferenceData } from '@/features/crm/quotations/server/service';
|
||||
import { PERMISSIONS } from '@/lib/auth/rbac';
|
||||
import { getQueryClient } from '@/lib/query-client';
|
||||
@@ -19,7 +19,7 @@ type PageProps = {
|
||||
params: Promise<{ id: string }>;
|
||||
};
|
||||
|
||||
export default async function EnquiryDetailRoute({ params }: PageProps) {
|
||||
export default async function OpportunityDetailRoute({ params }: PageProps) {
|
||||
const { id } = await params;
|
||||
const session = await auth();
|
||||
|
||||
@@ -27,61 +27,61 @@ export default async function EnquiryDetailRoute({ params }: PageProps) {
|
||||
session?.user?.systemRole === 'super_admin' ||
|
||||
(!!session?.user?.activeOrganizationId &&
|
||||
(session.user.activeMembershipRole === 'admin' ||
|
||||
session.user.activePermissions.includes(PERMISSIONS.crmEnquiryRead)));
|
||||
session.user.activePermissions.includes(PERMISSIONS.crmOpportunityRead)));
|
||||
|
||||
const canUpdate =
|
||||
session?.user?.systemRole === 'super_admin' ||
|
||||
(!!session?.user?.activeOrganizationId &&
|
||||
(session.user.activeMembershipRole === 'admin' ||
|
||||
session.user.activePermissions.includes(PERMISSIONS.crmEnquiryUpdate)));
|
||||
session.user.activePermissions.includes(PERMISSIONS.crmOpportunityUpdate)));
|
||||
|
||||
const canAssign =
|
||||
session?.user?.systemRole === 'super_admin' ||
|
||||
(!!session?.user?.activeOrganizationId &&
|
||||
(session.user.activeMembershipRole === 'admin' ||
|
||||
session.user.activePermissions.includes(PERMISSIONS.crmEnquiryAssign)));
|
||||
session.user.activePermissions.includes(PERMISSIONS.crmOpportunityAssign)));
|
||||
|
||||
const canReassign =
|
||||
session?.user?.systemRole === 'super_admin' ||
|
||||
(!!session?.user?.activeOrganizationId &&
|
||||
(session.user.activeMembershipRole === 'admin' ||
|
||||
session.user.activePermissions.includes(PERMISSIONS.crmEnquiryReassign)));
|
||||
session.user.activePermissions.includes(PERMISSIONS.crmOpportunityReassign)));
|
||||
|
||||
const canManageFollowups = {
|
||||
create:
|
||||
session?.user?.systemRole === 'super_admin' ||
|
||||
(!!session?.user?.activeOrganizationId &&
|
||||
(session.user.activeMembershipRole === 'admin' ||
|
||||
session.user.activePermissions.includes(PERMISSIONS.crmEnquiryFollowupCreate))),
|
||||
session.user.activePermissions.includes(PERMISSIONS.crmOpportunityFollowupCreate))),
|
||||
update:
|
||||
session?.user?.systemRole === 'super_admin' ||
|
||||
(!!session?.user?.activeOrganizationId &&
|
||||
(session.user.activeMembershipRole === 'admin' ||
|
||||
session.user.activePermissions.includes(PERMISSIONS.crmEnquiryFollowupUpdate))),
|
||||
session.user.activePermissions.includes(PERMISSIONS.crmOpportunityFollowupUpdate))),
|
||||
delete:
|
||||
session?.user?.systemRole === 'super_admin' ||
|
||||
(!!session?.user?.activeOrganizationId &&
|
||||
(session.user.activeMembershipRole === 'admin' ||
|
||||
session.user.activePermissions.includes(PERMISSIONS.crmEnquiryFollowupDelete)))
|
||||
session.user.activePermissions.includes(PERMISSIONS.crmOpportunityFollowupDelete)))
|
||||
};
|
||||
|
||||
const canMarkWon =
|
||||
session?.user?.systemRole === 'super_admin' ||
|
||||
(!!session?.user?.activeOrganizationId &&
|
||||
(session.user.activeMembershipRole === 'admin' ||
|
||||
session.user.activePermissions.includes(PERMISSIONS.crmEnquiryMarkWon)));
|
||||
session.user.activePermissions.includes(PERMISSIONS.crmOpportunityMarkWon)));
|
||||
|
||||
const canMarkLost =
|
||||
session?.user?.systemRole === 'super_admin' ||
|
||||
(!!session?.user?.activeOrganizationId &&
|
||||
(session.user.activeMembershipRole === 'admin' ||
|
||||
session.user.activePermissions.includes(PERMISSIONS.crmEnquiryMarkLost)));
|
||||
session.user.activePermissions.includes(PERMISSIONS.crmOpportunityMarkLost)));
|
||||
|
||||
const canReopen =
|
||||
session?.user?.systemRole === 'super_admin' ||
|
||||
(!!session?.user?.activeOrganizationId &&
|
||||
(session.user.activeMembershipRole === 'admin' ||
|
||||
session.user.activePermissions.includes(PERMISSIONS.crmEnquiryReopen)));
|
||||
session.user.activePermissions.includes(PERMISSIONS.crmOpportunityReopen)));
|
||||
|
||||
const canViewRelatedQuotations =
|
||||
session?.user?.systemRole === 'super_admin' ||
|
||||
@@ -118,17 +118,17 @@ export default async function EnquiryDetailRoute({ params }: PageProps) {
|
||||
|
||||
const queryClient = getQueryClient();
|
||||
await Promise.all([
|
||||
queryClient.prefetchQuery(enquiryByIdOptions(id)),
|
||||
queryClient.prefetchQuery(enquiryFollowupsOptions(id)),
|
||||
queryClient.prefetchQuery(enquiryProjectPartiesOptions(id))
|
||||
queryClient.prefetchQuery(opportunityByIdOptions(id)),
|
||||
queryClient.prefetchQuery(opportunityFollowupsOptions(id)),
|
||||
queryClient.prefetchQuery(opportunityProjectPartiesOptions(id))
|
||||
]);
|
||||
|
||||
const enquiryDetail = await getEnquiryDetail(id, session.user.activeOrganizationId, accessContext);
|
||||
const opportunityDetail = await getOpportunityDetail(id, session.user.activeOrganizationId, accessContext);
|
||||
const [referenceData, relatedQuotations, sourceLead, quotationReferenceData] = await Promise.all([
|
||||
getEnquiryReferenceData(session.user.activeOrganizationId),
|
||||
listEnquiryQuotationRelations(id, session.user.activeOrganizationId),
|
||||
enquiryDetail.leadId
|
||||
? getLeadById(enquiryDetail.leadId, session.user.activeOrganizationId).catch(() => null)
|
||||
getOpportunityReferenceData(session.user.activeOrganizationId),
|
||||
listOpportunityQuotationRelations(id, session.user.activeOrganizationId),
|
||||
opportunityDetail.leadId
|
||||
? getLeadById(opportunityDetail.leadId, session.user.activeOrganizationId).catch(() => null)
|
||||
: Promise.resolve(null),
|
||||
canCreateQuotation ? getQuotationReferenceData(session.user.activeOrganizationId) : Promise.resolve(null)
|
||||
]);
|
||||
@@ -139,11 +139,11 @@ export default async function EnquiryDetailRoute({ params }: PageProps) {
|
||||
pageDescription='Sales execution workspace for follow-up continuity, quotation readiness, and outcome control.'
|
||||
>
|
||||
<HydrationBoundary state={dehydrate(queryClient)}>
|
||||
<EnquiryDetail
|
||||
enquiryId={id}
|
||||
<OpportunityDetail
|
||||
opportunityId={id}
|
||||
referenceData={referenceData}
|
||||
relatedQuotations={relatedQuotations}
|
||||
workspace='enquiry'
|
||||
workspace='opportunity'
|
||||
canUpdate={canUpdate}
|
||||
canAssign={canAssign}
|
||||
canReassign={canReassign}
|
||||
@@ -171,3 +171,4 @@ export default async function EnquiryDetailRoute({ params }: PageProps) {
|
||||
</PageContainer>
|
||||
);
|
||||
}
|
||||
|
||||
93
src/app/dashboard/crm/opportunities/page.tsx
Normal file
93
src/app/dashboard/crm/opportunities/page.tsx
Normal file
@@ -0,0 +1,93 @@
|
||||
import { auth } from "@/auth";
|
||||
import PageContainer from "@/components/layout/page-container";
|
||||
import OpportunityListing from "@/features/crm/opportunities/components/opportunity-listing";
|
||||
import { OpportunityFormSheetTrigger } from "@/features/crm/opportunities/components/opportunity-form-sheet";
|
||||
import { getOpportunityReferenceData } from "@/features/crm/opportunities/server/service";
|
||||
import { PERMISSIONS } from "@/lib/auth/rbac";
|
||||
import type { SearchParams } from "nuqs/server";
|
||||
import { searchParamsCache } from "@/lib/searchparams";
|
||||
|
||||
export const metadata = {
|
||||
title: "Dashboard: CRM Opportunities",
|
||||
};
|
||||
|
||||
type PageProps = {
|
||||
searchParams: Promise<SearchParams>;
|
||||
};
|
||||
|
||||
export default async function OpportunitiesRoute(props: PageProps) {
|
||||
const searchParams = await props.searchParams;
|
||||
const session = await auth();
|
||||
|
||||
const canRead =
|
||||
session?.user?.systemRole === "super_admin" ||
|
||||
(!!session?.user?.activeOrganizationId &&
|
||||
(session.user.activeMembershipRole === "admin" ||
|
||||
session.user.activePermissions.includes(PERMISSIONS.crmOpportunityRead)));
|
||||
|
||||
const canCreate =
|
||||
session?.user?.systemRole === "super_admin" ||
|
||||
(!!session?.user?.activeOrganizationId &&
|
||||
(session.user.activeMembershipRole === "admin" ||
|
||||
session.user.activePermissions.includes(PERMISSIONS.crmOpportunityCreate)));
|
||||
|
||||
const canUpdate =
|
||||
session?.user?.systemRole === "super_admin" ||
|
||||
(!!session?.user?.activeOrganizationId &&
|
||||
(session.user.activeMembershipRole === "admin" ||
|
||||
session.user.activePermissions.includes(PERMISSIONS.crmOpportunityUpdate)));
|
||||
|
||||
const canDelete =
|
||||
session?.user?.systemRole === "super_admin" ||
|
||||
(!!session?.user?.activeOrganizationId &&
|
||||
(session.user.activeMembershipRole === "admin" ||
|
||||
session.user.activePermissions.includes(PERMISSIONS.crmOpportunityDelete)));
|
||||
|
||||
const canAssign =
|
||||
session?.user?.systemRole === "super_admin" ||
|
||||
(!!session?.user?.activeOrganizationId &&
|
||||
(session.user.activeMembershipRole === "admin" ||
|
||||
session.user.activePermissions.includes(PERMISSIONS.crmOpportunityAssign)));
|
||||
|
||||
const canReassign =
|
||||
session?.user?.systemRole === "super_admin" ||
|
||||
(!!session?.user?.activeOrganizationId &&
|
||||
(session.user.activeMembershipRole === "admin" ||
|
||||
session.user.activePermissions.includes(
|
||||
PERMISSIONS.crmOpportunityReassign,
|
||||
)));
|
||||
|
||||
if (!canRead || !session?.user?.activeOrganizationId) {
|
||||
return (
|
||||
<PageContainer access={false} pageTitle="CRM Opportunities">
|
||||
{null}
|
||||
</PageContainer>
|
||||
);
|
||||
}
|
||||
searchParamsCache.parse(searchParams);
|
||||
const referenceData = await getOpportunityReferenceData(
|
||||
session.user.activeOrganizationId,
|
||||
);
|
||||
|
||||
return (
|
||||
<PageContainer
|
||||
pageTitle="CRM Opportunities"
|
||||
pageDescription="Sales execution workspace for opportunities created directly or handed off from marketing leads."
|
||||
pageHeaderAction={
|
||||
canCreate ? (
|
||||
<OpportunityFormSheetTrigger referenceData={referenceData} />
|
||||
) : null
|
||||
}
|
||||
>
|
||||
<OpportunityListing
|
||||
referenceData={referenceData}
|
||||
workspace="opportunity"
|
||||
canUpdate={canUpdate}
|
||||
canDelete={canDelete}
|
||||
canAssign={canAssign}
|
||||
canReassign={canReassign}
|
||||
/>
|
||||
</PageContainer>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -2,7 +2,7 @@ import { HydrationBoundary, dehydrate } from '@tanstack/react-query';
|
||||
import { auth } from '@/auth';
|
||||
import PageContainer from '@/components/layout/page-container';
|
||||
import {
|
||||
crmEnquiryAgingReportQueryOptions,
|
||||
crmOpportunityAgingReportQueryOptions,
|
||||
crmReportFiltersQueryOptions
|
||||
} from '@/features/crm/reports/api/queries';
|
||||
import { AgingReportView } from '@/features/crm/reports/components/aging-report-view';
|
||||
@@ -11,7 +11,7 @@ import { getQueryClient } from '@/lib/query-client';
|
||||
import type { SearchParams } from 'nuqs/server';
|
||||
|
||||
export const metadata = {
|
||||
title: 'CRM Enquiry Aging Report'
|
||||
title: 'CRM Opportunity Aging Report'
|
||||
};
|
||||
|
||||
type PageProps = {
|
||||
@@ -22,7 +22,7 @@ function getFilterValue(value: string | string[] | undefined): string | null {
|
||||
return typeof value === 'string' ? value : null;
|
||||
}
|
||||
|
||||
export default async function CrmEnquiryAgingRoute(props: PageProps) {
|
||||
export default async function CrmOpportunityAgingRoute(props: PageProps) {
|
||||
const searchParams = await props.searchParams;
|
||||
const session = await auth();
|
||||
const canRead =
|
||||
@@ -48,25 +48,26 @@ export default async function CrmEnquiryAgingRoute(props: PageProps) {
|
||||
|
||||
if (canRead) {
|
||||
void queryClient.prefetchQuery(crmReportFiltersQueryOptions());
|
||||
void queryClient.prefetchQuery(crmEnquiryAgingReportQueryOptions(filters));
|
||||
void queryClient.prefetchQuery(crmOpportunityAgingReportQueryOptions(filters));
|
||||
}
|
||||
|
||||
return (
|
||||
<PageContainer
|
||||
pageTitle='Enquiry Aging Report'
|
||||
pageDescription='Identify stalled enquiries that need follow-up or progression.'
|
||||
pageTitle='Opportunity Aging Report'
|
||||
pageDescription='Identify stalled opportunities that need follow-up or progression.'
|
||||
access={canRead}
|
||||
accessFallback={
|
||||
<div className='text-muted-foreground rounded-lg border border-dashed p-8 text-center'>
|
||||
You do not have access to CRM enquiry aging reports.
|
||||
You do not have access to CRM opportunity aging reports.
|
||||
</div>
|
||||
}
|
||||
>
|
||||
{canRead ? (
|
||||
<HydrationBoundary state={dehydrate(queryClient)}>
|
||||
<AgingReportView variant='enquiry' canExport={canExport} />
|
||||
<AgingReportView variant='opportunity' canExport={canExport} />
|
||||
</HydrationBoundary>
|
||||
) : null}
|
||||
</PageContainer>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -56,7 +56,7 @@ export default async function CrmPipelineReportsRoute(props: PageProps) {
|
||||
return (
|
||||
<PageContainer
|
||||
pageTitle='Pipeline Reports'
|
||||
pageDescription='Lead, enquiry, conversion, and funnel analytics for the CRM pipeline lifecycle.'
|
||||
pageDescription='Lead, opportunity, conversion, and funnel analytics for the CRM pipeline lifecycle.'
|
||||
access={canRead}
|
||||
accessFallback={
|
||||
<div className='text-muted-foreground rounded-lg border border-dashed p-8 text-center'>
|
||||
@@ -72,3 +72,4 @@ export default async function CrmPipelineReportsRoute(props: PageProps) {
|
||||
</PageContainer>
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user