Skip to content

Commit

Permalink
Added Planner and Financial Forms
Browse files Browse the repository at this point in the history
  • Loading branch information
anoopkarnik committed Aug 2, 2024
1 parent 21dac7e commit 0b5da0f
Show file tree
Hide file tree
Showing 23 changed files with 1,482 additions and 164 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@ import axios from 'axios'
import { getNotionConnection } from './notion-connections'
import { createNotionPageAction, queryAllNotionDatabaseAction } from '../notion/notion'
import { delay } from '../../lib/utils'
import { modifyNotionPage } from '@repo/notion/notion-client'

const MAX_RETRIES = 3;
const RETRY_DELAY = 1000;
Expand Down Expand Up @@ -225,10 +224,4 @@ const getAccessTokenByRefreshToken = async (refresh_token: string) => {
}catch(err){
return null
}
}

export const modifyNotionPageAction = async ({apiToken,page_id,properties}:any) => {
const response = await modifyNotionPage({apiToken,page_id,properties})
console.log('Modify Notion Page Response', response)
return response;
}
13 changes: 7 additions & 6 deletions apps/dashboard-app/actions/notion/notion.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
'use server'
import { getConnectionsByUserAndType, updateNotionDb} from "@repo/prisma-db/repo/connection";
import { createNotionPage, getNotionDatabaseProperties, queryAllNotionDatabase, queryNotionDatabase } from '@repo/notion/notion-client'
import { createNotionPage, getNotionDatabaseProperties, modifyNotionPage, queryAllNotionDatabase, queryNotionDatabase } from '@repo/notion/notion-client'
import { deletePage } from "../../../../packages/notion/src";

