diff --git a/api/useCrmProject.ts b/api/useCrmProject.ts index 40d3dbeb8..62f314f61 100644 --- a/api/useCrmProject.ts +++ b/api/useCrmProject.ts @@ -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(); const fetchCrmProject = (projectId?: string) => async () => { @@ -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(); @@ -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, }); diff --git a/api/useInbox.tsx b/api/useInbox.tsx index b442d138c..5eea4f2a5 100644 --- a/api/useInbox.tsx +++ b/api/useInbox.tsx @@ -44,7 +44,7 @@ export type Inbox = { type MapInboxFn = (data: Schema["Inbox"]["type"]) => Inbox; -const mapInbox: MapInboxFn = ({ +export const mapInbox: MapInboxFn = ({ id, note, createdAt, @@ -62,9 +62,9 @@ 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 @@ -72,24 +72,14 @@ const fetchInbox = (status: InboxStatus) => async () => { .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, @@ -97,7 +87,6 @@ const useInbox = (status?: InboxStatus) => { status: "new", }); if (errors) handleApiErrors(errors, "Error creating inbox item"); - mutate(updated); return data?.id; }; @@ -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, }; }; diff --git a/api/useInboxItem.tsx b/api/useInboxItem.tsx new file mode 100644 index 000000000..e74a1a03e --- /dev/null +++ b/api/useInboxItem.tsx @@ -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(); + +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; diff --git a/components/activities/activity.tsx b/components/activities/activity.tsx index 5398b3d0d..14ea9173f 100644 --- a/components/activities/activity.tsx +++ b/components/activities/activity.tsx @@ -30,7 +30,6 @@ const ActivityComponent: FC = ({ 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()); @@ -39,9 +38,7 @@ const ActivityComponent: FC = ({ }, [activity]); const handleNotesUpdate = (serializer: () => SerializerOutput) => { - setNotesSaved(false); debouncedUpdateNotes({ - setSaveStatus: setNotesSaved, updateNotes, createActivity, serializer, @@ -75,7 +72,6 @@ const ActivityComponent: FC = ({ diff --git a/components/inbox/ClarifyAction.tsx b/components/inbox/ClarifyAction.tsx new file mode 100644 index 000000000..282f78c4c --- /dev/null +++ b/components/inbox/ClarifyAction.tsx @@ -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 = ({ + responses, + action, +}) => { + const [selectedProject, setSelectedProject] = useState(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 ( +
+ + {selectedProject && ( +
+ + + respondProjectSelected(selectedProject)}> + Confirm Changes + +
+ )} +
+ Inbox Notes (will be moved to selected project): +
+
+ ); +}; + +export default ClarifyAction; diff --git a/components/inbox/Inbox.module.css b/components/inbox/Inbox.module.css new file mode 100644 index 000000000..b5820609a --- /dev/null +++ b/components/inbox/Inbox.module.css @@ -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); +} diff --git a/components/inbox/Question.tsx b/components/inbox/Question.tsx new file mode 100644 index 000000000..f9701799a --- /dev/null +++ b/components/inbox/Question.tsx @@ -0,0 +1,27 @@ +import { FC } from "react"; +import SubmitButton from "../ui-elements/buttons/submit-button"; +import styles from "./Inbox.module.css"; +import { WorkflowStepComponentProps } from "./workflow"; + +const Question: FC = ({ + question, + responses, + action, +}) => ( +
+ {question} +
+ {responses?.map((response) => ( + action(response)} + btnClassName={response.responseClassName} + > + {response.response} + + ))} +
+
+); + +export default Question; diff --git a/components/inbox/WorkflowItem.tsx b/components/inbox/WorkflowItem.tsx new file mode 100644 index 000000000..f419b1dad --- /dev/null +++ b/components/inbox/WorkflowItem.tsx @@ -0,0 +1,88 @@ +import useInboxItem from "@/api/useInboxItem"; +import { debouncedOnChangeInboxNote } from "@/pages/inbox"; +import { useRouter } from "next/router"; +import { FC, useEffect, useState } from "react"; +import SubmitButton from "../ui-elements/buttons/submit-button"; +import NotesWriter, { + SerializerOutput, +} from "../ui-elements/notes-writer/NotesWriter"; +import styles from "./Inbox.module.css"; +import { + WorkflowStepResponse, + getPreviousStatusByStatus, + getWorkflowStepByStatus, + workflow, +} from "./workflow"; + +type WorkFlowItemProps = { + inboxItemId: string; + forwardUrl?: string; +}; + +const WorkFlowItem: FC = ({ inboxItemId, forwardUrl }) => { + const router = useRouter(); + const { inboxItem, updateNote, updateStatus, moveInboxItemToProject } = + useInboxItem(inboxItemId); + const [step, setStep] = useState( + getWorkflowStepByStatus(workflow, inboxItem?.status) + ); + const [prevStatus, setPrevStatus] = useState( + getPreviousStatusByStatus(workflow, inboxItem?.status || "new") + ); + + useEffect(() => { + if (!inboxItem) return; + setStep(getWorkflowStepByStatus(workflow, inboxItem.status)); + setPrevStatus(getPreviousStatusByStatus(workflow, inboxItem.status)); + }, [inboxItem]); + + const handleUpdate = (serializer: () => SerializerOutput) => { + debouncedOnChangeInboxNote(inboxItemId, serializer, updateNote); + }; + + const goBack = async () => { + if (!prevStatus) return; + await updateStatus(inboxItemId, prevStatus); + }; + + const startProcessingItem = async ( + response: WorkflowStepResponse, + projectId?: string + ) => { + if (!response.nextStep) return; + if (projectId) { + const result = await moveInboxItemToProject(projectId); + if (!result) return; + } else { + const result = await updateStatus(inboxItemId, response.nextStep.status); + if (!result) return; + } + + if (forwardUrl) router.push(forwardUrl); + if (response.nextStep.toHome) router.push("/inbox"); + }; + + return !inboxItem ? ( + "Loading inbox item…" + ) : !step ? ( + "Loading workflow…" + ) : ( +
+ {inboxItem.status !== "new" && ( + + Return to previous step + + )} + {step.component && ( + + )} + +
+ ); +}; + +export default WorkFlowItem; diff --git a/components/inbox/workflow.tsx b/components/inbox/workflow.tsx new file mode 100644 index 000000000..e4083fc5f --- /dev/null +++ b/components/inbox/workflow.tsx @@ -0,0 +1,182 @@ +import { InboxStatus } from "@/api/useInbox"; +import ClarifyAction from "./ClarifyAction"; +import styles from "./Inbox.module.css"; +import Question from "./Question"; + +export type WorkflowStepComponentProps = { + question?: string; + responses?: WorkflowStepResponse[]; + action: (response: WorkflowStepResponse, projectId?: string) => void; +}; + +export type WorkflowStepResponse = { + response: string; + responseClassName?: string; + nextStep?: WorkflowStep; +}; + +export type WorkflowStep = { + status: InboxStatus; + question?: string; + toHome?: boolean; + action?: (id: string, setting?: any) => void; + component?: React.FC; + responses?: WorkflowStepResponse[]; +}; + +export const workflow: WorkflowStep = { + status: "new", + question: "Is it actionable?", + component: Question, + responses: [ + { + response: "Yes", + responseClassName: styles.positive, + nextStep: { + status: "actionable", + question: "Doable in 2 minutes?", + component: Question, + responses: [ + { + response: "Yes", + responseClassName: styles.positive, + nextStep: { + status: "doNow", + question: "Done?", + component: Question, + responses: [ + { + response: "Yes", + responseClassName: styles.positive, + nextStep: { + status: "done", + toHome: true, + }, + }, + ], + }, + }, + { + response: "No", + responseClassName: styles.negative, + nextStep: { + status: "clarifyAction", + component: ClarifyAction, + responses: [ + { + response: "next", + nextStep: { status: "done", toHome: true }, + }, + ], + }, + }, + ], + }, + }, + { + response: "No", + responseClassName: styles.negative, + nextStep: { + status: "notActionable", + question: "Move to a project?", + component: Question, + responses: [ + { + response: "Yes", + responseClassName: styles.positive, + nextStep: { + status: "moveToProject", + component: ClarifyAction, + responses: [ + { + response: "next", + nextStep: { status: "done", toHome: true }, + }, + ], + }, + }, + { + response: "No", + responseClassName: styles.negative, + nextStep: { + status: "clarifyDeletion", + question: "Confirm deletion:", + component: Question, + responses: [ + { + response: "Yes", + responseClassName: styles.negative, + nextStep: { status: "done", toHome: true }, + }, + ], + }, + }, + ], + }, + }, + ], +}; + +export const getWorkflowStepByStatus = ( + workflowStep: WorkflowStep, + desiredStatus?: InboxStatus +): WorkflowStep | null => { + if (!desiredStatus) { + return workflowStep; + } + + if (workflowStep.status === desiredStatus) { + return workflowStep; + } + + // If there are responses, iterate over them to find the next steps + if (workflowStep.responses) { + for (const response of workflowStep.responses) { + if (response.nextStep) { + // Recursively search in the next steps + const foundStep = getWorkflowStepByStatus( + response.nextStep, + desiredStatus + ); + if (foundStep) { + return foundStep; + } + } + } + } + + // Return null if the step is not found + return null; +}; + +// Function to find the previous status by a given status +export const getPreviousStatusByStatus = ( + workflowStep: WorkflowStep, + currentStatus: InboxStatus, + parentStatus: InboxStatus | null = null +): InboxStatus | null => { + // Check if the current step matches the desired status + if (workflowStep.status === currentStatus) { + return parentStatus; + } + + // If there are responses, iterate over them to find the next steps + if (workflowStep.responses) { + for (const response of workflowStep.responses) { + if (response.nextStep) { + // Recursively search in the next steps, passing the current status as parentStatus + const foundStatus = getPreviousStatusByStatus( + response.nextStep, + currentStatus, + workflowStep.status + ); + if (foundStatus) { + return foundStatus; + } + } + } + } + + // Return null if the status is not found + return null; +}; diff --git a/components/ui-elements/account-details/account-updates-helpers.ts b/components/ui-elements/account-details/account-updates-helpers.ts index fd470cb93..0a27e2b87 100644 --- a/components/ui-elements/account-details/account-updates-helpers.ts +++ b/components/ui-elements/account-details/account-updates-helpers.ts @@ -13,21 +13,18 @@ type UpdateFnProps = { type UpdateAccountDetailsProps = UpdateFnProps & { serializeIntroduction?: () => SerializerOutput; updateAccountFn: (props: UpdateFnProps) => Promise; - setSaveStatus: (status: boolean) => void; }; export const debouncedUpdateAccountDetails = debounce( async ({ updateAccountFn, - setSaveStatus, serializeIntroduction, ...props }: UpdateAccountDetailsProps) => { - const data = await updateAccountFn({ + await updateAccountFn({ ...props, introduction: serializeIntroduction?.().json, }); - if (data) setSaveStatus(true); }, 1500 ); diff --git a/components/ui-elements/activity-helper.ts b/components/ui-elements/activity-helper.ts index c480d4808..46b016bbf 100644 --- a/components/ui-elements/activity-helper.ts +++ b/components/ui-elements/activity-helper.ts @@ -6,7 +6,6 @@ import { type DebouncedUpdateNotesProps = { serializer: () => SerializerOutput; - setSaveStatus: (status: boolean) => void; updateNotes: (notes: EditorJsonContent) => Promise; createActivity?: (notes: EditorJsonContent) => Promise; }; @@ -14,18 +13,12 @@ type DebouncedUpdateNotesProps = { export const debouncedUpdateNotes = debounce( async ({ serializer, - setSaveStatus, updateNotes, createActivity, }: DebouncedUpdateNotesProps) => { const { json: notes } = serializer(); - if (createActivity) { - const newActivity = await createActivity(notes); - if (newActivity) setSaveStatus(true); - return; - } - const data = await updateNotes(notes); - if (data) setSaveStatus(true); + if (createActivity) return await createActivity(notes); + await updateNotes(notes); }, 1000 ); diff --git a/components/ui-elements/notes-writer/NotesWriter.tsx b/components/ui-elements/notes-writer/NotesWriter.tsx index 20509aa6a..11faa1e4c 100644 --- a/components/ui-elements/notes-writer/NotesWriter.tsx +++ b/components/ui-elements/notes-writer/NotesWriter.tsx @@ -4,7 +4,8 @@ import Link from "@tiptap/extension-link"; import Placeholder from "@tiptap/extension-placeholder"; import { EditorContent, useEditor } from "@tiptap/react"; import StarterKit from "@tiptap/starter-kit"; -import { FC, useEffect, useState } from "react"; +import { isEqual } from "lodash"; +import { FC, useEffect } from "react"; import styles from "./NotesWriter.module.css"; export type EditorJsonContent = JSONContent; @@ -28,23 +29,18 @@ export const transformNotesVersion = ({ type NotesWriterProps = { notes?: EditorJsonContent | string; saveNotes?: (serializer: () => SerializerOutput) => void; - unsaved?: boolean; autoFocus?: boolean; placeholder?: string; - submitOnEnter?: boolean; + onSubmit?: (item: EditorJsonContent) => void; }; const NotesWriter: FC = ({ notes, saveNotes, - unsaved, autoFocus, placeholder = "Start taking notes...", - // submitOnEnter, + onSubmit, }) => { - const [isSaved, setIsSaved] = useState(!unsaved); - const [initialNotes, setInitialNotes] = useState(notes); - const editor = useEditor({ extensions: [ StarterKit, @@ -62,7 +58,16 @@ const NotesWriter: FC = ({ autofocus: autoFocus, editorProps: { attributes: { - class: `${styles.editor} ${isSaved ? "" : styles.unsaved}`, + class: styles.editor, + }, + handleKeyDown: (view, event) => { + if (!onSubmit) return false; + if (event.metaKey && event.key === "Enter") { + event.preventDefault(); + onSubmit(view.state.doc.toJSON()); + return true; + } + return false; }, }, content: notes, @@ -74,25 +79,21 @@ const NotesWriter: FC = ({ useEffect(() => { if (!editor) return; - if (unsaved !== isSaved) return; + if (editor.getText() === "" && notes) editor.commands.setContent(notes); + }, [editor, notes]); + + useEffect(() => { + if (!editor) return; editor.setOptions({ editorProps: { attributes: { - class: `${styles.editor} ${unsaved ? styles.unsaved : ""}`, + class: `${styles.editor} ${ + isEqual(notes, editor.getJSON()) ? "" : styles.unsaved + }`, }, }, }); - setIsSaved(!unsaved); - }, [editor, unsaved, isSaved]); - - useEffect(() => { - if (!editor) return; - if (initialNotes === notes) return; - const { from, to } = editor.state.selection; - editor.commands.setContent(notes || ""); - editor.commands.setTextSelection({ from, to }); - setInitialNotes(notes); - }, [editor, notes, initialNotes]); + }, [editor?.getJSON(), notes]); return (
diff --git a/components/ui-elements/project-details/next-actions.tsx b/components/ui-elements/project-details/next-actions.tsx index 4dbf4cd7c..6cc8ae169 100644 --- a/components/ui-elements/project-details/next-actions.tsx +++ b/components/ui-elements/project-details/next-actions.tsx @@ -1,4 +1,4 @@ -import { FC, ReactNode, useState } from "react"; +import { FC, ReactNode } from "react"; import NotesWriter, { EditorJsonContent, SerializerOutput, @@ -27,13 +27,9 @@ const NextActionHelper: FC = ({ saveFn, title, }) => { - const [saved, setSaved] = useState(true); - const handleNextActionsUpdate = (serializer: () => SerializerOutput) => { - setSaved(false); debouncedUpdateActions({ serializer, - setSaveStatus: setSaved, updateActions: saveFn, }); }; @@ -42,7 +38,6 @@ const NextActionHelper: FC = ({ diff --git a/components/ui-elements/project-details/project-updates-helpers.ts b/components/ui-elements/project-details/project-updates-helpers.ts index 7e5feda97..dac42ad7c 100644 --- a/components/ui-elements/project-details/project-updates-helpers.ts +++ b/components/ui-elements/project-details/project-updates-helpers.ts @@ -6,15 +6,13 @@ import { type UpdateActionsProps = { serializer: () => SerializerOutput; - setSaveStatus: (status: boolean) => void; updateActions: (actions: EditorJsonContent) => Promise; }; export const debouncedUpdateActions = debounce( - async ({ serializer, setSaveStatus, updateActions }: UpdateActionsProps) => { + async ({ serializer, updateActions }: UpdateActionsProps) => { const { json: actions } = serializer(); - const data = await updateActions(actions); - if (data) setSaveStatus(true); + await updateActions(actions); }, 1000 ); diff --git a/components/ui-elements/project-notes-form/project-notes-form.tsx b/components/ui-elements/project-notes-form/project-notes-form.tsx index 84df66419..02e5ff979 100644 --- a/components/ui-elements/project-notes-form/project-notes-form.tsx +++ b/components/ui-elements/project-notes-form/project-notes-form.tsx @@ -1,5 +1,5 @@ import useActivity from "@/api/useActivity"; -import { FC, useState } from "react"; +import { FC } from "react"; import { debouncedUpdateNotes } from "../activity-helper"; import ActivityMetaData from "../activity-meta-data"; import NotesWriter, { @@ -10,7 +10,6 @@ import ProjectDetails from "../project-details/project-details"; import ProjectSelector from "../project-selector"; import RecordDetails from "../record-details/record-details"; import ProjectName from "../tokens/project-name"; -import SavedState from "./saved-state"; type ProjectNotesFormProps = { className?: string; @@ -25,7 +24,6 @@ const ProjectNotesForm: FC = ({ }) => { const { activity, updateNotes, addProjectToActivity } = useActivity(activityId); - const [notesSaved, setNotesSaved] = useState(true); const handleSelectProject = async (projectId: string | null) => { if (!projectId) return; @@ -41,10 +39,8 @@ const ProjectNotesForm: FC = ({ const handleNotesUpdate = (serializer: () => SerializerOutput) => { if (!updateNotes) return; - setNotesSaved(false); debouncedUpdateNotes({ serializer, - setSaveStatus: setNotesSaved, updateNotes, createActivity, }); @@ -66,13 +62,11 @@ const ProjectNotesForm: FC = ({
-
); diff --git a/components/ui-elements/status-selector/status-selector.tsx b/components/ui-elements/status-selector/status-selector.tsx deleted file mode 100644 index 260bb1fa2..000000000 --- a/components/ui-elements/status-selector/status-selector.tsx +++ /dev/null @@ -1,40 +0,0 @@ -import { FC, useEffect, useState } from "react"; -import Select from "react-select"; - -type StatusSelectorProps = { - options: string[]; - value: string; - onChange: (selected: string) => void; -}; - -const StatusSelector: FC = ({ - options, - value, - onChange, -}) => { - const [mappedOptions] = useState( - options.map((o) => ({ - value: o, - label: o - .replace(/([A-Z])/g, " $1") - .replace(/^./, (str) => str.toUpperCase()), - })) - ); - const [selected, setSelected] = useState( - mappedOptions.find((o) => o.value === value) - ); - - useEffect(() => { - setSelected(mappedOptions.find((o) => o.value === value)); - }, [mappedOptions, value]); - - const selectStatus = (selectedOption: any) => { - onChange(selectedOption.value); - }; - - return ( -