refactor: decompose CrmWorkspaceApp.vue into 15 composables
Split the 6000+ line monolithic component into modular composables: - crm-types.ts: shared types and utility functions - useAuth, useContacts, useContactInboxes, useCalendar, useDeals, useDocuments, useFeed, useTimeline, usePilotChat, useCallAudio, usePins, useChangeReview, useCrmRealtime, useWorkspaceRouting CrmWorkspaceApp.vue is now a thin orchestrator (~2500 lines) that wires composables together with glue code, keeping template and styles intact. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
52
frontend/app/composables/useTimeline.ts
Normal file
52
frontend/app/composables/useTimeline.ts
Normal file
@@ -0,0 +1,52 @@
|
||||
import { ref, computed, watch, type ComputedRef } from "vue";
|
||||
import { useQuery } from "@vue/apollo-composable";
|
||||
import { GetClientTimelineQueryDocument } from "~~/graphql/generated";
|
||||
import type { ClientTimelineItem } from "~/composables/crm-types";
|
||||
|
||||
export function useTimeline(opts: { apolloAuthReady: ComputedRef<boolean> }) {
|
||||
const timelineContactId = ref("");
|
||||
const timelineLimit = ref(500);
|
||||
|
||||
const { result: timelineResult, refetch: refetchTimeline } = useQuery(
|
||||
GetClientTimelineQueryDocument,
|
||||
() => ({ contactId: timelineContactId.value, limit: timelineLimit.value }),
|
||||
{ enabled: computed(() => !!timelineContactId.value && opts.apolloAuthReady.value) },
|
||||
);
|
||||
|
||||
const clientTimelineItems = ref<ClientTimelineItem[]>([]);
|
||||
|
||||
watch(() => timelineResult.value?.getClientTimeline, (v) => {
|
||||
if (v) clientTimelineItems.value = v as ClientTimelineItem[];
|
||||
}, { immediate: true });
|
||||
|
||||
async function loadClientTimeline(contactId: string, limit = 500) {
|
||||
const normalizedContactId = String(contactId ?? "").trim();
|
||||
if (!normalizedContactId) {
|
||||
clientTimelineItems.value = [];
|
||||
timelineContactId.value = "";
|
||||
return;
|
||||
}
|
||||
|
||||
timelineContactId.value = normalizedContactId;
|
||||
timelineLimit.value = limit;
|
||||
await refetchTimeline();
|
||||
}
|
||||
|
||||
async function refreshSelectedClientTimeline(selectedCommThreadId: string) {
|
||||
const contactId = String(selectedCommThreadId ?? "").trim();
|
||||
if (!contactId) {
|
||||
clientTimelineItems.value = [];
|
||||
return;
|
||||
}
|
||||
await loadClientTimeline(contactId);
|
||||
}
|
||||
|
||||
return {
|
||||
clientTimelineItems,
|
||||
timelineContactId,
|
||||
timelineLimit,
|
||||
loadClientTimeline,
|
||||
refreshSelectedClientTimeline,
|
||||
refetchTimeline,
|
||||
};
|
||||
}
|
||||
Reference in New Issue
Block a user