export const getDatabases = async (token: string) => {
Expand Down Expand Up @@ -77,11 +77,6 @@ export const queryNotionDatabaseByDateRange = async ({apiToken,database_id,start
return response;
}

export const createPage = async ({apiToken, dbId, properties}:any) => {
const response = await createNotionPage({apiToken, dbId, properties})
return response;
}

export const deleteNotionPages = async ({apiToken, dbId, ids}:any) => {
for (let id of ids){
await deletePage({apiToken, page_id: id})
Expand All @@ -91,4 +86,10 @@ export const deleteNotionPages = async ({apiToken, dbId, ids}:any) => {
export const createNotionPageAction = async ({apiToken, dbId, properties}:any) => {
const response = await createNotionPage({apiToken, database_id:dbId, properties})
return response;
}

export const modifyNotionPageAction = async ({apiToken, pageId, properties}:any) => {
console.log('Modifying Page', pageId)
const response = await modifyNotionPage({apiToken, page_id:pageId, properties})
return response;
}
9 changes: 7 additions & 2 deletions apps/dashboard-app/actions/notion/planner.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
'use server'

import { queryAllNotionDatabaseAction } from "./notion"
import { createNotionPageAction, queryAllNotionDatabaseAction } from "./notion"

export const getCalendarSummary = async ({apiToken, calendarDbId}:any) => {
let filters:any= [
Expand Down Expand Up @@ -67,7 +67,7 @@ export const getWeeklyPlannerSummary = async ({apiToken, weeklyPlannerDbId}:any)
]
let sorts:any = [
{
name: 'Created time',
ame: 'Created time',
type: 'created_time',
direction: 'descending'
}
Expand All @@ -85,4 +85,9 @@ export const getWeeklyPlannerSummary = async ({apiToken, weeklyPlannerDbId}:any)
weeklyPlannerTasks,
totalHoursLeft
}
}

export const createTimeTrackingPage = async ({apiToken, timeTrackingDbId, properties}:any) => {
const response = await createNotionPageAction({apiToken, dbId: timeTrackingDbId, properties})
return response
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,128 @@
import { Button } from '@repo/ui/molecules/shadcn/Button'
import { Input } from '@repo/ui/molecules/shadcn/Input'
import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from '@repo/ui/molecules/shadcn/Select'
import React, { useContext, useEffect, useState } from 'react'
import { ConnectionsContext } from '../../../../providers/connections-provider'
import { createNotionPageAction, queryNotionDatabaseAction } from '../../../../actions/notion/notion'

const BudgetForm = () => {
const connectionsContext = useContext(ConnectionsContext)
const apiToken = connectionsContext?.notionNode?.accessToken
const budgetDbId = connectionsContext?.notionNode?.monthlyBudgetDb?.id
let schedulerDbId = connectionsContext?.notionNode?.schedulerDb?.id
let expenseTypes = ['Living','Growth','Delight','Saving','Others']
let schedulerTypes = ['Monthly','BiMonthly','Quarterly','Yearly','Half Yearly']


const [name, setName] = useState('')
const [cost, setCost] = useState('')
const [expenseType, setExpenseType] = useState('')
const [schedulerType, setSchedulerType] = useState('')
const [scheduler, setScheduler] = useState('')
const [schedulers, setSchedulers] = useState([])
const [filteredSchedulers, setFilteredSchedulers] = useState([])
const [searchSchedulerQuery, setSearchSchedulerQuery] = useState('')


useEffect(() => {
const updateSummary = async () => {
try{
if (!apiToken || !schedulerDbId) {
return
}
const schedulers = await queryNotionDatabaseAction({apiToken,database_id:schedulerDbId})
setSchedulers(schedulers.results)
setFilteredSchedulers(schedulers.results)

}catch(e){
console.error('Error in fetching schedulers',e)
}
}
updateSummary()
},[apiToken, schedulerDbId])

const handleScheduler = (event:any) => {
const query = event.target.value.toLowerCase();
setSearchSchedulerQuery(query)
setFilteredSchedulers(schedulers?.filter((scheduler:any) => {
if(scheduler.Name ===null) return
return scheduler.Name.toLowerCase().includes(query)
}));
}

const handleAddBudget = async () => {
if (!name || !cost || !expenseType || !schedulerType || !scheduler) {
return
}
const selectedScheduler:any = schedulers?.find((scheduler:any) => scheduler.Name === scheduler)
if (!scheduler) {
return
}
const properties:any = [
{name:'Name',type: 'title', value: name},
{name:'Cost',type: 'number', value: Number(cost)},
{name:'Expense Type',type: 'select', value: expenseType},
{name:'Scheduler Type',type: 'select', value: schedulerType},
{name:'Scheduler',type: 'relation', value: [selectedScheduler.id]},
]
const dbId = budgetDbId
const response = await createNotionPageAction({apiToken, dbId, properties})
console.log(response)
}


return (
<div className='flex flex-col items-center justify-center gap-4 border-2 border-border/20 p-4 m-2'>
<div className='flex items-center justify-between gap-4 w-[95%] flex-wrap my-2 mx-2 '>
<Input className='w-[300px]' placeholder='Name' value={name} onChange={(event)=>setName(event.target.value)} />
<Input className='w-[300px]' placeholder='Cost' value={cost} onChange={(event)=>setCost(event.target.value)} />
<Select value={expenseType} onValueChange={(value) => setExpenseType(value)} >
<SelectTrigger className='w-[300px]'>
<SelectValue placeholder={`Select Expense Type`}/>
</SelectTrigger>
<SelectContent>
{expenseTypes.length> 0 && expenseTypes?.map((expenseType:any) => (
<SelectItem key={expenseType} value={expenseType}>
<div className='flex items-center justify-center gap-4'>
<div>{expenseType}</div>
</div>
</SelectItem>
))}
</SelectContent>
</Select>
<Select value={schedulerType} onValueChange={(value) => setSchedulerType(value)} >
<SelectTrigger className='w-[300px]'>
<SelectValue placeholder={`Select Scheduler Type`}/>
</SelectTrigger>
<SelectContent>
{schedulerTypes.length> 0 && schedulerTypes?.map((schedulerType:any) => (
<SelectItem key={schedulerType} value={schedulerType}>
<div className='flex items-center justify-center gap-4'>
<div>{schedulerType}</div>
</div>
</SelectItem>
))}
</SelectContent>
</Select>
<Select value={scheduler} onValueChange={(value) => setScheduler(value)} >
<SelectTrigger className='w-[300px]'>
<SelectValue placeholder={`Select Budget`}/>
</SelectTrigger>
<SelectContent>
<Input placeholder='Search Budget' className='w-full' value={searchSchedulerQuery} onChange={handleScheduler} />
{filteredSchedulers.length> 0 && filteredSchedulers?.map((scheduler:any) => (
<SelectItem key={scheduler.id} value={scheduler.Name}>
<div className='flex items-center justify-center gap-4'>
<div>{scheduler.Name}</div>
</div>
</SelectItem>
))}
</SelectContent>
</Select>
</div>
<Button onClick={handleAddBudget} className='font-bold w-[300px]' variant='secondary'> Add a Budget</Button>
</div>
)
}

export default BudgetForm
Original file line number Diff line number Diff line change
@@ -1,18 +1,18 @@
'use client'
import React, { useContext, useEffect, useState } from 'react'
import { format, set } from "date-fns";
import { format } from "date-fns";
import { DatePickerWithRange } from '@repo/ui/molecules/shadcn/DateRange';
import { ConnectionsContext } from '../../../../providers/connections-provider';
import { getAccountsSummary, getDateSpecificFinancialSummary, getLastMonthsFinancialSummary, getYearlyBudgetSummary, getMonthlyBudgetSummary, getPastMonthsBudgetSummary, } from '../../../../actions/notion/financial'
import { getAccountsSummary, getDateSpecificFinancialSummary, getLastMonthsFinancialSummary, getYearlyBudgetSummary,
getMonthlyBudgetSummary, getPastMonthsBudgetSummary, } from '../../../../actions/notion/financial'
import ChartCard from '@repo/ui/molecules/common/ChartCard';
import { ChartConfig } from '@repo/ui/molecules/shadcn/Chart';
import { Accordion, AccordionContent, AccordionItem, AccordionTrigger } from '@repo/ui/molecules/shadcn/Accordion';
import {Skeleton} from '@repo/ui/molecules/shadcn/Skeleton'
import HeaderCard from '@repo/ui/molecules/common/HeaderCard';
import { Input } from '@repo/ui/molecules/shadcn/Input';
import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from '@repo/ui/molecules/shadcn/Select';
import { Button } from '@repo/ui/molecules/shadcn/Button';
import { createNotionPageAction, queryNotionDatabaseAction } from '../../../../actions/notion/notion';
import { queryNotionDatabaseAction } from '../../../../actions/notion/notion';
import TransactionForm from './TransactionForm';
import BudgetForm from './BudgetForm';

const Overview = () => {

Expand All @@ -33,12 +33,8 @@ const Overview = () => {
const [endDate, setEndDate] = useState('')

// Add Transaction
const [name, setName] = useState('')
const [cost, setCost] = useState('')
const [selectedBudget, setSelectedBudget] = useState('')
const [budgets, setBudgets] = useState([])
const [filteredBudgets, setFilteredBudgets] = useState([])
const [searchBudgetQuery, setSearchBudgetQuery] = useState('')


useEffect(() => {
const updateSummary = async () => {
Expand All @@ -53,7 +49,6 @@ const Overview = () => {
}
const budgets = await queryNotionDatabaseAction({apiToken,database_id:budgetDbId})
setBudgets(budgets.results)
setFilteredBudgets(budgets.results)

let dateSpecificSummary = await getDateSpecificFinancialSummary({apiToken,transactionsDbId,startDate,endDate})
setDateSpecificSummary(dateSpecificSummary)
Expand Down Expand Up @@ -82,34 +77,6 @@ const Overview = () => {
updateSummary()
},[apiToken, transactionsDbId, accountsDbId, budgetDbId])

const handleBudget = (event:any) => {
const query = event.target.value.toLowerCase();
setSearchBudgetQuery(query)
setFilteredBudgets(budgets?.filter((budget:any) => {
if(budget.Name ===null) return
return budget.Name.toLowerCase().includes(query)
}));
}

const handleAddTransaction = async () => {
if (!name || !cost || !selectedBudget) {
return
}
const budget:any = budgets?.find((budget:any) => budget.Name === selectedBudget)
if (!budget) {
return
}
const properties:any = [
{name:'Name',type: 'title', value: name},
{name:'Cost',type: 'number', value: Number(cost)},
{name:'Monthly Budget',type: 'relation', value: [budget.id]}
]
const dbId = transactionsDbId
const response = await createNotionPageAction({apiToken, dbId, properties})
console.log(response)
}


const onTimeUpdate = async (dateRange: any) => {
if (!dateRange) {
return;
Expand Down Expand Up @@ -171,38 +138,23 @@ const Overview = () => {
<HeaderCard title='Time Left to Loss' description='Time left to Loss based on current expenses and income' value={`${timeLeftToLoss} Months`}/>
</div>
<div>
{budgets ? <Accordion type="single" collapsible className='w-full'>
{budgets ?
<Accordion type="single" collapsible className='w-full'>
<AccordionItem value="item-1">
<AccordionTrigger>
<div className='flex justify-between items-center w-full mr-2'>
<div> Add New Transactions and Budgets </div>
</div>
</AccordionTrigger>
<AccordionContent>
<div className='flex items-center gap-4 w-full flex-wrap my-2 mx-2'>
<Input className='w-[200px]' placeholder='Name' value={name} onChange={(event)=>setName(event.target.value)} />
<Input className='w-[200px]' placeholder='Cost' value={cost} onChange={(event)=>setCost(event.target.value)} />
<Select value={selectedBudget} onValueChange={(value) => setSelectedBudget(value)} >
<SelectTrigger className='w-[200px]'>
<SelectValue placeholder={`Select Budget`}/>
</SelectTrigger>
<SelectContent>
<Input placeholder='Search Budget' className='w-full' value={searchBudgetQuery} onChange={handleBudget} />
{filteredBudgets.length> 0 && filteredBudgets?.map((budget:any) => (
<SelectItem key={budget.id} value={budget.Name}>
<div className='flex items-center justify-center gap-4'>
<div>{budget.Name}</div>
</div>
</SelectItem>
))}
</SelectContent>
</Select>
<Button onClick={handleAddTransaction} className='font-bold'> Add a Transaction</Button>
</div>
<TransactionForm/>
<BudgetForm/>
</AccordionContent>
</AccordionItem>
</Accordion>: <Skeleton className=" h-[30px] rounded-full my-6" />}
{dateSpecificSummary ? <Accordion type="single" collapsible className='w-full'>
</Accordion>: <Skeleton className=" h-[30px] rounded-full my-6" />
}
{dateSpecificSummary ?
<Accordion type="single" collapsible className='w-full'>
<AccordionItem value="item-1">
<AccordionTrigger>
<div className='flex justify-between items-center w-full mr-2'>
Expand Down Expand Up @@ -233,8 +185,10 @@ const Overview = () => {
</div>
</AccordionContent>
</AccordionItem>
</Accordion>: <Skeleton className=" h-[30px] rounded-full my-6" />}
{lastMonthsSummary? <Accordion type="single" collapsible className='w-full'>
</Accordion>: <Skeleton className=" h-[30px] rounded-full my-6" />
}
{lastMonthsSummary?
<Accordion type="single" collapsible className='w-full'>
<AccordionItem value="item-1">
<AccordionTrigger>
<div className='flex justify-between items-center w-full mr-2'>
Expand Down Expand Up @@ -264,7 +218,9 @@ const Overview = () => {
</div>
</AccordionContent>
</AccordionItem>
</Accordion>: <Skeleton className=" h-[30px] rounded-full my-6" />}
</Accordion>:
<Skeleton className=" h-[30px] rounded-full my-6" />
}
{accountsSummary? <Accordion type="single" collapsible className='w-full'>
<AccordionItem value="item-1">
<AccordionTrigger>
Expand Down
Loading

0 comments on commit 0b5da0f

Please sign in to comment.