Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion apps/app/app/(app)/[slug]/companies/create-company-sheet.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ import { parseAsBoolean, useQueryState } from "nuqs";
import { type ComponentProps, Suspense, useId, useState } from "react";
import { toast } from "sonner";
import { useOpenRecord } from "@/components/crm/record-sheet/record-stack";
import { SEARCH_PARAM } from "@/lib/search-param-keys";
import { useCrmCache } from "@/lib/trpc/cache";
import { useTRPC } from "@/lib/trpc/client";

Expand Down Expand Up @@ -61,7 +62,7 @@ function CreateCompanyForm() {
const cache = useCrmCache();

const [open, setOpen] = useQueryState(
"new",
SEARCH_PARAM.dialog.create,
parseAsBoolean.withDefault(false),
);
const [name, setName] = useState("");
Expand Down
3 changes: 2 additions & 1 deletion apps/app/app/(app)/[slug]/contacts/create-contact-sheet.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ import { type ComponentProps, Suspense, useId, useState } from "react";
import { toast } from "sonner";
import { CompanyPicker } from "@/components/crm/company-picker";
import { useOpenRecord } from "@/components/crm/record-sheet/record-stack";
import { SEARCH_PARAM } from "@/lib/search-param-keys";
import { useCrmCache } from "@/lib/trpc/cache";
import { useTRPC } from "@/lib/trpc/client";

Expand Down Expand Up @@ -57,7 +58,7 @@ function CreateContactForm({ companyId }: { companyId?: string }) {
const cache = useCrmCache();

const [open, setOpen] = useQueryState(
"new",
SEARCH_PARAM.dialog.create,
parseAsBoolean.withDefault(false),
);
const [firstName, setFirstName] = useState("");
Expand Down
6 changes: 5 additions & 1 deletion apps/app/app/(app)/[slug]/dashboard-summary.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ import { useOpenRecord } from "@/components/crm/record-sheet/record-stack";
import { LocalRelativeTime } from "@/components/local-date-time";
import { activityLabel } from "@/lib/activity-presentation";
import { dealStageColor } from "@/lib/deal-stage";
import { SEARCH_PARAM } from "@/lib/search-param-keys";
import { useCrmCache } from "@/lib/trpc/cache";
import { useTRPC } from "@/lib/trpc/client";
import { useWorkspaceUrl } from "@/lib/use-workspace-url";
Expand Down Expand Up @@ -94,7 +95,10 @@ export function DashboardSummary() {
const openRecord = useOpenRecord();
const workspaceUrl = useWorkspaceUrl();

const [scope] = useQueryState("scope", overviewParsers.scope);
const [scope] = useQueryState(
SEARCH_PARAM.overview.scope,
overviewParsers[SEARCH_PARAM.overview.scope],
);

const summaryQuery = useQuery({
...trpc.dashboard.summary.queryOptions({ scope }),
Expand Down
3 changes: 2 additions & 1 deletion apps/app/app/(app)/[slug]/deals/create-deal-sheet.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ import { toast } from "sonner";
import { CompanyPicker } from "@/components/crm/company-picker";
import { useOpenRecord } from "@/components/crm/record-sheet/record-stack";
import { dealStageLabel, OPEN_STAGES } from "@/lib/deal-stage";
import { SEARCH_PARAM } from "@/lib/search-param-keys";
import { useCrmCache } from "@/lib/trpc/cache";
import { useTRPC } from "@/lib/trpc/client";

Expand Down Expand Up @@ -65,7 +66,7 @@ function CreateDealForm({ companyId }: { companyId?: string }) {
const cache = useCrmCache();

const [open, setOpen] = useQueryState(
"new",
SEARCH_PARAM.dialog.create,
parseAsBoolean.withDefault(false),
);
const [name, setName] = useState("");
Expand Down
6 changes: 5 additions & 1 deletion apps/app/app/(app)/[slug]/overview-greeting.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

import { useQueryState } from "nuqs";
import { PageShellDescription, PageShellTitle } from "@/components/page-shell";
import { SEARCH_PARAM } from "@/lib/search-param-keys";
import { overviewParsers } from "./overview-search-params";

export function OverviewGreetingFallback() {
Expand All @@ -16,7 +17,10 @@ export function OverviewGreetingFallback() {
}

export function OverviewGreeting() {
const [scope] = useQueryState("scope", overviewParsers.scope);
const [scope] = useQueryState(
SEARCH_PARAM.overview.scope,
overviewParsers[SEARCH_PARAM.overview.scope],
);

return (
<>
Expand Down
6 changes: 5 additions & 1 deletion apps/app/app/(app)/[slug]/overview-scope.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

import { ToggleGroup, ToggleGroupItem } from "@crm/ui/components/toggle-group";
import { useQueryState } from "nuqs";
import { SEARCH_PARAM } from "@/lib/search-param-keys";
import {
OVERVIEW_SCOPES,
type OverviewScope,
Expand Down Expand Up @@ -37,7 +38,10 @@ export function OverviewScopeToggleFallback() {
}

export function OverviewScopeToggle() {
const [scope, setScope] = useQueryState("scope", overviewParsers.scope);
const [scope, setScope] = useQueryState(
SEARCH_PARAM.overview.scope,
overviewParsers[SEARCH_PARAM.overview.scope],
);

return (
<ToggleGroup
Expand Down
4 changes: 3 additions & 1 deletion apps/app/app/(app)/[slug]/overview-search-params.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,13 @@
import { createLoader, parseAsStringLiteral } from "nuqs/server";
import { SEARCH_PARAM } from "@/lib/search-param-keys";

export const OVERVIEW_SCOPES = ["me", "everyone"] as const;

export type OverviewScope = (typeof OVERVIEW_SCOPES)[number];

export const overviewParsers = {
scope: parseAsStringLiteral(OVERVIEW_SCOPES).withDefault("me"),
[SEARCH_PARAM.overview.scope]:
parseAsStringLiteral(OVERVIEW_SCOPES).withDefault("me"),
};

export const loadOverviewSearchParams = createLoader(overviewParsers);
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ import { useMutation } from "@tanstack/react-query";
import { parseAsBoolean, useQueryState } from "nuqs";
import { type ComponentProps, Suspense, useId, useState } from "react";
import { toast } from "sonner";
import { SEARCH_PARAM } from "@/lib/search-param-keys";
import { useCrmCache } from "@/lib/trpc/cache";
import { useTRPC } from "@/lib/trpc/client";
import type { RouterOutputs } from "@/lib/trpc/types";
Expand Down Expand Up @@ -75,7 +76,7 @@ function CreateApiKeyForm() {
const expirationId = useId();

const [open, setOpen] = useQueryState(
"new",
SEARCH_PARAM.dialog.create,
parseAsBoolean.withDefault(false),
);
const [name, setName] = useState("");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ import { useMutation, useQuery } from "@tanstack/react-query";
import { parseAsBoolean, useQueryState } from "nuqs";
import { type ComponentProps, Suspense, useId, useState } from "react";
import { toast } from "sonner";
import { SEARCH_PARAM } from "@/lib/search-param-keys";
import { useCrmCache } from "@/lib/trpc/cache";
import { useTRPC } from "@/lib/trpc/client";
import { CopyValue } from "../copy-value";
Expand Down Expand Up @@ -75,7 +76,7 @@ function AddSsoProviderForm() {
const redirectId = useId();

const [open, setOpen] = useQueryState(
"new",
SEARCH_PARAM.dialog.create,
parseAsBoolean.withDefault(false),
);
const [values, setValues] = useState(EMPTY);
Expand Down
6 changes: 5 additions & 1 deletion apps/app/components/crm/quick-switcher.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ import { useQuery } from "@tanstack/react-query";
import { parseAsBoolean, useQueryState } from "nuqs";
import { useEffect, useState } from "react";
import { useOpenRecord } from "@/components/crm/record-sheet/record-stack";
import { SEARCH_PARAM } from "@/lib/search-param-keys";
import { useTRPC } from "@/lib/trpc/client";

const GROUP_LABEL = {
Expand All @@ -32,7 +33,10 @@ export function QuickSwitcher() {
const openRecord = useOpenRecord();
const trpc = useTRPC();

const [open, setOpen] = useQueryState("k", parseAsBoolean.withDefault(false));
const [open, setOpen] = useQueryState(
SEARCH_PARAM.dialog.switcher,
parseAsBoolean.withDefault(false),
);
const [query, setQuery] = useState("");

useEffect(() => {
Expand Down
80 changes: 49 additions & 31 deletions apps/app/components/crm/record-sheet/record-stack.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,8 @@ import {
useQueryStates,
} from "nuqs";
import { useCallback, useMemo } from "react";
import {
TIMELINE_PARAM,
timelineTabParser,
} from "@/components/crm/timeline/timeline-search-params";
import { timelineTabParser } from "@/components/crm/timeline/timeline-search-params";
import { SEARCH_PARAM } from "@/lib/search-param-keys";

const RECORD_KINDS = ["company", "contact", "deal"] as const;

Expand All @@ -28,13 +26,15 @@ const FORM_TAB = {
} satisfies Record<RecordForm, string>;

const params = {
record: parseAsArrayOf(parseAsString, ",").withDefault([]),
tab: parseAsString,
add: parseAsStringLiteral(RECORD_FORMS),
thread: parseAsString,
fields: parseAsStringLiteral(RECORD_KINDS),
field: parseAsString,
[TIMELINE_PARAM]: timelineTabParser,
[SEARCH_PARAM.record.stack]: parseAsArrayOf(parseAsString, ",").withDefault(
[],
),
[SEARCH_PARAM.record.tab]: parseAsString,
[SEARCH_PARAM.record.add]: parseAsStringLiteral(RECORD_FORMS),
[SEARCH_PARAM.record.thread]: parseAsString,
[SEARCH_PARAM.fieldsSheet.entity]: parseAsStringLiteral(RECORD_KINDS),
[SEARCH_PARAM.fieldsSheet.field]: parseAsString,
[SEARCH_PARAM.record.timeline]: timelineTabParser,
};

export function recordKey(ref: RecordRef): string {
Expand All @@ -51,7 +51,8 @@ function parseRef(raw: string): RecordRef | null {
}

export function useRecordStack() {
const [{ record }, setParams] = useQueryStates(params);
const [values, setParams] = useQueryStates(params);
const record = values[SEARCH_PARAM.record.stack];

const stack = useMemo(
() => record.map(parseRef).filter((ref): ref is RecordRef => ref !== null),
Expand All @@ -62,13 +63,14 @@ export function useRecordStack() {
(next: RecordRef[], history: "push" | "replace") => {
void setParams(
{
record: next.length === 0 ? null : next.map(recordKey),
tab: null,
add: null,
thread: null,
fields: null,
field: null,
[TIMELINE_PARAM]: null,
[SEARCH_PARAM.record.stack]:
next.length === 0 ? null : next.map(recordKey),
[SEARCH_PARAM.record.tab]: null,
[SEARCH_PARAM.record.add]: null,
[SEARCH_PARAM.record.thread]: null,
[SEARCH_PARAM.fieldsSheet.entity]: null,
[SEARCH_PARAM.fieldsSheet.field]: null,
[SEARCH_PARAM.record.timeline]: null,
},
{ history },
);
Expand Down Expand Up @@ -108,50 +110,66 @@ export function useOpenRecord() {
}

export function useFieldsSheet() {
const [{ fields, field }, setParams] = useQueryStates(params);
const [values, setParams] = useQueryStates(params);
const entity = values[SEARCH_PARAM.fieldsSheet.entity];
const field = values[SEARCH_PARAM.fieldsSheet.field];

const open = useCallback(
(kind: RecordKind) => void setParams({ fields: kind, field: null }),
(kind: RecordKind) =>
void setParams({
[SEARCH_PARAM.fieldsSheet.entity]: kind,
[SEARCH_PARAM.fieldsSheet.field]: null,
}),
[setParams],
);

const close = useCallback(
() => void setParams({ fields: null, field: null }),
() =>
void setParams({
[SEARCH_PARAM.fieldsSheet.entity]: null,
[SEARCH_PARAM.fieldsSheet.field]: null,
}),
[setParams],
);

const edit = useCallback(
(key: string | null) => void setParams({ field: key }),
(key: string | null) =>
void setParams({ [SEARCH_PARAM.fieldsSheet.field]: key }),
[setParams],
);

return { entity: fields, field, open, close, edit };
return { entity, field, open, close, edit };
}

export function useRecordSheetView(fallbackTab: string) {
const [{ tab, add, thread }, setParams] = useQueryStates(params);
const [values, setParams] = useQueryStates(params);
const tab = values[SEARCH_PARAM.record.tab];
const add = values[SEARCH_PARAM.record.add];
const thread = values[SEARCH_PARAM.record.thread];

const active = add ? FORM_TAB[add] : (tab ?? fallbackTab);

const setTab = useCallback(
(next: string) => {
void setParams({
tab: next === fallbackTab ? null : next,
add: null,
thread: null,
[TIMELINE_PARAM]: null,
[SEARCH_PARAM.record.tab]: next === fallbackTab ? null : next,
[SEARCH_PARAM.record.add]: null,
[SEARCH_PARAM.record.thread]: null,
[SEARCH_PARAM.record.timeline]: null,
});
},
[setParams, fallbackTab],
);

const setForm = useCallback(
(next: RecordForm | null) => void setParams({ add: next }),
(next: RecordForm | null) =>
void setParams({ [SEARCH_PARAM.record.add]: next }),
[setParams],
);

const setThread = useCallback(
(next: string | null) => void setParams({ thread: next }),
(next: string | null) =>
void setParams({ [SEARCH_PARAM.record.thread]: next }),
[setParams],
);

Expand Down
19 changes: 12 additions & 7 deletions apps/app/components/crm/stage-change.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -27,13 +27,14 @@ import { parseAsString, useQueryStates } from "nuqs";
import { useId, useState } from "react";
import { toast } from "sonner";
import { DEAL_STAGE_OPTIONS, LOSING_STAGES } from "@/lib/deal-stage";
import { SEARCH_PARAM } from "@/lib/search-param-keys";
import { useCrmCache } from "@/lib/trpc/cache";
import { useTRPC } from "@/lib/trpc/client";
import { DealStageIndicator } from "./deal-stage";

const closeReasonParams = {
closing: parseAsString,
closingStage: parseAsString,
[SEARCH_PARAM.dialog.closeDeal]: parseAsString,
[SEARCH_PARAM.dialog.closeStage]: parseAsString,
};

function useStageMutation(onDone?: () => void) {
Expand Down Expand Up @@ -99,8 +100,8 @@ export function DealStageMenu({
if (chosen === stage) return;
if (LOSING_STAGES.includes(chosen)) {
void setCloseParams({
closing: dealId,
closingStage: chosen,
[SEARCH_PARAM.dialog.closeDeal]: dealId,
[SEARCH_PARAM.dialog.closeStage]: chosen,
});
return;
}
Expand All @@ -120,13 +121,17 @@ export function DealStageMenu({

export function CloseReasonDialog() {
const reasonId = useId();
const [{ closing, closingStage }, setCloseParams] =
useQueryStates(closeReasonParams);
const [closeValues, setCloseParams] = useQueryStates(closeReasonParams);
const closing = closeValues[SEARCH_PARAM.dialog.closeDeal];
const closingStage = closeValues[SEARCH_PARAM.dialog.closeStage];
const [reason, setReason] = useState("");

const close = () => {
setReason("");
void setCloseParams({ closing: null, closingStage: null });
void setCloseParams({
[SEARCH_PARAM.dialog.closeDeal]: null,
[SEARCH_PARAM.dialog.closeStage]: null,
});
};

const setStage = useStageMutation(() => {
Expand Down
2 changes: 0 additions & 2 deletions apps/app/components/crm/timeline/timeline-search-params.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,6 @@ export const TIMELINE_TABS = [

export type TimelineTab = (typeof TIMELINE_TABS)[number];

export const TIMELINE_PARAM = "timeline";

export const timelineTabParser =
parseAsStringLiteral(TIMELINE_TABS).withDefault("all");

Expand Down
Loading
Loading