Skip to content

Commit

Permalink
feat: checklist in weekly planning with inbox zero, and upload financ…
Browse files Browse the repository at this point in the history
…ial data and projects
  • Loading branch information
Carsten Koch committed Nov 23, 2024
1 parent 7e5397a commit bb99960
Show file tree
Hide file tree
Showing 8 changed files with 190 additions and 23 deletions.
90 changes: 90 additions & 0 deletions api/useLatestUploadsWork.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
import { type Schema } from "@/amplify/data/resource";
import { generateClient, SelectionSet } from "aws-amplify/data";
import { differenceInCalendarDays } from "date-fns";
import { first, flow, get, identity } from "lodash/fp";
import useSWR from "swr";
import { handleApiErrors } from "./globals";
const client = generateClient<Schema>();

const selectionSet = ["createdAt"] as const;

type MrrLatestUploadData = SelectionSet<
Schema["MrrDataUpload"]["type"],
typeof selectionSet
>;

type SfdcLatestUploadData = SelectionSet<
Schema["CrmProjectImport"]["type"],
typeof selectionSet
>;

const isTooOld = (dateStr: string | undefined) =>
!dateStr || differenceInCalendarDays(new Date(), dateStr) >= 7;

const fetchSfdcLatestUpload = async () => {
const { data, errors } =
await client.models.CrmProjectImport.listByImportStatus(
{
status: "DONE",
},
{
sortDirection: "DESC",
limit: 1,
selectionSet,
}
);
if (errors) {
handleApiErrors(errors, "Loading SfdcLatestUpload failed");
throw errors;
}
try {
return flow(
identity<SfdcLatestUploadData[] | undefined>,
first,
get("createdAt"),
isTooOld
)(data);
} catch (error) {
console.error("fetchSfdcLatestUpload", error);
throw error;
}
};

const fetchMrrLatestUpload = async () => {
const { data, errors } =
await client.models.MrrDataUpload.listMrrDataUploadByStatusAndCreatedAt(
{ status: "DONE" },
{ sortDirection: "DESC", limit: 1, selectionSet }
);
if (errors) {
handleApiErrors(errors, "Loading MrrLatestUpload failed");
throw errors;
}
try {
return flow(
identity<MrrLatestUploadData[] | undefined>,
first,
get("createdAt"),
isTooOld
)(data);
} catch (error) {
console.error("fetchMrrLatestUpload", error);
throw error;
}
};

const useLatestUploadsWork = () => {
const { data: mrrUploadTooOld, mutate: mutateMrr } = useSWR(
"/api/mrr-latest",
fetchMrrLatestUpload
);

const { data: sfdcUploadTooOld, mutate: mutateSfdc } = useSWR(
"/api/sfdc-latest",
fetchSfdcLatestUpload
);

return { mrrUploadTooOld, mutateMrr, sfdcUploadTooOld, mutateSfdc };
};

export default useLatestUploadsWork;
19 changes: 17 additions & 2 deletions components/analytics/instructions/instructions-upload-mrr.tsx
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
import { MrrMutator } from "@/api/useMrr";
import imgDownload from "@/public/images/analytics/mrr-download.png";
import imgFilter from "@/public/images/analytics/mrr-filters.png";
import { ExternalLink } from "lucide-react";
import Image from "next/image";
import Link from "next/link";
import { FC } from "react";
import DefaultAccordionItem from "../../ui-elements/accordion/DefaultAccordionItem";
import BulletList from "../../ui-elements/list-items/bullet-list";
import { useMrrFilter } from "../useMrrFilter";
Expand All @@ -11,9 +13,22 @@ import ImportMrrData from "./import-data";
const mrrTableauLink =
"https://awstableau.corp.amazon.com/t/WWSalesInsights/views/MonthlyRevenueDeep/DeepMonthlyRevenue?%3Aembed=yes&%3Alinktarget=_blank&%3Aoriginal_view=yes#1";

