From b11015ed3ac080dc45cd16ebcd41a3e25e1637a6 Mon Sep 17 00:00:00 2001 From: Bruno Bernardino Date: Fri, 4 Dec 2020 07:33:19 +0000 Subject: [PATCH] Copying of budgets and limiting future month navigation. --- components/Panels/All.tsx | 35 ++++++++++++++++++++++++++++++++-- components/Panels/Budgets.tsx | 9 +++++++++ components/Panels/Expenses.tsx | 9 +++++++++ lib/data-utils.ts | 19 ++++++++++++++++++ 4 files changed, 70 insertions(+), 2 deletions(-) diff --git a/components/Panels/All.tsx b/components/Panels/All.tsx index 6cdb793..6445fc0 100644 --- a/components/Panels/All.tsx +++ b/components/Panels/All.tsx @@ -7,7 +7,12 @@ import { RxDatabase } from 'rxdb'; import LogoutLink from 'modules/auth/LogoutLink'; import { Loading } from 'components'; import { getUserInfo, showNotification } from 'lib/utils'; -import { initializeDb, fetchBudgets, fetchExpenses } from 'lib/data-utils'; +import { + initializeDb, + fetchBudgets, + fetchExpenses, + copyBudgets, +} from 'lib/data-utils'; import * as T from 'lib/types'; import Navigation from './Navigation'; @@ -41,7 +46,7 @@ const All = () => { const [expenses, setExpenses] = useState([]); const db = useRef(null); - const reloadData = async () => { + const reloadData = async ({ isComingFromEmptyState = false } = {}) => { setIsLoading(true); const fetchedBudgets = await fetchBudgets(db.current, monthInView); @@ -50,6 +55,25 @@ const All = () => { const fetchedExpenses = await fetchExpenses(db.current, monthInView); setExpenses(fetchedExpenses); + // If this is for the current or next month and there are no budgets, create budgets based on the previous/current month. + if (fetchedBudgets.length === 0 && !isComingFromEmptyState) { + const currentMonth = moment().format('YYYY-MM'); + const nextMonth = moment().add(1, 'month').format('YYYY-MM'); + const previousMonth = moment().subtract(1, 'month').format('YYYY-MM'); + + if (monthInView === nextMonth) { + await copyBudgets(db.current, currentMonth, nextMonth); + await reloadData({ isComingFromEmptyState: true }); + return; + } + + if (monthInView === currentMonth) { + await copyBudgets(db.current, previousMonth, currentMonth); + await reloadData({ isComingFromEmptyState: true }); + return; + } + } + showNotification( 'Data is continuously synchronizing in the background. Navigate between months to see the latest data.', ); @@ -58,6 +82,13 @@ const All = () => { }; const changeMonthInView = async (month: string) => { + const nextMonth = moment().add(1, 'month').format('YYYY-MM'); + + if (month > nextMonth) { + showNotification('Cannot travel further into the future!', 'error'); + return; + } + setIsLoading(true); setMonthInView(month); diff --git a/components/Panels/Budgets.tsx b/components/Panels/Budgets.tsx index 3d73a77..959be75 100644 --- a/components/Panels/Budgets.tsx +++ b/components/Panels/Budgets.tsx @@ -15,6 +15,14 @@ interface BudgetsToShow extends T.Budget { expensesCost: number; } +// user-agent sniffing sucks, but I couldn't figure out why this problem only happens on Safari (macOS and iOS) +const safariFix = + typeof navigator !== 'undefined' && + navigator.userAgent && + navigator.userAgent.includes('Safari') + ? 'max-block-size: 100%;' + : ''; + const Container = styled.section` display: flex; flex-direction: column; @@ -22,6 +30,7 @@ const Container = styled.section` margin: 0 10px; max-height: 80vh; overflow: auto; + ${safariFix} `; const AddButton = styled(Button)` diff --git a/components/Panels/Expenses.tsx b/components/Panels/Expenses.tsx index c32e4c2..086430a 100644 --- a/components/Panels/Expenses.tsx +++ b/components/Panels/Expenses.tsx @@ -11,12 +11,21 @@ import * as T from 'lib/types'; interface ExpensesProps extends T.PanelProps {} +// user-agent sniffing sucks, but I couldn't figure out why this problem only happens on Safari (macOS and iOS) +const safariFix = + typeof navigator !== 'undefined' && + navigator.userAgent && + navigator.userAgent.includes('Safari') + ? 'max-block-size: 100%;' + : ''; + const Container = styled.section` display: flex; flex-direction: column; flex: 1; max-height: 80vh; overflow: auto; + ${safariFix} `; const FiltersContainer = styled.section` diff --git a/lib/data-utils.ts b/lib/data-utils.ts index f4ed3b8..921b1be 100644 --- a/lib/data-utils.ts +++ b/lib/data-utils.ts @@ -637,3 +637,22 @@ export const importData = async ( return false; }; + +export const copyBudgets = async ( + db: RxDatabase, + originalMonth: string, + destinationMonth: string, +) => { + const originalBudgets = await fetchBudgets(db, originalMonth); + const destinationBudgets = originalBudgets.map((budget) => { + const newBudget: T.Budget = { ...budget }; + newBudget.id = `${Date.now().toString()}:${Math.random()}`; + newBudget.month = destinationMonth; + delete newBudget._rev; + return newBudget; + }); + + if (destinationBudgets.length > 0) { + await db.budgets.bulkInsert(destinationBudgets); + } +};