From ce6a2de44f8a3e80b6baf72f21dc79e51f3a8b8e Mon Sep 17 00:00:00 2001 From: tnagorra Date: Fri, 6 Sep 2024 15:56:43 +0545 Subject: [PATCH] WIP --- knip.json | 4 +- src/App/index.tsx | 34 +++-- src/App/routes/index.tsx | 7 +- src/App/styles.module.css | 6 - src/PwaPrompt/index.tsx | 5 +- src/components/Link/index.tsx | 2 +- src/utils/localStorage.ts | 6 +- .../DayView/WorkItemRow/index.tsx | 10 +- src/views/DailyJournal/DayView/index.tsx | 2 +- src/views/DailyJournal/StartSidebar/index.tsx | 109 -------------- src/views/DailyStandup/index.tsx | 3 +- src/views/Settings/index.tsx | 136 ++++++++++++++++++ src/views/Settings/styles.module.css | 13 ++ 13 files changed, 190 insertions(+), 147 deletions(-) create mode 100644 src/views/Settings/index.tsx create mode 100644 src/views/Settings/styles.module.css diff --git a/knip.json b/knip.json index faebd69..40e4fc1 100644 --- a/knip.json +++ b/knip.json @@ -1,5 +1,5 @@ { "$schema": "https://unpkg.com/knip@5/schema.json", - "entry": ["src/index.tsx"], - "project": ["src/**/*.tsx", "src/**/*.ts"] + "entry": ["src/index.tsx!"], + "project": ["src/**/*.tsx!", "src/**/*.ts!"] } diff --git a/src/App/index.tsx b/src/App/index.tsx index 995ffd8..a468821 100644 --- a/src/App/index.tsx +++ b/src/App/index.tsx @@ -111,14 +111,23 @@ function App() { const [userAuth, setUserAuth] = useState(); const [size, setSize] = useState(getWindowSize); const [ready, setReady] = useState(false); + + // Local Storage + const [storageState, setStorageState] = useState({ 'timur-config': { defaultValue: defaultConfigValue, }, }); - const debouncedSize = useThrottledValue(size); + const storageContextValue = useMemo(() => ({ + storageState, + setStorageState, + }), [storageState]); + // Device Size + + const throttledSize = useThrottledValue(size); useEffect(() => { function handleResize() { setSize(getWindowSize()); @@ -131,6 +140,8 @@ function App() { }; }, []); + // Authentication + const [meResult] = useQuery( { query: ME_QUERY }, ); @@ -143,10 +154,6 @@ function App() { setReady(true); }, [meResult.data, meResult.fetching]); - const [enumsResult] = useQuery( - { query: ENUMS_QUERY }, - ); - const removeUserAuth = useCallback( () => { setUserAuth(undefined); @@ -163,6 +170,12 @@ function App() { [userAuth, removeUserAuth], ); + // Enums + + const [enumsResult] = useQuery( + { query: ENUMS_QUERY }, + ); + const enumsContextValue = useMemo( () => ({ enums: enumsResult.data, @@ -182,10 +195,7 @@ function App() { [enumsResult], ); - const storageContextValue = useMemo(() => ({ - storageState, - setStorageState, - }), [storageState]); + // Page layouts const navbarStartActionRef = useRef(null); const navbarMidActionRef = useRef(null); @@ -197,6 +207,8 @@ function App() { endActionsRef: navbarEndActionRef, }), []); + // Route + const fallbackElement = (
); + // NOTE: We should block page for authentication before we mount routes + // TODO: Handle error with authentication if (!ready) { return fallbackElement; } return ( - + diff --git a/src/App/routes/index.tsx b/src/App/routes/index.tsx index c1af8da..419ca67 100644 --- a/src/App/routes/index.tsx +++ b/src/App/routes/index.tsx @@ -84,11 +84,8 @@ const settings = customWrapRoute({ parent: rootLayout, path: 'settings', component: { - render: () => import('#components/TemplateView'), - props: { - title: 'Settings', - description: 'No settings to configure', - }, + render: () => import('#views/Settings'), + props: {}, }, wrapperComponent: Auth, context: { diff --git a/src/App/styles.module.css b/src/App/styles.module.css index 05e5da5..6dbff78 100644 --- a/src/App/styles.module.css +++ b/src/App/styles.module.css @@ -3,9 +3,6 @@ align-items: center; flex-direction: column; justify-content: center; - /* - background-color: var(--go-ui-color-background); - */ width: 100vw; height: 100vh; gap: 1rem; @@ -13,8 +10,5 @@ .app-logo { margin-top: -4rem; height: 6rem; - /* - animation: slide-up var(--go-ui-duration-animation-slow) ease-in-out forwards; - */ } } diff --git a/src/PwaPrompt/index.tsx b/src/PwaPrompt/index.tsx index 0f13e90..fc2769e 100644 --- a/src/PwaPrompt/index.tsx +++ b/src/PwaPrompt/index.tsx @@ -10,7 +10,7 @@ import styles from './styles.module.css'; // eslint-disable-next-line no-console console.info('PWA information:', pwaInfo); -function ReloadPrompt() { +function PwaPrompt() { const { offlineReady: [offlineReady, setOfflineReady], needRefresh: [needRefresh, setNeedRefresh], @@ -38,6 +38,7 @@ function ReloadPrompt() { console.info('SW registration error', error); }, }); + const reload = useCallback( () => { updateServiceWorker(true); @@ -96,4 +97,4 @@ function ReloadPrompt() { ); } -export default ReloadPrompt; +export default PwaPrompt; diff --git a/src/components/Link/index.tsx b/src/components/Link/index.tsx index 746afec..d86b5aa 100644 --- a/src/components/Link/index.tsx +++ b/src/components/Link/index.tsx @@ -56,7 +56,7 @@ export function resolvePath( } // eslint-disable-next-line react-refresh/only-export-components -export function useLink(props: { +function useLink(props: { external: true, href: string | undefined | null, to?: never, diff --git a/src/utils/localStorage.ts b/src/utils/localStorage.ts index f11a825..80cb1be 100644 --- a/src/utils/localStorage.ts +++ b/src/utils/localStorage.ts @@ -5,13 +5,9 @@ export function getFromStorage(key: string) { return val === null || val === undefined ? undefined : JSON.parse(val) as T; } -export function removeFromStorage(key: string) { - localStorage.removeItem(key); -} - export function setToStorage(key: string, value: unknown) { if (isNotDefined(value)) { - localStorage.clearItem(key); + localStorage.removeItem(key); } localStorage.setItem(key, JSON.stringify(value)); } diff --git a/src/views/DailyJournal/DayView/WorkItemRow/index.tsx b/src/views/DailyJournal/DayView/WorkItemRow/index.tsx index 1b15277..da0de34 100644 --- a/src/views/DailyJournal/DayView/WorkItemRow/index.tsx +++ b/src/views/DailyJournal/DayView/WorkItemRow/index.tsx @@ -39,7 +39,6 @@ import { useFocusClient } from '#hooks/useFocus'; import useLocalStorage from '#hooks/useLocalStorage'; import { colorscheme } from '#utils/constants'; import { - Contract, EntriesAsList, Task, WorkItem, @@ -86,7 +85,7 @@ function defaultColorSelector(_: T, i: number): [string, string] { export interface Props { className?: string; workItem: WorkItem; - contract: Contract; + contractId: string; onClone: (clientId: string, override?: Partial) => void; onChange: (clientId: string, ...entries: EntriesAsList) => void; @@ -97,7 +96,7 @@ function WorkItemRow(props: Props) { const { className, workItem, - contract, + contractId, onClone, onDelete, onChange, @@ -105,6 +104,7 @@ function WorkItemRow(props: Props) { const { enums } = useContext(EnumsContext); const { width: windowWidth } = useContext(SizeContext); + const inputRef = useFocusClient(workItem.clientId); const [config] = useLocalStorage('timur-config'); @@ -116,8 +116,8 @@ function WorkItemRow(props: Props) { ); const filteredTaskList = useMemo( - () => enums?.private?.allActiveTasks?.filter((task) => task.contract.id === contract.id), - [contract.id, enums], + () => enums?.private?.allActiveTasks?.filter((task) => task.contract.id === contractId), + [contractId, enums], ); const handleStatusCheck = useCallback(() => { diff --git a/src/views/DailyJournal/DayView/index.tsx b/src/views/DailyJournal/DayView/index.tsx index 73adcce..599990d 100644 --- a/src/views/DailyJournal/DayView/index.tsx +++ b/src/views/DailyJournal/DayView/index.tsx @@ -266,7 +266,7 @@ function DayView(props: Props) { onClone={onWorkItemClone} onChange={onWorkItemChange} onDelete={onWorkItemDelete} - contract={taskDetails?.contract} + contractId={taskDetails.contract.id} />
); diff --git a/src/views/DailyJournal/StartSidebar/index.tsx b/src/views/DailyJournal/StartSidebar/index.tsx index 45d862a..a160674 100644 --- a/src/views/DailyJournal/StartSidebar/index.tsx +++ b/src/views/DailyJournal/StartSidebar/index.tsx @@ -1,6 +1,5 @@ import { useCallback, - useContext, useMemo, } from 'react'; import { MdDragIndicator } from 'react-icons/md'; @@ -25,16 +24,11 @@ import { isNotDefined, } from '@togglecorp/fujs'; -import Checkbox from '#components/Checkbox'; import MonthlyCalendar from '#components/MonthlyCalendar'; import RadioInput from '#components/RadioInput'; -import SelectInput from '#components/SelectInput'; -import EnumsContext from '#contexts/enums'; -import { EnumsQuery } from '#generated/types/graphql'; import useLocalStorage from '#hooks/useLocalStorage'; import useSetFieldValue from '#hooks/useSetFieldValue'; import { - colorscheme, defaultConfigValue, numericOptionKeySelector, numericOptionLabelSelector, @@ -44,7 +38,6 @@ import { DailyJournalAttributeKeys, DailyJournalAttributeOrder, DailyJournalGrouping, - EditingMode, } from '#utils/types'; import styles from './styles.module.css'; @@ -155,47 +148,6 @@ function SortableItem(props: SortableItemProps) { ); } -type EditingOption = { key: EditingMode, label: string }; -function editingOptionKeySelector(item: EditingOption) { - return item.key; -} -function editingOptionLabelSelector(item: EditingOption) { - return item.label; -} -const editingOptions: EditingOption[] = [ - { key: 'normal', label: 'Normies' }, - { key: 'vim', label: 'Vim Masterace' }, -]; - -type WorkItemTypeOption = EnumsQuery['enums']['TimeEntryType'][number]; -function workItemTypeKeySelector(item: WorkItemTypeOption) { - return item.key; -} -function workItemTypeLabelSelector(item: WorkItemTypeOption) { - return item.label; -} - -type WorkItemStatusOption = EnumsQuery['enums']['TimeEntryStatus'][number]; -function workItemStatusKeySelector(item: WorkItemStatusOption) { - return item.key; -} -function workItemStatusLabelSelector(item: WorkItemStatusOption) { - return item.label; -} -function workItemStatusColorSelector(item: WorkItemStatusOption): [string, string] { - if (item.key === 'DOING') { - return colorscheme[1]; - } - if (item.key === 'DONE') { - return colorscheme[5]; - } - return colorscheme[7]; -} - -function defaultColorSelector(_: T, i: number): [string, string] { - return colorscheme[i % colorscheme.length]; -} - interface Props { selectedDate: string; setSelectedDate: (newDate: string) => void; @@ -211,8 +163,6 @@ function StartSidebar(props: Props) { setSelectedDate, } = props; - const { enums } = useContext(EnumsContext); - const [storedConfig, setStoredConfig] = useLocalStorage('timur-config'); const setConfigFieldValue = useSetFieldValue(setStoredConfig); @@ -327,65 +277,6 @@ function StartSidebar(props: Props) { labelSelector={numericOptionLabelSelector} /> -
-

- Quick Settings -

- - - - - - -
); } diff --git a/src/views/DailyStandup/index.tsx b/src/views/DailyStandup/index.tsx index 02ccd0e..81c56ed 100644 --- a/src/views/DailyStandup/index.tsx +++ b/src/views/DailyStandup/index.tsx @@ -336,8 +336,9 @@ export function Component() { onClick={handlePresentClick} variant="quaternary" title="Enter full screen" + icons={} > - + Present diff --git a/src/views/Settings/index.tsx b/src/views/Settings/index.tsx new file mode 100644 index 0000000..c8178ef --- /dev/null +++ b/src/views/Settings/index.tsx @@ -0,0 +1,136 @@ +import { useContext } from 'react'; + +import Checkbox from '#components/Checkbox'; +import Page from '#components/Page'; +import SelectInput from '#components/SelectInput'; +import EnumsContext from '#contexts/enums'; +import { EnumsQuery } from '#generated/types/graphql'; +import useLocalStorage from '#hooks/useLocalStorage'; +import useSetFieldValue from '#hooks/useSetFieldValue'; +import { colorscheme } from '#utils/constants'; +import { EditingMode } from '#utils/types'; + +import styles from './styles.module.css'; + +type EditingOption = { key: EditingMode, label: string }; +function editingOptionKeySelector(item: EditingOption) { + return item.key; +} +function editingOptionLabelSelector(item: EditingOption) { + return item.label; +} +const editingOptions: EditingOption[] = [ + { key: 'normal', label: 'Normies' }, + { key: 'vim', label: 'Vim Masterace' }, +]; + +type WorkItemTypeOption = EnumsQuery['enums']['TimeEntryType'][number]; +function workItemTypeKeySelector(item: WorkItemTypeOption) { + return item.key; +} +function workItemTypeLabelSelector(item: WorkItemTypeOption) { + return item.label; +} + +type WorkItemStatusOption = EnumsQuery['enums']['TimeEntryStatus'][number]; +function workItemStatusKeySelector(item: WorkItemStatusOption) { + return item.key; +} +function workItemStatusLabelSelector(item: WorkItemStatusOption) { + return item.label; +} +function workItemStatusColorSelector(item: WorkItemStatusOption): [string, string] { + if (item.key === 'DOING') { + return colorscheme[1]; + } + if (item.key === 'DONE') { + return colorscheme[5]; + } + return colorscheme[7]; +} + +function defaultColorSelector(_: T, i: number): [string, string] { + return colorscheme[i % colorscheme.length]; +} + +// eslint-disable-next-line import/prefer-default-export +export function Component() { + const { enums } = useContext(EnumsContext); + const [storedConfig, setStoredConfig] = useLocalStorage('timur-config'); + const setConfigFieldValue = useSetFieldValue(setStoredConfig); + + return ( + +
+

+ Journal +

+ + + + + +
+
+

+ Note +

+ +
+
+ ); +} + +Component.displayName = 'Settings'; diff --git a/src/views/Settings/styles.module.css b/src/views/Settings/styles.module.css new file mode 100644 index 0000000..6ca80fa --- /dev/null +++ b/src/views/Settings/styles.module.css @@ -0,0 +1,13 @@ +.settings { + .main-content { + display: flex; + flex-direction: column; + gap: var(--spacing-lg); + + .section { + display: flex; + flex-direction: column; + gap: var(--spacing-sm); + } + } +}