Skip to content

Commit

Permalink
Integrate link budget
Browse files Browse the repository at this point in the history
  • Loading branch information
ParadoxZero committed Aug 13, 2024
1 parent 6ddf2e7 commit 326a2d3
Show file tree
Hide file tree
Showing 3 changed files with 114 additions and 4 deletions.
20 changes: 17 additions & 3 deletions ui/components/header.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ import { connect } from "react-redux";
import { budgetSlice, headerSlice, navigate, store, View } from "../store";
import { GetScreenSize, ScreenSize } from "../utils";
import { ShareBudgetModal } from "./share_budget_modal";
import { LinkBudgetModal } from "./link_budget_modal";

export interface HeaderBudgetDetails {
name: string;
Expand All @@ -42,6 +43,7 @@ export interface HeaderProps {
interface HeaderState {
is_budget_selector_visible: boolean;
open_share_modal: boolean;
open_link_modal: boolean;
}

class Header extends React.Component<HeaderProps, HeaderState> {
Expand Down Expand Up @@ -73,6 +75,7 @@ class Header extends React.Component<HeaderProps, HeaderState> {
this.state = {
is_budget_selector_visible: false,
open_share_modal: false,
open_link_modal: false,
};
}

Expand All @@ -96,15 +99,20 @@ class Header extends React.Component<HeaderProps, HeaderState> {
store.dispatch(budgetSlice.actions.updateSelection({ index: null }));
store.dispatch(navigate(View.NoBudgetAvailable));
};
const linkBudget = (e: React.MouseEvent<HTMLButtonElement | HTMLAnchorElement>) => {
this.setState({ open_link_modal: true });
e.preventDefault();
}
const onSelectionChanged = (value: number) => {
store.dispatch(budgetSlice.actions.updateSelection({ index: value }));
}
};
const onSettingsClicked = () => {
this.setState({ is_budget_selector_visible: false });
store.dispatch(navigate(View.NoBudgetAvailable));
}
};

return (
<>
<Select
size="large"
style={{ width: 300 }}
Expand All @@ -123,7 +131,7 @@ class Header extends React.Component<HeaderProps, HeaderState> {
<Button type="text" icon={<PlusOutlined />} onClick={addItem}>
New
</Button>
<Button type="text" icon={<LinkOutlined />} disabled onClick={addItem}>
<Button type="text" icon={<LinkOutlined />} onClick={linkBudget}>
Link
</Button>
</Flex>
Expand All @@ -136,6 +144,12 @@ class Header extends React.Component<HeaderProps, HeaderState> {
)}
variant="outlined"
/>
<LinkBudgetModal
isOpen={this.state.open_link_modal}
onDone={() => { store.dispatch(navigate(View.Overview)); }}
onClose={() => { this.setState({ open_link_modal: false }) }}
/>
</>
);
}

Expand Down
87 changes: 87 additions & 0 deletions ui/components/link_budget_modal.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
/*
* BudgetBug - Budgeting and Expense Tracker with WebUI and API server
* Copyright (C) 2024 Sidhin S Thomas <[email protected]>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published
* by the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*
* The source is available at: https://github.com/ParadoxZero/budgetbud
*/

import { Button, Flex, Input, message, Modal, Typography } from "antd";
import { useState } from "react";
import { LinkBudget } from "../services/share_service";
import { InputStatus } from "antd/es/_util/statusUtils";

export function LinkBudgetModal(props: { isOpen: boolean, onDone: () => void, onClose: () => void }) {
const [confirmLoading, setConfirmLoading] = useState(false);
const [validationStatus, setValidationStatus] = useState("");
const [messageApi, contextHolder] = message.useMessage();

const handle_ok = () => {
setConfirmLoading(true);
const code = (document.getElementById('share_code_id') as HTMLInputElement).value
if (code.length == 0) {
messageApi.error("Please enter the share code.", 5);
setValidationStatus("error");
setConfirmLoading(false);
return;
}
LinkBudget(code).then(() => {
props.onDone();
messageApi.error("Succesfully linked the budget.", 5);
}).catch(()=>{
messageApi.error("Failed to link budget.", 5);
}).finally(() => {
setConfirmLoading(false);
props.onClose();
});

}
let status: InputStatus = "";
switch (validationStatus) {
case "error":
status = "error";
break;
case "warning":
status = "warning";
break;
}
return (
<>
{contextHolder}
<Modal
centered
closable={true}
destroyOnClose
keyboard
mask
width={300}
maskClosable
confirmLoading={confirmLoading}
onCancel={props.onClose}
title="Link Budget"
footer={(
<Flex style={{ width: "100%" }} align="center" justify="center">
<Button type="primary" size="large" onClick={handle_ok}>Ok</Button>
</Flex>
)}
open={props.isOpen}>
<Flex vertical align="center" justify="center">
<Typography.Paragraph>Linking budget will allow you to share the budget with others.</Typography.Paragraph>
<Input id="share_code_id" size="large" placeholder="Enter Share Code" status={status} />
</Flex>
</Modal>
</>
);
}
11 changes: 10 additions & 1 deletion ui/services/share_service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,9 +26,18 @@ export interface ShareKeyResponse {

export async function GetShareKey(budget_id: string): Promise<ShareKeyResponse> {
if (import.meta.env.VITE_USE_LOCAL_DATA_SERVICE === 'true') {
await new Promise((resolve,_reject) => _reject("Failed"));
await new Promise((resolve,_reject) => setTimeout(resolve, 3000));
return { shareKey: "2U0T0Y05" };
}
const response = await fetchData(`/api/Social/share_code/${budget_id}`, {method:"POST"});
return await response.json();
}

export async function LinkBudget(share_key: string): Promise<void> {
if (import.meta.env.VITE_USE_LOCAL_DATA_SERVICE === 'true') {
await new Promise((resolve,_reject) => setTimeout(resolve, 3000));
return;
}
await fetchData(`/api/Social/link/${share_key}`, {method:"POST"});
return;
}

0 comments on commit 326a2d3

Please sign in to comment.