const InstructionsUploadMrr = () => {
type InstructionsUploadMrrProps = {
reloader?: () => void;
};

const InstructionsUploadMrr: FC<InstructionsUploadMrrProps> = ({
reloader,
}) => {
const { mrr, mutateMrr } = useMrrFilter();

const reload: MrrMutator = (data) => {
if (reloader) {
reloader();
}
return mutateMrr(data);
};

return (
<DefaultAccordionItem value="revenue" triggerTitle="Monthly Revenue">
<div className="space-y-6">
Expand Down Expand Up @@ -67,7 +82,7 @@ const InstructionsUploadMrr = () => {

<div>Then upload the file here:</div>

<ImportMrrData mrr={mrr} mutateMrr={mutateMrr} />
<ImportMrrData mrr={mrr} mutateMrr={reload} />
</div>
</DefaultAccordionItem>
);
Expand Down
2 changes: 1 addition & 1 deletion components/analytics/useMrrFilter.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ interface MrrFilterProviderProps {
children: React.ReactNode;
}

const MrrFilterProvider: FC<MrrFilterProviderProps> = ({ children }) => {
export const MrrFilterProvider: FC<MrrFilterProviderProps> = ({ children }) => {
const [mrrFilter, setMrrFilter] = useState<MrrFilters>("6");
const { mrr, isLoading, error, mutate } = useMrr("DONE", mrrFilter);

Expand Down
29 changes: 25 additions & 4 deletions components/crm/import-project-data.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,9 @@ import {
} from "@/helpers/crm/filters";
import { cn } from "@/lib/utils";
import { flow, map, sum } from "lodash/fp";
import { Loader2 } from "lucide-react";
import { useEffect, useState } from "react";
import { ExternalLink, Loader2 } from "lucide-react";
import Link from "next/link";
import { FC, useEffect, useState } from "react";
import ApiLoadingError from "../layouts/ApiLoadingError";
import { Accordion } from "../ui/accordion";
import { Button } from "../ui/button";
Expand All @@ -19,7 +20,14 @@ import ChangedCrmProjects from "./changed-projects";
import MissingCrmProjects from "./missing-projects";
import NewCrmProjects from "./new-projects";

const ImportProjectData = () => {
const linkSfdcReport =
"https://aws-crm.lightning.force.com/lightning/r/Report/00ORU000000oksT2AQ/view";

type ImportProjectDataProps = {
reloader?: () => void;
};

const ImportProjectData: FC<ImportProjectDataProps> = ({ reloader }) => {
const { crmProjects, mutate } = useCrmProjects();
const {
crmProjectsImport,
Expand Down Expand Up @@ -78,12 +86,25 @@ const ImportProjectData = () => {
});
}, [crmProjects, processedData]);

const handleClose = async () => {
await closeImportFile();
reloader?.();
};

return (
<div className="space-y-6">
<ApiLoadingError title="Loading imports failed" error={errorImports} />

{!crmProjectsImport && (
<div className="space-y-2">
<div>
<Link href={linkSfdcReport} target="_blank">
<div className="flex flex-row items-baseline gap-1 text-muted-foreground font-semibold text-sm">
Link to SFDC opportunity report
<ExternalLink className="w-3 h-3" />
</div>
</Link>
</div>
{loadingImports ? (
<div className="text-muted-foreground text-sm font-semibold flex gap-2">
Loading status of imported data…
Expand Down Expand Up @@ -137,7 +158,7 @@ const ImportProjectData = () => {
)}

{crmProjectsImport && (
<Button onClick={closeImportFile}>Close import file</Button>
<Button onClick={handleClose}>Close import file</Button>
)}
</div>
);
Expand Down
13 changes: 13 additions & 0 deletions components/planning/week/PlanWeekAction.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import { FC } from "react";

type PlanWeekActionProps = {
label: string;
};

const PlanWeekAction: FC<PlanWeekActionProps> = ({ label }) => (
<div className="border-2 border-[--context-color] rounded-md flex justify-center p-1 font-semibold">
Next Action: {label}
</div>
);

export default PlanWeekAction;
8 changes: 1 addition & 7 deletions components/planning/week/PlanWeekStatistics.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,14 +8,8 @@ const PlanWeekStatistics = () => {

return (
<div className="mx-2 md:mx-4 my-8 font-semibold text-sm text-muted-foreground md:text-center">
{!weekPlan ? (
"Start Week Planning to review a list of projects for the current context."
) : (
{weekPlan && (
<div>
<div>
Review each project and decide if you can make progress here during
the next week.
</div>
<div>Projects to be reviewed: {openProjectsCount}</div>
<div>Projects on hold: {onholdProjectsCount}</div>
<div>Projects in focus: {focusProjectsCount}</div>
Expand Down
5 changes: 2 additions & 3 deletions docs/releases/next.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,15 +4,14 @@
- Neue Inbox Einträge können nun mit Cmd+Enter gespeichert werden.
- Der Workflow für Inbox-Einträge ist vollständig überarbeitet und insgesamt schlüssiger und schneller. Die getroffene Entscheidung wird ausschließlich am Ende gespeichert und nicht mehr zwischendurch.
- Inbox-Einträge können nun auch als Gelerntes über Personen gespeichert werden.
- In der Wochenplanung ist nun eine kleine Checkliste eingeführt. Zunächst werden offene Inbox-Einträge verarbeitet, dann aktuelle Umsätze und Projekte der Kunden geladen und schließlich – wie zuvor auch – die Projekte überprüft.

## Kleinere Verbesserungen

- Im Dialog zum Erstellen neuer Aufgaben muss nun nicht mehr der Speichern-Button gedrückt werden; es kann nun auch mit der Tastenkombination Cmd+Enter gespeichert werden.

## In Arbeit

- In der Wochenplanung direkt auch anbieten, die Inbox zu verarbeiten.

## Geplant

### Account Details
Expand All @@ -38,7 +37,7 @@

- In Wochenplanung persönliche Termine mit berücksichtigen (Geburtstage, Jahrestage).
- Ich möchte einfache Todos haben, die keinem Projekt zugeordnet sind.
- Eine Checkliste einführen für das wöchentliche oder tägliche Planen.
- Eine Checkliste einführen für das tägliche Planen.

### Projekte

Expand Down
47 changes: 41 additions & 6 deletions pages/planweek.tsx
Original file line number Diff line number Diff line change
@@ -1,3 +1,9 @@
import useInbox from "@/api/useInbox";
import useMrrLatestUpload from "@/api/useLatestUploadsWork";
import InstructionsUploadMrr from "@/components/analytics/instructions/instructions-upload-mrr";
import { MrrFilterProvider } from "@/components/analytics/useMrrFilter";
import ImportProjectData from "@/components/crm/import-project-data";
import ProcessInboxItem from "@/components/inbox/ProcessInboxItem";
import ApiLoadingError from "@/components/layouts/ApiLoadingError";
import MainLayout from "@/components/layouts/MainLayout";
import ContextSwitcher from "@/components/navigation-menu/ContextSwitcher";
Expand All @@ -6,16 +12,21 @@ import {
useWeekPlanContext,
withWeekPlan,
} from "@/components/planning/useWeekPlanContext";
import PlanWeekAction from "@/components/planning/week/PlanWeekAction";
import PlanWeekContextNotWork from "@/components/planning/week/PlanWeekContextNotWork";
import PlanWeekContextWork from "@/components/planning/week/PlanWeekContextWork";
import PlanWeekFilter from "@/components/planning/week/PlanWeekFilter";
import PlanWeekForm from "@/components/planning/week/PlanWeekForm";
import PlanWeekStatistics from "@/components/planning/week/PlanWeekStatistics";
import { Accordion } from "@/components/ui/accordion";
import { useContextContext } from "@/contexts/ContextContext";

const WeeklyPlanningPage = () => {
const { context } = useContextContext();
const { error } = useWeekPlanContext();
const { inbox } = useInbox();
const { mrrUploadTooOld, mutateMrr, sfdcUploadTooOld, mutateSfdc } =
useMrrLatestUpload();

return (
<MainLayout title="Weekly Planning" sectionName="Weekly Planning">
Expand All @@ -28,14 +39,38 @@ const WeeklyPlanningPage = () => {
<ContextSwitcher />
</div>

<PlanningProjectFilterProvider>
<PlanWeekStatistics />
{inbox && inbox.length > 0 ? (
<>
<PlanWeekAction label="Process Inbox Items" />
<ProcessInboxItem />
</>
) : context === "work" && mrrUploadTooOld ? (
<>
<PlanWeekAction label="Upload Customer Financials" />
<MrrFilterProvider>
<Accordion type="single" collapsible>
<InstructionsUploadMrr reloader={mutateMrr} />
</Accordion>
</MrrFilterProvider>
</>
) : context === "work" && sfdcUploadTooOld ? (
<>
<PlanWeekAction label="Upload Salesforce Opportunities" />
<ImportProjectData reloader={mutateSfdc} />
</>
) : (
<>
<PlanWeekAction label="Review Projects" />
<PlanningProjectFilterProvider>
<PlanWeekStatistics />

<PlanWeekFilter />
<PlanWeekFilter />

{context !== "work" && <PlanWeekContextNotWork />}
{context === "work" && <PlanWeekContextWork />}
</PlanningProjectFilterProvider>
{context !== "work" && <PlanWeekContextNotWork />}
{context === "work" && <PlanWeekContextWork />}
</PlanningProjectFilterProvider>
</>
)}
</div>
</MainLayout>
);
Expand Down

0 comments on commit bb99960

Please sign in to comment.