wisesplit/pages/index.tsx

128 lines
3.2 KiB
TypeScript
Raw Normal View History

import { useAtom, atom } from "jotai";
2022-10-24 07:10:52 +00:00
import type { NextPage } from "next";
import { useEffect, useRef } from "react";
2022-10-25 18:26:48 +00:00
import { SyntheticEvent, useState } from "react";
2022-10-24 07:40:14 +00:00
import { Form } from "react-bootstrap";
2022-10-24 19:00:16 +00:00
import NumberEditBox from "../components/NumberEditBox";
import ReceiptItem from "../components/ReceiptItem";
import { moneyFormatter } from "../lib/formatter";
import { ParsedInputDisplay } from "../lib/parseInput";
2022-10-24 07:40:14 +00:00
import {
addLine,
receiptAtom,
receiptTotalAtom,
totalAtom,
} from "../lib/state";
2022-10-24 07:10:52 +00:00
const Home: NextPage = () => {
const [receipt, setReceipt] = useAtom(receiptAtom);
const [input, setInput] = useState("");
2022-10-24 19:00:16 +00:00
const [total] = useAtom(totalAtom);
const [calculated] = useAtom(receiptTotalAtom);
const isAddCalled = useRef(false);
const [receiptJson] = useAtom(
atom((get) => {
const receiptJson: any[] = [];
for (const itemAtom of receipt) {
const receiptItemFromAtom = get(itemAtom);
const splitBetweenArray = get(receiptItemFromAtom.splitBetween).map(
(personAtom) => ({
name: get(get(personAtom).name),
})
);
const receiptItemParsed = {
name: get(receiptItemFromAtom.name),
price: get(receiptItemFromAtom.price),
splitBetween: splitBetweenArray,
};
receiptJson.push(receiptItemParsed);
}
return receiptJson;
})
);
2022-10-24 07:10:52 +00:00
const formatter = new Intl.NumberFormat("en-US", {
style: "currency",
currency: "USD",
});
const add = async (e: SyntheticEvent) => {
2022-10-24 07:10:52 +00:00
e.preventDefault();
isAddCalled.current = true;
2022-10-25 18:26:48 +00:00
addLine(input, receipt, setReceipt);
2022-10-24 07:10:52 +00:00
setInput("");
return false;
};
const receiptJSONString = JSON.stringify(receiptJson);
useEffect(() => {
const updateDb = async () => {
const response = await fetch("/api/createReceipt", {
method: "POST",
body: JSON.stringify({ receipts: receiptJson }),
});
console.log(receiptJSONString);
};
if (isAddCalled.current) {
updateDb();
}
}, [receiptJSONString]);
2022-10-24 07:10:52 +00:00
return (
<main>
2022-10-24 07:40:14 +00:00
<h1>Items</h1>
2022-10-24 07:10:52 +00:00
2022-10-24 07:40:14 +00:00
<Form onSubmit={add}>
2022-10-24 07:10:52 +00:00
<ParsedInputDisplay input={input} />
2022-10-24 07:40:14 +00:00
<Form.Control
2022-10-24 07:18:22 +00:00
autoFocus={true}
2022-10-24 07:10:52 +00:00
type="text"
placeholder="Add item..."
2022-10-25 18:26:48 +00:00
onInput={(e) => setInput(e.currentTarget.value)}
2022-10-24 07:10:52 +00:00
value={input}
2022-10-24 18:27:34 +00:00
style={{ padding: "8px 16px", fontSize: "1.5em" }}
2022-10-24 07:10:52 +00:00
/>
2022-10-24 07:40:14 +00:00
</Form>
2022-10-24 07:10:52 +00:00
2022-11-04 17:05:04 +00:00
{receipt.map((itemAtom, i) => {
return <ReceiptItem itemAtom={itemAtom} key={`receiptItem-${i}`} />;
})}
2022-10-24 07:18:22 +00:00
<div>
Receipt Total:
2022-10-24 19:00:16 +00:00
<span style={total < calculated.subtotal ? { color: "red" } : {}}>
<NumberEditBox
valueAtom={totalAtom}
formatter={moneyFormatter.format}
/>
</span>
2022-10-24 07:18:22 +00:00
</div>
2022-11-04 17:05:04 +00:00
<hr />
2022-10-24 07:10:52 +00:00
2022-10-24 19:00:16 +00:00
{calculated.totalMap.size > 0 && (
<>
<h3>Weighted Breakdown</h3>
<div>
<ul>
2022-10-24 19:00:16 +00:00
{[...calculated.totalMap.entries()].map(([person, value], i) => (
<li key={`breakdown-${i}`}>
<b>{person}</b>: {formatter.format(value)}
</li>
))}
</ul>
</div>
</>
)}
2022-10-24 07:10:52 +00:00
</main>
);
};
export default Home;