Skip to content

Commit

Permalink
Merge pull request #71 from cabcookie/staging
Browse files Browse the repository at this point in the history
Inbox Workflow optimieren und Editieren verlässlicher machen
  • Loading branch information
cabcookie authored May 22, 2024
2 parents a38967e + 2daa2ea commit 283169a
Show file tree
Hide file tree
Showing 21 changed files with 609 additions and 461 deletions.
9 changes: 4 additions & 5 deletions api/useCrmProject.ts
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
import { type Schema } from "@/amplify/data/resource";
import { getDayOfDate } from "@/helpers/functional";
import { generateClient } from "aws-amplify/data";
import useSWR from "swr";
import { useProjectsContext } from "./ContextProjects";
import { handleApiErrors } from "./globals";
import {
CrmProject,
mapCrmProject,
selectionSetCrmProject,
} from "./useCrmProjects";
import { getDayOfDate } from "@/helpers/functional";
import { handleApiErrors } from "./globals";
import { useProjectsContext } from "./ContextProjects";
const client = generateClient<Schema>();

const fetchCrmProject = (projectId?: string) => async () => {
Expand All @@ -27,7 +27,6 @@ const useCrmProject = (projectId?: string) => {
data: crmProject,
error: errorCrmProject,
isLoading: loadingCrmProject,
mutate,
} = useSWR(`/api/crm-projects/${projectId}`, fetchCrmProject(projectId));
const { projects, mutateProjects } = useProjectsContext();

Expand All @@ -46,7 +45,7 @@ const useCrmProject = (projectId?: string) => {
return;
}
if (!newProject) return;
const { data, errors } = await client.models.CrmProjectProjects.create({
const { errors } = await client.models.CrmProjectProjects.create({
projectId: project.projectIds[0],
crmProjectId: newProject.id,
});
Expand Down
90 changes: 5 additions & 85 deletions api/useInbox.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ export type Inbox = {

type MapInboxFn = (data: Schema["Inbox"]["type"]) => Inbox;

const mapInbox: MapInboxFn = ({
export const mapInbox: MapInboxFn = ({
id,
note,
createdAt,
Expand All @@ -62,42 +62,31 @@ const mapInbox: MapInboxFn = ({
createdAt: new Date(createdAt),
});

const fetchInbox = (status: InboxStatus) => async () => {
const fetchInbox = async () => {
const { data, errors } = await client.models.Inbox.listInboxByStatus({
status,
status: "new",
});
if (errors) throw errors;
return data
.map(mapInbox)
.sort((a, b) => a.createdAt.getTime() - b.createdAt.getTime());
};

const useInbox = (status?: InboxStatus) => {
const useInbox = () => {
const {
data: inbox,
error: errorInbox,
mutate,
} = useSWR(`/api/inbox/${status}`, fetchInbox(status || "new"));
} = useSWR("/api/inbox", fetchInbox);

const createInbox = async (note: EditorJsonContent) => {
const updated: Inbox[] = [
...(inbox || []),
{
id: crypto.randomUUID(),
note,
status: "new",
createdAt: new Date(),
},
];
mutate(updated, false);
const { data, errors } = await client.models.Inbox.create({
noteJson: JSON.stringify(note),
note: null,
formatVersion: 2,
status: "new",
});
if (errors) handleApiErrors(errors, "Error creating inbox item");
mutate(updated);
return data?.id;
};

Expand All @@ -117,80 +106,11 @@ const useInbox = (status?: InboxStatus) => {
return data?.id;
};

const moveInboxItemToProject = async (
inboxId: string,
createdAt: Date,
notes: EditorJsonContent,
projectId: string
) => {
const { data: activity, errors: activityErrors } =
await client.models.Activity.create({
finishedOn: createdAt.toISOString(),
formatVersion: 2,
notes: null,
notesJson: JSON.stringify(notes),
});
if (activityErrors)
return handleApiErrors(
activityErrors,
"Error creating activity with inbox notes"
);
if (!activity) return;

const { errors: projectActivityErrors } =
await client.models.ProjectActivity.create({
activityId: activity.id,
projectsId: projectId,
});
if (projectActivityErrors)
return handleApiErrors(
projectActivityErrors,
"Error linking activity with project"
);

const { data, errors } = await client.models.Inbox.update({
id: inboxId,
status: "done",
movedToActivityId: activity.id,
});
if (errors)
return handleApiErrors(errors, "Error updating status of inbox item");

return data?.id;
};

const updateStatus = async (id: string, status: InboxStatus) => {
const updated = inbox?.map((item) =>
item.id !== id ? item : { ...item, status }
);
mutate(updated, false);
const { data, errors } = await client.models.Inbox.update({ id, status });
if (errors) handleApiErrors(errors, "Can't update status");
mutate(updated);
return data?.id;
};

const makeActionable = (id: string) => updateStatus(id, "actionable");
const makeNonActionable = (id: string) => updateStatus(id, "notActionable");
const doNow = (id: string) => updateStatus(id, "doNow");
const clarifyAction = (id: string) => updateStatus(id, "clarifyAction");
const isDone = (id: string) => updateStatus(id, "done");
const moveToProject = (id: string) => updateStatus(id, "moveToProject");
const clarifyDeletion = (id: string) => updateStatus(id, "clarifyDeletion");

return {
inbox,
errorInbox,
createInbox,
updateNote,
makeActionable,
makeNonActionable,
doNow,
clarifyAction,
isDone,
moveToProject,
clarifyDeletion,
moveInboxItemToProject,
};
};

Expand Down
97 changes: 97 additions & 0 deletions api/useInboxItem.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
import { type Schema } from "@/amplify/data/resource";
import { EditorJsonContent } from "@/components/ui-elements/notes-writer/NotesWriter";
import { generateClient } from "aws-amplify/data";
import useSWR from "swr";
import { handleApiErrors } from "./globals";
import { InboxStatus, mapInbox } from "./useInbox";
const client = generateClient<Schema>();

const fetchInboxItem = (itemId?: string) => async () => {
if (!itemId) return;
const { data, errors } = await client.models.Inbox.get({ id: itemId });
if (errors) throw errors;
if (!data) throw new Error("fetchInboxItem didn't retrieve data");
return mapInbox(data);
};

const useInboxItem = (itemId?: string) => {
const {
data: inboxItem,
error: errorInboxItem,
isLoading: loadingInboxItem,
mutate,
} = useSWR(`/api/inbox/${itemId}`, fetchInboxItem(itemId));

const updateNote = async (id: string, note: EditorJsonContent) => {
const { data, errors } = await client.models.Inbox.update({
id,
note: null,
formatVersion: 2,
noteJson: JSON.stringify(note),
});
if (errors) handleApiErrors(errors, "Error updating inbox item");
if (!data) return;
const updated = mapInbox(data);
mutate(updated);
return data.id;
};

const moveInboxItemToProject = async (projectId: string) => {
if (!inboxItem) return;

const { data: activity, errors: activityErrors } =
await client.models.Activity.create({
finishedOn: inboxItem.createdAt.toISOString(),
formatVersion: 2,
notes: null,
notesJson: JSON.stringify(inboxItem.note),
});
if (activityErrors)
return handleApiErrors(
activityErrors,
"Error creating activity with inbox notes"
);
if (!activity) return;

const { errors: projectActivityErrors } =
await client.models.ProjectActivity.create({
activityId: activity.id,
projectsId: projectId,
});
if (projectActivityErrors)
return handleApiErrors(
projectActivityErrors,
"Error linking activity with project"
);

const { data, errors } = await client.models.Inbox.update({
id: inboxItem.id,
status: "done",
movedToActivityId: activity.id,
});

if (errors)
return handleApiErrors(errors, "Error updating status of inbox item");
return data?.id;
};

const updateStatus = async (id: string, status: InboxStatus) => {
if (inboxItem) mutate({ ...inboxItem, status }, false);
const { data, errors } = await client.models.Inbox.update({ id, status });
if (errors) handleApiErrors(errors, "Can't update status");
if (!data) return;
mutate(mapInbox(data));
return data.id;
};

return {
inboxItem,
errorInboxItem,
loadingInboxItem,
updateNote,
moveInboxItemToProject,
updateStatus,
};
};

export default useInboxItem;
4 changes: 0 additions & 4 deletions components/activities/activity.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,6 @@ const ActivityComponent: FC<ActivityComponentProps> = ({
createActivity,
}) => {
const { activity, updateNotes, updateDate } = useActivity(activityId);
const [notesSaved, setNotesSaved] = useState(true);
const [dateSaved, setDateSaved] = useState(true);
const [date, setDate] = useState(activity?.finishedOn || new Date());

Expand All @@ -39,9 +38,7 @@ const ActivityComponent: FC<ActivityComponentProps> = ({
}, [activity]);

const handleNotesUpdate = (serializer: () => SerializerOutput) => {
setNotesSaved(false);
debouncedUpdateNotes({
setSaveStatus: setNotesSaved,
updateNotes,
createActivity,
serializer,
Expand Down Expand Up @@ -75,7 +72,6 @@ const ActivityComponent: FC<ActivityComponentProps> = ({
<NotesWriter
notes={activity?.notes}
saveNotes={handleNotesUpdate}
unsaved={!notesSaved}
autoFocus={autoFocus}
key={activityId}
/>
Expand Down
45 changes: 45 additions & 0 deletions components/inbox/ClarifyAction.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
import { FC, useState } from "react";
import SubmitButton from "../ui-elements/buttons/submit-button";
import ProjectDetails from "../ui-elements/project-details/project-details";
import ProjectSelector from "../ui-elements/project-selector";
import ProjectName from "../ui-elements/tokens/project-name";
import styles from "./Inbox.module.css";
import { WorkflowStepComponentProps } from "./workflow";

const ClarifyAction: FC<WorkflowStepComponentProps> = ({
responses,
action,
}) => {
const [selectedProject, setSelectedProject] = useState<string | null>(null);

const respondProjectSelected = async (projectId: string | null) => {
if (!projectId) return;
if (!responses) return;
if (responses.length !== 1 && responses[0].response !== "next") return;
await action(responses[0], projectId);
};

return (
<div>
<ProjectSelector
placeholder="Select project…"
onChange={setSelectedProject}
allowCreateProjects
/>
{selectedProject && (
<div>
<ProjectName projectId={selectedProject} />
<ProjectDetails projectId={selectedProject} />
<SubmitButton onClick={() => respondProjectSelected(selectedProject)}>
Confirm Changes
</SubmitButton>
</div>
)}
<div className={styles.spacer}>
<strong>Inbox Notes (will be moved to selected project):</strong>
</div>
</div>
);
};

export default ClarifyAction;
36 changes: 36 additions & 0 deletions components/inbox/Inbox.module.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
.spacer {
margin-top: 3rem;
}

.question {
font-size: var(--font-size-x-large);
display: flex;
flex-direction: row;
vertical-align: middle;
font-weight: bold;
color: var(--color-btn);
margin-top: -0.6rem;
gap: 1rem;
}

.decisionBtns {
font-weight: normal;
font-size: var(--font-size-large);
display: flex;
flex-direction: row;
vertical-align: middle;
margin-top: -0.4rem;
gap: 0.4rem;
}

.positive {
background-color: var(--secondary-button-bg-color);
}

.negative {
background-color: var(--primary-button-bg-color);
}

.small {
font-size: var(--font-size-small);
}
Loading

0 comments on commit 283169a

Please sign in to comment.