Skip to content

Commit

Permalink
Expense chart joyride
Browse files Browse the repository at this point in the history
  • Loading branch information
EdDiazGRS committed Sep 9, 2024
1 parent 4418584 commit 5a1c8ee
Show file tree
Hide file tree
Showing 5 changed files with 179 additions and 95 deletions.
8 changes: 7 additions & 1 deletion client/src/components/Chart.jsx
Original file line number Diff line number Diff line change
@@ -1,10 +1,15 @@
import React, { useEffect, useState } from 'react';
import React, { useEffect, useState, useContext } from 'react';
import BackButton from "./BackButton.jsx";
import { auth, onAuthStateChanged } from "../config/initializeFirestore.js";
import '../App.css';
import HamburgerMenu from "./HamburgerMenu.jsx";
import { AppContext } from '../context/AppContext.jsx';
import ExpenseChartJoyride from './ExpenseChartJoyride.jsx';



function App() {
const {runChartTour, setRunChartTour} = useContext(AppContext);
const [userId, setUserId] = useState("");
const [userEmail, setUserEmail] = useState("");
const [dimensions, setDimensions] = useState({
Expand Down Expand Up @@ -40,6 +45,7 @@ function App() {

return (
<div className="App">
< ExpenseChartJoyride />
<h1>SimpliTrac</h1>
<HamburgerMenu />
<LookerStudioChart dimensions={dimensions} userEmail={userEmail} />
Expand Down
62 changes: 62 additions & 0 deletions client/src/components/ExpenseChartJoyride.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
import React, { useContext } from 'react';
import Joyride, { STATUS } from 'react-joyride';
import { AppContext } from '../context/AppContext';

const steps = [
{
target: 'body',
content: 'Welcome to the Expense Chart! This guide will walk you through the features of this powerful visualization tool.',
placement: 'center',
disableBeacon: true,
},
{
target: '#report-frame',
content: 'This is your expense chart. It provides a detailed view of your spending patterns.',
},
{
target: '#report-frame',
content: 'In the top left corner, you can switch between Mobile and Desktop views.',
},
{
target: '#report-frame',
content: 'The three-dot menu in the top right allows you to export your data in various formats.',
},
{
target: '#report-frame',
content: 'Use the date range selector at the top to filter your expenses for specific time periods.',
},
{
target: 'body',
content: 'Explore your spending patterns and gain insights into your financial habits. Remember to refer back to these features as you use the chart!',
placement: 'center',
},
];

const ExpenseChartJoyride = () => {
const { runChartTour, setRunChartTour } = useContext(AppContext);

const handleJoyrideCallback = (data) => {
const { status } = data;
if ([STATUS.FINISHED, STATUS.SKIPPED].includes(status)) {
setRunChartTour(false);
}
};

return (
<Joyride
steps={steps}
run={runChartTour}
continuous={true}
showSkipButton={true}
showProgress={true}
styles={{
options: {
zIndex: 10000,
},
}}
callback={handleJoyrideCallback}
/>
);
};

export default ExpenseChartJoyride;
188 changes: 96 additions & 92 deletions client/src/components/ExpensesTable.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import { AppContext } from "../context/AppContext.jsx";
import Transaction from "../models/Transaction.js";
import User from "../models/User.js";
import Updating from "./Updating.jsx";
import ExpenseChartJoyride from "./ExpenseChartJoyride.jsx";

const ExpensesForm = () => {
const { user, formData, setFormData, setUser, ocrData, setOcrData, setServerResponse, isUpdating, setIsUpdating } = useContext(AppContext);
Expand Down Expand Up @@ -106,98 +107,101 @@ const ExpensesForm = () => {
};

return (
<Box as="form" onSubmit={handleSubmit(onSubmit)} maxW="500px" mx="auto">
{isUpdating && <Updating />} {/* Show overlay when isUpdating is true */}
<FormControl mb={4} isInvalid={errors.date}>
<FormLabel>Date</FormLabel>
<Controller
name="date"
control={control}
render={({ field }) => <Input type="date" {...field} />}
/>
</FormControl>

<FormControl mb={4} isInvalid={errors.vendor}>
<FormLabel>Vendor</FormLabel>
<Controller
name="vendor"
control={control}
rules={{ required: 'Please select a vendor' }}
render={({ field }) => (
<CreatableSelect
{...field}
options={vendors}
placeholder="Select or type a vendor..."
isClearable
isSearchable
styles={customSelectStyles}
onChange={(selectedOption) => {
const newValue = selectedOption?.value || '';
field.onChange(newValue);
if (newValue && !vendors.some(v => v.value === newValue)) {
setVendors([...vendors, { value: newValue, label: newValue }]);
}
}}
value={vendors.find(v => v.value === field.value) || null}
/>
)}
/>
{errors.vendor && <Text color="red.500">{errors.vendor.message}</Text>}
</FormControl>

<FormControl mb={4} isInvalid={errors.category}>
<FormLabel>Category</FormLabel>
<Controller
name="category"
control={control}
rules={{ required: 'Please select a category' }}
render={({ field }) => (
<CreatableSelect
{...field}
options={categories}
placeholder="Select or type a category..."
isClearable
isSearchable
styles={customSelectStyles}
onChange={(selectedOption) => {
const newValue = selectedOption?.value || '';
field.onChange(newValue);
if (newValue && !categories.some(c => c.value === newValue)) {
setCategories([...categories, { value: newValue, label: newValue }]);
}
}}
value={categories.find(c => c.value === field.value) || null}
/>
)}
/>
{errors.category && <Text color="red.500">{errors.category.message}</Text>}
</FormControl>

<FormControl mb={4} isInvalid={errors.amount}>
<FormLabel htmlFor="amount">Amount</FormLabel>
<Controller
name="amount"
control={control}
rules={{
required: 'Please enter a valid amount. Enter a number without the "$" sign',
validate: value => {
const numberChecker = /^-?\d*(\.\d*)?$/;
return numberChecker.test(value) ? true : 'Please enter a valid amount. Enter a number without the "$" sign';
}
}}
render={({ field, fieldState: { error } }) => (
<>
<Input type="text" {...field} />
{error && <Text color="red.500">{error.message}</Text>}
</>
)}
/>
</FormControl>

<Button type="submit" background="#415a77" width="full">
{isUpdating ? <Spinner size="sm" /> : 'Submit'}
</Button>
</Box>
<>
< ExpenseChartJoyride />
<Box as="form" onSubmit={handleSubmit(onSubmit)} maxW="500px" mx="auto">
{isUpdating && <Updating />} {/* Show overlay when isUpdating is true */}
<FormControl mb={4} isInvalid={errors.date}>
<FormLabel>Date</FormLabel>
<Controller
name="date"
control={control}
render={({ field }) => <Input type="date" {...field} />}
/>
</FormControl>

<FormControl mb={4} isInvalid={errors.vendor}>
<FormLabel>Vendor</FormLabel>
<Controller
name="vendor"
control={control}
rules={{ required: 'Please select a vendor' }}
render={({ field }) => (
<CreatableSelect
{...field}
options={vendors}
placeholder="Select or type a vendor..."
isClearable
isSearchable
styles={customSelectStyles}
onChange={(selectedOption) => {
const newValue = selectedOption?.value || '';
field.onChange(newValue);
if (newValue && !vendors.some(v => v.value === newValue)) {
setVendors([...vendors, { value: newValue, label: newValue }]);
}
}}
value={vendors.find(v => v.value === field.value) || null}
/>
)}
/>
{errors.vendor && <Text color="red.500">{errors.vendor.message}</Text>}
</FormControl>

<FormControl mb={4} isInvalid={errors.category}>
<FormLabel>Category</FormLabel>
<Controller
name="category"
control={control}
rules={{ required: 'Please select a category' }}
render={({ field }) => (
<CreatableSelect
{...field}
options={categories}
placeholder="Select or type a category..."
isClearable
isSearchable
styles={customSelectStyles}
onChange={(selectedOption) => {
const newValue = selectedOption?.value || '';
field.onChange(newValue);
if (newValue && !categories.some(c => c.value === newValue)) {
setCategories([...categories, { value: newValue, label: newValue }]);
}
}}
value={categories.find(c => c.value === field.value) || null}
/>
)}
/>
{errors.category && <Text color="red.500">{errors.category.message}</Text>}
</FormControl>

<FormControl mb={4} isInvalid={errors.amount}>
<FormLabel htmlFor="amount">Amount</FormLabel>
<Controller
name="amount"
control={control}
rules={{
required: 'Please enter a valid amount. Enter a number without the "$" sign',
validate: value => {
const numberChecker = /^-?\d*(\.\d*)?$/;
return numberChecker.test(value) ? true : 'Please enter a valid amount. Enter a number without the "$" sign';
}
}}
render={({ field, fieldState: { error } }) => (
<>
<Input type="text" {...field} />
{error && <Text color="red.500">{error.message}</Text>}
</>
)}
/>
</FormControl>

<Button type="submit" background="#415a77" width="full">
{isUpdating ? <Spinner size="sm" /> : 'Submit'}
</Button>
</Box>
</>
);
};

Expand Down
13 changes: 11 additions & 2 deletions client/src/components/HamburgerMenu.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,9 @@ const HamburgerMenu = () => {
renderNewScreen,
showCategories,
toggleCategoriesList,
user, setRunTour
user,
setRunTour,
setRunChartTour
} = useContext(AppContext);
const {isOpen, onOpen, onClose} = useDisclosure();

Expand Down Expand Up @@ -86,7 +88,14 @@ const HamburgerMenu = () => {
variant="ghost"
w="100%"
data-tour="expense-chart"
onClick={() => renderNewScreen("chart")}>Expense Chart</Button>
onClick={() => {
renderNewScreen("chart");
setRunChartTour(true);
setShowHamburger(false);
}}
>
Expense Chart
</Button>
<Button
variant="ghost"
w="100%"
Expand Down
3 changes: 3 additions & 0 deletions client/src/context/AppContext.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ const AppProvider = ({ children }) => {
const [categoriesSelected, setCategoriesSelected] = useState(false);
const [runTour, setRunTour] = useState(false);
const [runEditTransactionsTour, setRunEditTransactionsTour] =useState(false);
const [runChartTour, setRunChartTour] =useState(false);



Expand Down Expand Up @@ -93,6 +94,7 @@ const AppProvider = ({ children }) => {
setShowCategories(false)
setRunTour(false)
setRunEditTransactionsTour(false)
setRunChartTour(false)
};

// updating data based on user state
Expand Down Expand Up @@ -121,6 +123,7 @@ const AppProvider = ({ children }) => {
toggleCategoriesList,
categoriesSelected, setCategoriesSelected,
runEditTransactionsTour, setRunEditTransactionsTour,
runChartTour, setRunChartTour,
};


Expand Down

0 comments on commit 5a1c8ee

Please sign in to comment.