diff --git a/components/pages/Goals/ArchivePage/index.tsx b/components/pages/Goals/ArchivePage/index.tsx
new file mode 100644
index 00000000..8ade8897
--- /dev/null
+++ b/components/pages/Goals/ArchivePage/index.tsx
@@ -0,0 +1,14 @@
+import React from 'react';
+import { observer } from 'mobx-react-lite';
+import { GoalsArchiveStoreProvider } from './store';
+import { GoalsArchiveView } from './view';
+
+const GoalsArchivePage = observer(function GoalsArchivePage() {
+ return (
+
+
+
+ );
+});
+
+export default GoalsArchivePage;
diff --git a/components/pages/Goals/ArchivePage/store.ts b/components/pages/Goals/ArchivePage/store.ts
new file mode 100644
index 00000000..dc848e51
--- /dev/null
+++ b/components/pages/Goals/ArchivePage/store.ts
@@ -0,0 +1,40 @@
+import { computed, makeObservable } from 'mobx';
+import { RootStore } from '../../../../stores/RootStore';
+import { getProvider } from '../../../../helpers/StoreProvider';
+import { BaseGoalsStore } from "../stores/BaseGoalsStore";
+import { GoalDataExtended } from "../types";
+
+export class GoalsArchiveStore extends BaseGoalsStore {
+ constructor(public root: RootStore) {
+ super(root);
+
+ makeObservable(this, {
+ list: computed,
+ hasGoals: computed,
+ })
+ }
+
+ get list() {
+ return Object.entries(this.extendedGoals).reduce((acc, [id, goals]) => {
+ const archivedGoals = goals.filter((goal) => goal.isArchived);
+
+ if (archivedGoals.length) {
+ return {
+ ...acc,
+ [id]: archivedGoals,
+ };
+ }
+
+ return acc;
+ }, {} as Record)
+ }
+
+ get hasGoals() {
+ return Boolean(Object.keys(this.list).length);
+ }
+}
+
+export const {
+ StoreProvider: GoalsArchiveStoreProvider,
+ useStore: useGoalsArchiveStore
+} = getProvider(GoalsArchiveStore);
diff --git a/components/pages/Goals/ArchivePage/view.tsx b/components/pages/Goals/ArchivePage/view.tsx
new file mode 100644
index 00000000..166a9496
--- /dev/null
+++ b/components/pages/Goals/ArchivePage/view.tsx
@@ -0,0 +1,77 @@
+import React, { useEffect } from 'react';
+import { observer } from 'mobx-react-lite';
+import Head from 'next/head';
+import { GoalList } from '../components/GoalList';
+import { ModalsSwitcher } from '../../../../helpers/ModalsController';
+import { useGoalsArchiveStore } from './store';
+import { Box, Button, Heading, Text } from "@chakra-ui/react";
+import NextLink from "next/link";
+import { faAngleLeft } from "@fortawesome/pro-light-svg-icons";
+import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
+import { useRouter } from "next/navigation";
+
+export const GoalsArchiveView = observer(function GoalsArchiveView() {
+ const { push } = useRouter();
+ const store = useGoalsArchiveStore();
+
+ useEffect(() => {
+ if (!store.hasGoals) {
+ push('/goals');
+ }
+ }, [store.hasGoals, push]);
+
+ return (
+ <>
+
+ Goals Archive
+
+ {store.hasGoals && (
+ <>
+
+
+ Archive
+
+
+
+
+
+
+
+ >
+ )}
+ >
+ );
+});
diff --git a/components/pages/Goals/index.tsx b/components/pages/Goals/MainPage/index.tsx
similarity index 91%
rename from components/pages/Goals/index.tsx
rename to components/pages/Goals/MainPage/index.tsx
index 6384f432..6fc58c22 100644
--- a/components/pages/Goals/index.tsx
+++ b/components/pages/Goals/MainPage/index.tsx
@@ -1,3 +1,4 @@
+import React from 'react';
import { observer } from 'mobx-react-lite';
import { GoalsStoreProvider } from './store';
import { GoalsView } from './view';
diff --git a/components/pages/Goals/MainPage/store.ts b/components/pages/Goals/MainPage/store.ts
new file mode 100644
index 00000000..ca4acd4f
--- /dev/null
+++ b/components/pages/Goals/MainPage/store.ts
@@ -0,0 +1,80 @@
+import { action, computed, makeObservable, observable } from 'mobx';
+import { RootStore } from '../../../../stores/RootStore';
+import { getProvider } from '../../../../helpers/StoreProvider';
+import { BaseGoalsStore, GoalsModalsTypes } from "../stores/BaseGoalsStore";
+import { GoalDataExtended } from "../types";
+import { CreateGoalParams } from "../../../../stores/RootStore/Resources/GoalsStore";
+
+export class GoalsStore extends BaseGoalsStore {
+ keymap = {
+ CREATE_GOAL: ['n'],
+ };
+
+ hotkeysHandlers = {
+ CREATE_GOAL: () => {
+ this.startGoalCreation();
+ },
+ };
+
+ constructor(public root: RootStore) {
+ super(root);
+
+ makeObservable(this, {
+ keymap: observable,
+ hotkeysHandlers: observable,
+ list: computed,
+ hasGoals: computed,
+ cloneGoal: action.bound,
+ startGoalCreation: action.bound,
+ });
+ }
+
+ get list() {
+ return Object.entries(this.extendedGoals).reduce((acc, [id, goals]) => {
+ const notArchivedGoals = goals.filter((goal) => !goal.isArchived);
+
+ if (notArchivedGoals.length) {
+ return {
+ ...acc,
+ [id]: notArchivedGoals,
+ };
+ }
+
+ return acc;
+ }, {} as Record)
+ }
+
+ get hasGoals() {
+ return Boolean(Object.keys(this.list).length);
+ }
+
+ get hasArchivedGoals() {
+ return this.root.resources.goals.list.some((goal) => goal.isArchived);
+ }
+
+ cloneGoal = ({ customFields, ...goal }: GoalDataExtended) => {
+ return this.root.resources.goals.cloneGoal(goal);
+ }
+
+ startGoalCreation = () => {
+ this.modals.open({
+ type: GoalsModalsTypes.CREATE_OR_UPDATE_GOAL,
+ props: {
+ onSave: async ({
+ goal: { customFields, ...goal },
+ ...otherParams
+ }: CreateGoalParams) => {
+ await this.root.resources.goals.add({ goal, ...otherParams });
+ await this.loadTaskList();
+ this.modals.close();
+ },
+ onClose: this.modals.close,
+ },
+ });
+ };
+}
+
+export const {
+ StoreProvider: GoalsStoreProvider,
+ useStore: useGoalsStore
+} = getProvider(GoalsStore);
diff --git a/components/pages/Goals/MainPage/view.tsx b/components/pages/Goals/MainPage/view.tsx
new file mode 100644
index 00000000..aa23318b
--- /dev/null
+++ b/components/pages/Goals/MainPage/view.tsx
@@ -0,0 +1,103 @@
+import React from 'react';
+import { observer } from 'mobx-react-lite';
+import Head from 'next/head';
+import { GoalList } from '../components/GoalList';
+import { ModalsSwitcher } from '../../../../helpers/ModalsController';
+import { useGoalsStore } from './store';
+import { useHotkeysHandler } from "../../../../helpers/useHotkeysHandler";
+import { Box, Button, Heading, Text } from "@chakra-ui/react";
+import { GoalCreateNewButton } from "../components/GoalCreateNewButton";
+import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
+import { faPlus } from "@fortawesome/pro-regular-svg-icons";
+import { EmptyGoalListMessage } from "../components/EmptyGoalListMessage/EmptyGoalListMessage";
+import NextLink from 'next/link';
+import { faBoxArchive } from "@fortawesome/pro-light-svg-icons";
+import { Tooltip } from "../../../shared/Tooltip";
+
+export const GoalsView = observer(function GoalsView() {
+ const store = useGoalsStore();
+
+ useHotkeysHandler(store.keymap, store.hotkeysHandlers, {
+ enabled: !store.modals.isOpen,
+ keyup: true,
+ });
+
+ return (
+ <>
+
+ Goals
+
+
+
+ Goals
+
+
+ {store.hasArchivedGoals && (
+
+
+
+
+
+ )}
+
+ {store.hasGoals ? (
+
+ ) : (
+
+ )}
+
+ {store.hasGoals && (
+
+
+
+ )}
+
+
+ >
+ );
+});
diff --git a/components/pages/Goals/components/EmptyGoalListMessage/EmptyGoalListMessage.tsx b/components/pages/Goals/components/EmptyGoalListMessage/EmptyGoalListMessage.tsx
index 16aab73b..3703386d 100644
--- a/components/pages/Goals/components/EmptyGoalListMessage/EmptyGoalListMessage.tsx
+++ b/components/pages/Goals/components/EmptyGoalListMessage/EmptyGoalListMessage.tsx
@@ -3,7 +3,11 @@ import { MascotGoals } from '../../../../images/illustrations/MascotGoals';
import { GoalCreateNewButton } from "../GoalCreateNewButton";
import React from "react";
-export function EmptyGoalListMessage() {
+type Props = {
+ onCreate(): void;
+}
+
+export function EmptyGoalListMessage({ onCreate }: Props) {
return (
-
+
Create new goal 🎯
diff --git a/components/pages/Goals/components/GoalCreateNewButton/index.tsx b/components/pages/Goals/components/GoalCreateNewButton/index.tsx
index 62189791..e050b377 100644
--- a/components/pages/Goals/components/GoalCreateNewButton/index.tsx
+++ b/components/pages/Goals/components/GoalCreateNewButton/index.tsx
@@ -1,6 +1,4 @@
-import { observer } from 'mobx-react-lite';
import { Button, Text, ButtonProps } from '@chakra-ui/react';
-import { useGoalsStore } from '../../store';
import React from 'react';
import { HotkeyBlock } from '../../../../shared/HotkeyBlock';
import { Tooltip } from "../../../../shared/Tooltip";
@@ -10,51 +8,46 @@ type Props = ButtonProps & {
withTooltip?: boolean;
}
-export const GoalCreateNewButton = observer(
- function GoalCreateNewButton({ children, withHotkey, withTooltip, ...buttonProps }: Props) {
- const store = useGoalsStore();
-
- return (
- <>
-
+
+
+
+ {withHotkey && !withTooltip && (
+
-
-
- {withHotkey && !withTooltip && (
-
- Press
-
-
- )}
- >
- );
- }
-);
+ Press
+
+
+ )}
+ >
+ );
+}
diff --git a/components/pages/Goals/components/GoalEmojiSelect/GoalEmojiSelect.tsx b/components/pages/Goals/components/GoalEmojiSelect/index.tsx
similarity index 100%
rename from components/pages/Goals/components/GoalEmojiSelect/GoalEmojiSelect.tsx
rename to components/pages/Goals/components/GoalEmojiSelect/index.tsx
diff --git a/components/pages/Goals/components/GoalItem/index.tsx b/components/pages/Goals/components/GoalList/GoalItem/index.tsx
similarity index 85%
rename from components/pages/Goals/components/GoalItem/index.tsx
rename to components/pages/Goals/components/GoalList/GoalItem/index.tsx
index deccf77c..1c6827d1 100644
--- a/components/pages/Goals/components/GoalItem/index.tsx
+++ b/components/pages/Goals/components/GoalList/GoalItem/index.tsx
@@ -1,7 +1,6 @@
import { observer } from 'mobx-react-lite';
import { Box, chakra, Flex, Text, Tooltip } from '@chakra-ui/react';
-import { useGoalsStore } from '../../store';
-import { DatePicker } from "../../../../shared/DatePicker";
+import { DatePicker } from "../../../../../shared/DatePicker";
import {
faAlarmClock,
faBoxArchive,
@@ -19,11 +18,12 @@ import {
} from "@fortawesome/pro-solid-svg-icons";
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
import React from "react";
-import { GoalDataExtended, GoalState, GoalStatus } from "../../types";
-import { ActionMenu } from "../../../../shared/ActionMenu";
-import { EditableTitle } from "../../../../shared/EditableTitle";
-import { DatePickerHelpers } from "../../../../shared/DatePicker/helpers";
-import { GoalEmojiSelect } from "../GoalEmojiSelect/GoalEmojiSelect";
+import { GoalDataExtended, GoalState, GoalStatus } from "../../../types";
+import { ActionMenu } from "../../../../../shared/ActionMenu";
+import { EditableTitle } from "../../../../../shared/EditableTitle";
+import { DatePickerHelpers } from "../../../../../shared/DatePicker/helpers";
+import { GoalEmojiSelect } from "../../GoalEmojiSelect";
+import { useGoalListStore } from "../store";
type Props = {
goal: GoalDataExtended
@@ -48,9 +48,7 @@ const GOAL_STATE_PARAMS = {
}
export const GoalItem = observer(function GoalItem({ goal }: Props) {
- const store = useGoalsStore();
-
- const handleOpenGoal = () => store.editGoal(goal.id);
+ const store = useGoalListStore();
const isDone = goal.status === GoalStatus.DONE;
const isWontDo = goal.status === GoalStatus.WONT_DO;
@@ -60,13 +58,13 @@ export const GoalItem = observer(function GoalItem({ goal }: Props) {
icon: faSquareArrowUpRight,
title: 'Open',
command: '↵/⌥O',
- onClick: handleOpenGoal
+ onClick: () => store.callbacks?.onOpenGoal(goal.id),
},
{
icon: faCircleCheck,
title: isDone ? 'Unmark as done' : 'Done',
command: '⌥D',
- onClick: () => store.updateGoal({
+ onClick: () => store.callbacks?.onUpdateGoal({
...goal,
status: isDone ? GoalStatus.TODO : GoalStatus.DONE,
}),
@@ -75,19 +73,20 @@ export const GoalItem = observer(function GoalItem({ goal }: Props) {
icon: faCircleMinus,
title: isWontDo ? "Unmark as won't do" : "Won't do",
command: '⌥W',
- onClick: () => store.wontDoSubmitModalOpen(goal),
+ onClick: () => store.callbacks?.onWontDo(goal),
},
{
icon: faClone,
title: 'Clone',
command: '⌥C',
+ hidden: !store.hasClone,
onClick: () => store.cloneGoal(goal),
},
{
icon: faBoxArchive,
title: goal.isArchived ? 'Unarchive' : 'Archive',
command: '⌥A',
- onClick: () => store.updateGoal({
+ onClick: () => store.callbacks?.onUpdateGoal({
...goal,
isArchived: !goal.isArchived
}),
@@ -104,14 +103,14 @@ export const GoalItem = observer(function GoalItem({ goal }: Props) {
content: 'Are you sure you would like to delete this goal?'
})
) {
- await store.deleteGoal(goal.id);
+ await store.callbacks?.onDeleteGoal(goal.id);
}
},
},
];
const handleChangeStartDate = (date: string) => {
- return store.updateGoal({
+ return store.callbacks?.onUpdateGoal({
...goal,
startDate: date,
targetDate: DatePickerHelpers.isStartDateAfterEndDate(date, goal.targetDate)
@@ -120,16 +119,16 @@ export const GoalItem = observer(function GoalItem({ goal }: Props) {
});
};
const handleChangeTargetDate = (date: string) => {
- return store.updateGoal({ ...goal, targetDate: date });
+ return store.callbacks?.onUpdateGoal({ ...goal, targetDate: date });
};
const handleChangeTitle = (title: string) => {
- return store.updateGoal({ ...goal, title });
+ return store.callbacks?.onUpdateGoal({ ...goal, title });
};
const handleChangeIcon = (icon: string) => {
- return store.updateGoal({ ...goal, icon: { ...goal.icon, value: icon } });
+ return store.callbacks?.onUpdateGoal({ ...goal, icon: { ...goal.icon, value: icon } });
};
const handleColorChange = (color: string) => {
- return store.updateGoal({ ...goal, icon: { ...goal.icon, color } });
+ return store.callbacks?.onUpdateGoal({ ...goal, icon: { ...goal.icon, color } });
};
return (
@@ -150,7 +149,7 @@ export const GoalItem = observer(function GoalItem({ goal }: Props) {
position='relative'
cursor='pointer'
height={124}
- onClick={handleOpenGoal}
+ onClick={() => store.callbacks?.onOpenGoal(goal.id)}
>
{
- return store.root.resources.spaces.update({ ...space, name });
+ return store.updateSpace({ ...space, name });
};
const handleSpaceIconChange = (icon: string) => {
- return store.root.resources.spaces.update({ ...space, icon });
+ return store.updateSpace({ ...space, icon });
};
const handleSpaceColorChange = (color: string) => {
- return store.root.resources.spaces.update({ ...space, color });
+ return store.updateSpace({ ...space, color });
};
return (
diff --git a/components/pages/Goals/components/GoalList/index.tsx b/components/pages/Goals/components/GoalList/index.tsx
new file mode 100644
index 00000000..0615c912
--- /dev/null
+++ b/components/pages/Goals/components/GoalList/index.tsx
@@ -0,0 +1,12 @@
+import { observer } from 'mobx-react-lite';
+import { GoalListProps } from "./types";
+import { GoalListStoreProvider } from './store';
+import { GoalListView } from "./view";
+
+export const GoalList = observer(function GoalList(props: GoalListProps) {
+ return (
+
+
+
+ );
+});
diff --git a/components/pages/Goals/components/GoalList/store.ts b/components/pages/Goals/components/GoalList/store.ts
new file mode 100644
index 00000000..b70f044d
--- /dev/null
+++ b/components/pages/Goals/components/GoalList/store.ts
@@ -0,0 +1,65 @@
+import { makeAutoObservable, toJS } from 'mobx';
+import { RootStore } from '../../../../../stores/RootStore';
+import { getProvider } from '../../../../../helpers/StoreProvider';
+import { GoalDataExtended } from "../../types";
+import { GoalListProps, GoalListCallbacks } from './types';
+import { EDITABLE_TITLE_ID_SLUG } from "../../../../shared/EditableTitle";
+import { SpaceData } from "../../../Spaces/types";
+
+export class GoalListStore {
+ listBySpaces: Record = {};
+ callbacks: GoalListCallbacks;
+
+ goalsRefs: Record = {};
+
+ constructor(public root: RootStore) {
+ makeAutoObservable(this);
+ }
+
+ get hasClone() {
+ return Boolean(this.callbacks?.onCloneGoal);
+ }
+
+ setGoalRef = (goalId: string, ref: HTMLDivElement) => {
+ this.goalsRefs[goalId] = ref;
+ }
+
+ getGoalTitleElement = (goalId: string) => {
+ return this.goalsRefs[goalId].querySelector(
+ `#${EDITABLE_TITLE_ID_SLUG}-${goalId}`
+ ) as HTMLParagraphElement;
+ };
+
+ cloneGoal = async (goal: GoalDataExtended) => {
+ if (!this.hasClone) {
+ return;
+ }
+
+ const clonedGoal = await this.callbacks.onCloneGoal(goal);
+ this.getGoalTitleElement(clonedGoal.id).click();
+ }
+
+ getSpace = (spaceId: string) => {
+ return toJS(this.root.resources.spaces.getById(spaceId));
+ }
+
+ updateSpace = (space: SpaceData) => {
+ return this.root.resources.spaces.update(space);
+ }
+
+ update = ({ listBySpaces, onUpdateGoal, onDeleteGoal, onCloneGoal, onOpenGoal, onWontDo }: GoalListProps) => {
+ this.listBySpaces = listBySpaces;
+ this.callbacks = {
+ onCloneGoal,
+ onDeleteGoal,
+ onUpdateGoal,
+ onOpenGoal,
+ onWontDo,
+ };
+ };
+}
+
+export const {
+ StoreProvider: GoalListStoreProvider,
+ useStore: useGoalListStore
+} = getProvider(GoalListStore);
diff --git a/components/pages/Goals/components/GoalList/types.ts b/components/pages/Goals/components/GoalList/types.ts
new file mode 100644
index 00000000..ac3e99c2
--- /dev/null
+++ b/components/pages/Goals/components/GoalList/types.ts
@@ -0,0 +1,13 @@
+import { GoalData, GoalDataExtended } from "../../types";
+
+export type GoalListCallbacks = {
+ onOpenGoal(goalId: string): void;
+ onDeleteGoal(goalId: string): Promise;
+ onUpdateGoal(goal: GoalDataExtended): void;
+ onWontDo(goal: GoalDataExtended): void;
+ onCloneGoal?(goal: GoalDataExtended): Promise;
+};
+
+export type GoalListProps = GoalListCallbacks & {
+ listBySpaces: Record;
+};
diff --git a/components/pages/Goals/components/GoalList/view.tsx b/components/pages/Goals/components/GoalList/view.tsx
new file mode 100644
index 00000000..fbc7b414
--- /dev/null
+++ b/components/pages/Goals/components/GoalList/view.tsx
@@ -0,0 +1,45 @@
+import { observer } from 'mobx-react-lite';
+import { Box, Flex } from '@chakra-ui/react';
+import React from 'react';
+import { faList } from '@fortawesome/pro-solid-svg-icons';
+import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
+import { SpaceItem } from './SpaceItem';
+import { Filters } from "../../../../shared/Filters";
+import { ManArrowToIcon } from "../../../../images/icons/ManArrowToIcon";
+import { ManArrowOffIcon } from "../../../../images/icons/ManArrowOffIcon";
+import { useGoalListStore } from "./store";
+
+const GOALS_LIST_FILTERS = [
+ {
+ value: 'all',
+ label: 'All',
+ icon:
+ },
+ {
+ value: 'created-by-me',
+ label: 'Created by me',
+ icon:
+ },
+ {
+ value: 'assigned-to-me',
+ label: 'Assigned to me',
+ icon:
+ },
+];
+
+export const GoalListView = observer(function GoalListView() {
+ const store = useGoalListStore();
+
+ const haveGoals = store.root.resources.goals.haveGoals;
+
+ return (
+
+ {haveGoals && }
+
+ {Object.entries(store.listBySpaces).map(([spaceId, goals]) => (
+
+ ))}
+
+
+ );
+});
diff --git a/components/pages/Goals/components/GoalsList/index.tsx b/components/pages/Goals/components/GoalsList/index.tsx
deleted file mode 100644
index ec10094b..00000000
--- a/components/pages/Goals/components/GoalsList/index.tsx
+++ /dev/null
@@ -1,85 +0,0 @@
-import { observer } from 'mobx-react-lite';
-import { Box, Heading, Flex } from '@chakra-ui/react';
-import { useGoalsStore } from '../../store';
-import { GoalCreateNewButton } from '../GoalCreateNewButton';
-import React from 'react';
-import { useHotkeysHandler } from '../../../../../helpers/useHotkeysHandler';
-import { faPlus } from '@fortawesome/pro-regular-svg-icons';
-import { faList } from '@fortawesome/pro-solid-svg-icons';
-import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
-import { SpaceItem } from '../SpaceItem';
-import { EmptyGoalListMessage } from '../EmptyGoalListMessage/EmptyGoalListMessage';
-import { Filters } from "../../../../shared/Filters";
-import { ManArrowToIcon } from "../../../../images/icons/ManArrowToIcon";
-import { ManArrowOffIcon } from "../../../../images/icons/ManArrowOffIcon";
-
-const GOALS_LIST_FILTERS = [
- {
- value: 'all',
- label: 'All',
- icon:
- },
- {
- value: 'created-by-me',
- label: 'Created by me',
- icon:
- },
- {
- value: 'assigned-to-me',
- label: 'Assigned to me',
- icon:
- },
-]
-
-export const GoalsList = observer(function GoalsList() {
- const store = useGoalsStore();
-
- useHotkeysHandler(store.keymap, store.hotkeysHandlers, {
- enabled: !store.modals.isOpen,
- keyup: true,
- });
-
- const haveGoals = store.root.resources.goals.haveGoals;
-
- return (
-
-
- Goals
-
-
- {haveGoals && }
-
-
- {haveGoals
- ? Object.entries(store.extendedGoals).map(([spaceId, goals]) => (
-
- ))
- : }
-
-
- {haveGoals && (
-
-
-
- )}
-
- );
-});
diff --git a/components/pages/Goals/modals/GoalCreationModal/components/GoalCreationDescription.tsx b/components/pages/Goals/modals/GoalCreationModal/components/GoalCreationDescription.tsx
index 4a2fde80..d6e9e063 100644
--- a/components/pages/Goals/modals/GoalCreationModal/components/GoalCreationDescription.tsx
+++ b/components/pages/Goals/modals/GoalCreationModal/components/GoalCreationDescription.tsx
@@ -4,7 +4,7 @@ import { useGoalCreationModalStore } from '../store';
import { Editor } from '../../../../../shared/Editor';
import React from "react";
import { FormError } from "../../../../../shared/FormError";
-import { GoalEmojiSelect } from "../../../components/GoalEmojiSelect/GoalEmojiSelect";
+import { GoalEmojiSelect } from "../../../components/GoalEmojiSelect";
export const GoalCreationDescription = observer(
function GoalCreationDescription() {
diff --git a/components/pages/Goals/store.ts b/components/pages/Goals/stores/BaseGoalsStore.ts
similarity index 61%
rename from components/pages/Goals/store.ts
rename to components/pages/Goals/stores/BaseGoalsStore.ts
index c7d3be0b..93e19771 100644
--- a/components/pages/Goals/store.ts
+++ b/components/pages/Goals/stores/BaseGoalsStore.ts
@@ -1,14 +1,12 @@
-import { makeAutoObservable } from 'mobx';
-import { RootStore } from '../../../stores/RootStore';
-import { getProvider } from '../../../helpers/StoreProvider';
-import { ModalsController } from '../../../helpers/ModalsController';
-import { GoalCreationModal } from './modals/GoalCreationModal';
-import { GoalDataExtended, GoalState, GoalStatus } from './types';
-import { TaskData, TaskStatus } from "../../shared/TasksList/types";
-import { CreateGoalParams } from "../../../stores/RootStore/Resources/GoalsStore";
-import { GoalWontDoSubmitModal } from "./modals/GoalWontDoSubmitModal";
-import moment from "moment";
-import { EDITABLE_TITLE_ID_SLUG } from "../../shared/EditableTitle";
+import { action, computed, makeObservable, observable } from 'mobx';
+import { RootStore } from '../../../../stores/RootStore';
+import { ModalsController } from '../../../../helpers/ModalsController';
+import { GoalCreationModal } from '../modals/GoalCreationModal';
+import { GoalDataExtended, GoalState, GoalStatus } from '../types';
+import { TaskData, TaskStatus } from "../../../shared/TasksList/types";
+import { CreateGoalParams } from "../../../../stores/RootStore/Resources/GoalsStore";
+import { GoalWontDoSubmitModal } from "../modals/GoalWontDoSubmitModal";
+import moment, { Moment } from "moment";
export enum GoalsModalsTypes {
CREATE_OR_UPDATE_GOAL,
@@ -20,25 +18,28 @@ const GoalsModals = {
[GoalsModalsTypes.WONT_DO_SUBMIT]: GoalWontDoSubmitModal,
};
-export class GoalsStore {
- taskList: TaskData[];
- goalsRefs: Record = {};
+export class BaseGoalsStore {
+ taskList: TaskData[] = [];
+ currentDay: Moment = moment();
+
+ modals = new ModalsController(GoalsModals);
constructor(public root: RootStore) {
- makeAutoObservable(this);
+ makeObservable(this, {
+ taskList: observable,
+ currentDay: observable,
+ extendedGoals: computed,
+ taskListByGoal: computed,
+ getStateByDate: action.bound,
+ wontDoSubmitModalOpen: action.bound,
+ editGoal: action.bound,
+ updateGoal: action.bound,
+ deleteGoal: action.bound,
+ loadTaskList: action.bound,
+ init: action.bound,
+ });
}
- currentDay = moment();
- keymap = {
- CREATE_GOAL: ['n'],
- };
-
- hotkeysHandlers = {
- CREATE_GOAL: () => {
- this.startGoalCreation();
- },
- };
-
get taskListByGoal() {
if (!this.taskList || !this.taskList.length) {
return {};
@@ -61,7 +62,7 @@ export class GoalsStore {
}
get extendedGoals() {
- return Object.entries(this.root.resources.goals.map).reduce((acc, [id, goal], index) => ({
+ return Object.entries(this.root.resources.goals.map).reduce((acc, [id, goal]) => ({
...acc,
[goal.spaceId]: [
...(acc[goal.spaceId] ?? []),
@@ -79,12 +80,6 @@ export class GoalsStore {
}), {} as Record);
}
- getGoalTitleElement = (goalId: string) => {
- return this.goalsRefs[goalId].querySelector(
- `#${EDITABLE_TITLE_ID_SLUG}-${goalId}`
- ) as HTMLParagraphElement;
- };
-
getStateByDate = (startDate: string, targetDate: string) => {
const start = moment(startDate);
const target = moment(targetDate);
@@ -101,25 +96,10 @@ export class GoalsStore {
}
};
- setGoalRef = (goalId: string, ref: HTMLDivElement) => {
- this.goalsRefs[goalId] = ref;
- }
-
- modals = new ModalsController(GoalsModals);
-
- startGoalCreation = () => {
- this.modals.open({
- type: GoalsModalsTypes.CREATE_OR_UPDATE_GOAL,
- props: {
- onSave: this.createGoal,
- onClose: this.modals.close,
- },
- });
- };
-
wontDoSubmitModalOpen = (goal: GoalDataExtended) => {
if (goal.status === GoalStatus.WONT_DO) {
- return this.updateGoal({ ...goal, status: GoalStatus.TODO });
+ this.updateGoal({ ...goal, status: GoalStatus.TODO });
+ return;
}
this.modals.open({
@@ -134,11 +114,6 @@ export class GoalsStore {
});
};
- cloneGoal = async ({ customFields, ...goal }: GoalDataExtended) => {
- const clonedGoal = await this.root.resources.goals.cloneGoal(goal);
- this.getGoalTitleElement(clonedGoal.id).click();
- }
-
editGoal = (goalId: string) => {
this.modals.open({
type: GoalsModalsTypes.CREATE_OR_UPDATE_GOAL,
@@ -167,17 +142,8 @@ export class GoalsStore {
await this.loadTaskList();
};
- createGoal = async ({
- goal: { customFields, ...goal },
- ...otherParams
- }: CreateGoalParams) => {
- await this.root.resources.goals.add({ goal, ...otherParams });
- await this.loadTaskList();
- this.modals.close();
- };
-
- deleteGoal = async (goalId: string) => {
- await this.root.resources.goals.delete([goalId]);
+ deleteGoal = (goalId: string) => {
+ return this.root.resources.goals.delete([goalId]);
};
loadTaskList = async () => {
@@ -190,6 +156,3 @@ export class GoalsStore {
update = () => null;
}
-
-export const { StoreProvider: GoalsStoreProvider, useStore: useGoalsStore } =
- getProvider(GoalsStore);
diff --git a/components/pages/Goals/view.tsx b/components/pages/Goals/view.tsx
deleted file mode 100644
index 96935ce8..00000000
--- a/components/pages/Goals/view.tsx
+++ /dev/null
@@ -1,20 +0,0 @@
-import React from 'react';
-import { observer } from 'mobx-react-lite';
-import Head from 'next/head';
-import { GoalsList } from './components/GoalsList';
-import { ModalsSwitcher } from '../../../helpers/ModalsController';
-import { useGoalsStore } from './store';
-
-export const GoalsView = observer(function GoalsView() {
- const store = useGoalsStore();
-
- return (
- <>
-
- Goals
-
-
-
- >
- );
-});
diff --git a/components/pages/Goals/components/GoalIcon/index.tsx b/components/shared/GoalIcon/index.tsx
similarity index 89%
rename from components/pages/Goals/components/GoalIcon/index.tsx
rename to components/shared/GoalIcon/index.tsx
index 2e5a5bb3..fb78cf5c 100644
--- a/components/pages/Goals/components/GoalIcon/index.tsx
+++ b/components/shared/GoalIcon/index.tsx
@@ -1,5 +1,5 @@
import { Box, Text } from '@chakra-ui/react';
-import { GoalIconData, GoalIconVariants } from '../../types';
+import { GoalIconData, GoalIconVariants } from '../../pages/Goals/types';
import React from 'react';
import { observer } from 'mobx-react-lite';
diff --git a/components/shared/GoalsSelection/view.tsx b/components/shared/GoalsSelection/view.tsx
index b1e9f6bb..278fa173 100644
--- a/components/shared/GoalsSelection/view.tsx
+++ b/components/shared/GoalsSelection/view.tsx
@@ -12,7 +12,7 @@ import {
import { GoalsSelectionProps, useGoalsSelectionStore } from './store';
import React, { useRef } from 'react';
import { LargePlusIcon } from '../Icons/LargePlusIcon';
-import { GoalIcon } from '../../pages/Goals/components/GoalIcon';
+import { GoalIcon } from '../GoalIcon';
type GoalSelectionListItemProps = {
id: string | null;
diff --git a/components/shared/TaskQuickEditor/TaskQuickEditorGoal.tsx b/components/shared/TaskQuickEditor/TaskQuickEditorGoal.tsx
index 61e6ae8f..7f31e167 100644
--- a/components/shared/TaskQuickEditor/TaskQuickEditorGoal.tsx
+++ b/components/shared/TaskQuickEditor/TaskQuickEditorGoal.tsx
@@ -3,7 +3,7 @@ import { Modes, useTaskQuickEditorStore } from './store';
import { Button, ButtonProps, chakra } from '@chakra-ui/react';
import React, { useEffect } from 'react';
import { TaskQuickEditorMenu } from './TaskQuickEditorMenu';
-import { GoalIcon } from '../../pages/Goals/components/GoalIcon';
+import { GoalIcon } from '../GoalIcon';
import { TaskQuickEditorEmptyButton } from './TaskQuickEditorEmptyButton';
export const TaskQuickEditorGoal = observer(function TaskQuickEditorGoal({
diff --git a/components/shared/TaskQuickEditor/modes/GoalModeStore.tsx b/components/shared/TaskQuickEditor/modes/GoalModeStore.tsx
index d4e447b1..01733428 100644
--- a/components/shared/TaskQuickEditor/modes/GoalModeStore.tsx
+++ b/components/shared/TaskQuickEditor/modes/GoalModeStore.tsx
@@ -1,7 +1,7 @@
import React from 'react';
import { makeAutoObservable } from 'mobx';
import { chakra } from '@chakra-ui/react';
-import { GoalIcon } from '../../../pages/Goals/components/GoalIcon';
+import { GoalIcon } from '../../GoalIcon';
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
import { faXmark } from '@fortawesome/pro-regular-svg-icons';
import { RootStore } from '../../../../stores/RootStore';
diff --git a/package-lock.json b/package-lock.json
index 800cf110..9d843538 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -50,7 +50,7 @@
"prosemirror-state": "^1.4.2",
"react": "^18.2.0",
"react-beautiful-dnd": "^13.1.1",
- "react-datepicker": "4.11.0",
+ "react-datepicker": "4.10.0",
"react-dom": "^18.2.0",
"react-hotkeys-hook": "^4.3.8",
"tippy.js": "^6.3.7",
@@ -7210,9 +7210,9 @@
}
},
"node_modules/react-datepicker": {
- "version": "4.11.0",
- "resolved": "https://registry.npmjs.org/react-datepicker/-/react-datepicker-4.11.0.tgz",
- "integrity": "sha512-50n93o7mQwBEhg05tbopjFKgs8qgi8VBCAOMC4VqrKut72eAjESc/wXS/k5hRtnP0oe2FCGw7MJuIwh37wuXOw==",
+ "version": "4.10.0",
+ "resolved": "https://registry.npmjs.org/react-datepicker/-/react-datepicker-4.10.0.tgz",
+ "integrity": "sha512-6IfBCZyWj54ZZGLmEZJ9c4Yph0s9MVfEGDC2evOvf9AmVz+RRcfP2Czqad88Ff9wREbcbqa4dk7IFYeXF1d3Ag==",
"dependencies": {
"@popperjs/core": "^2.9.2",
"classnames": "^2.2.6",
@@ -13628,9 +13628,9 @@
}
},
"react-datepicker": {
- "version": "4.11.0",
- "resolved": "https://registry.npmjs.org/react-datepicker/-/react-datepicker-4.11.0.tgz",
- "integrity": "sha512-50n93o7mQwBEhg05tbopjFKgs8qgi8VBCAOMC4VqrKut72eAjESc/wXS/k5hRtnP0oe2FCGw7MJuIwh37wuXOw==",
+ "version": "4.10.0",
+ "resolved": "https://registry.npmjs.org/react-datepicker/-/react-datepicker-4.10.0.tgz",
+ "integrity": "sha512-6IfBCZyWj54ZZGLmEZJ9c4Yph0s9MVfEGDC2evOvf9AmVz+RRcfP2Czqad88Ff9wREbcbqa4dk7IFYeXF1d3Ag==",
"requires": {
"@popperjs/core": "^2.9.2",
"classnames": "^2.2.6",
diff --git a/package.json b/package.json
index 7b7159cd..e70c55a7 100644
--- a/package.json
+++ b/package.json
@@ -62,7 +62,7 @@
"prosemirror-state": "^1.4.2",
"react": "^18.2.0",
"react-beautiful-dnd": "^13.1.1",
- "react-datepicker": "4.11.0",
+ "react-datepicker": "4.10.0",
"react-dom": "^18.2.0",
"react-hotkeys-hook": "^4.3.8",
"tippy.js": "^6.3.7",
diff --git a/pages/goals/archive.tsx b/pages/goals/archive.tsx
new file mode 100644
index 00000000..8fd3778a
--- /dev/null
+++ b/pages/goals/archive.tsx
@@ -0,0 +1,11 @@
+import dynamic from 'next/dynamic';
+import { PageLoader } from '../../components/shared/PageLoader';
+
+const DynamicGoalsArchivePage = dynamic(() => import('../../components/pages/Goals/ArchivePage'), {
+ loading: () => ,
+ ssr: false,
+});
+
+export default function GoalsArchive() {
+ return ;
+}
diff --git a/pages/goals/index.tsx b/pages/goals/index.tsx
index f8c07289..c806abf6 100644
--- a/pages/goals/index.tsx
+++ b/pages/goals/index.tsx
@@ -1,7 +1,7 @@
import dynamic from 'next/dynamic';
import { PageLoader } from '../../components/shared/PageLoader';
-const DynamicGoalsPage = dynamic(() => import('../../components/pages/Goals'), {
+const DynamicGoalsPage = dynamic(() => import('../../components/pages/Goals/MainPage'), {
loading: () => ,
ssr: false,
});