This commit is contained in:
Michael Zhang 2022-10-24 13:27:34 -05:00
parent 0d30b03b93
commit 90924073ed
6 changed files with 102 additions and 74 deletions

View file

@ -1,6 +1,5 @@
import { Atom, useAtom } from "jotai";
import { useState } from "react";
import { Form } from "react-bootstrap";
import styled from "styled-components";
export interface Props {

View file

@ -12,6 +12,25 @@ export default function Layout({ children }) {
<Container>
<main>{children}</main>
</Container>
<footer style={{ textAlign: "center" }}>
<small>
<a href="https://github.com/iptq/wisesplit/" target="_blank">
[source]
</a>
&middot;
<a href="https://www.gnu.org/licenses/agpl-3.0.txt" target="_blank">
[license]
</a>
&middot;
<a href="https://github.com/iptq/wisesplit/stargazers">
<img
alt="GitHub stars"
src="https://img.shields.io/github/stars/iptq/wisesplit?style=social"
/>
</a>
</small>
</footer>
</>
);
}

View file

@ -1,4 +1,4 @@
import { Atom, useAtom } from "jotai";
import { Atom, useAtom, WritableAtom } from "jotai";
import { Badge, ListGroup } from "react-bootstrap";
export interface IPerson {
@ -7,6 +7,7 @@ export interface IPerson {
export interface Props {
personAtom: Atom<IPerson>;
splitBetweenAtom: WritableAtom<Atom<IPerson>[]>;
}
export default function Person({ personAtom, splitBetweenAtom }: Props) {

View file

@ -1,9 +1,9 @@
import { atom, Atom, useAtom, useAtomValue } from "jotai";
import { useState } from "react";
import { Badge, Card, ListGroup } from "react-bootstrap";
import { Atom, useAtom } from "jotai";
import { Badge, Card } from "react-bootstrap";
import { receiptAtom } from "../lib/state";
import EditBox from "./EditBox";
import Person, { IPerson } from "./Person";
import { IPerson } from "./Person";
import SplitBetween from "./SplitBetween";
export interface IReceiptItem {
name: string;
@ -11,61 +11,14 @@ export interface IReceiptItem {
splitBetween: Atom<Atom<IPerson>[]>;
}
export interface Props {
itemAtom: Atom<IReceiptItem>;
}
function SplitBetween({ splitBetweenAtom }) {
const [splitBetween, setSplitBetween] = useAtom(splitBetweenAtom);
const [input, setInput] = useState("");
const [editing, setEditing] = useState(false);
const startEditing = (_) => {
setInput("");
setEditing(true);
};
const addPerson = (e) => {
e.preventDefault();
setSplitBetween([...splitBetween, atom({ name: input })]);
setEditing(false);
};
return (
<div>
Split between ({splitBetween.length}):
<ListGroup horizontal>
{splitBetween.map((a, i) => (
<Person
personAtom={a}
key={`split-${i}`}
splitBetweenAtom={splitBetweenAtom}
/>
))}
<ListGroup.Item onClick={startEditing}>
{editing ? (
<form onSubmit={addPerson}>
<input
autoFocus={true}
type="text"
value={input}
onBlur={(_) => setEditing(false)}
onInput={(e) => setInput(e.target.value)}
/>
</form>
) : (
"[+]"
)}
</ListGroup.Item>
</ListGroup>
</div>
);
}
function Price({ priceAtom }) {
return <EditBox valueAtom={priceAtom} />;
}
export interface Props {
itemAtom: Atom<IReceiptItem>;
}
export default function ReceiptItem({ itemAtom }: Props) {
const [receipt, setReceipt] = useAtom(receiptAtom);
const [item, _] = useAtom(itemAtom);
@ -76,17 +29,24 @@ export default function ReceiptItem({ itemAtom }: Props) {
return (
<Card>
<Card.Header>
<Card.Title className="d-flex justify-content-between align-items-center">
<h3>{item.name}</h3>
<span>
<Price priceAtom={item.price} />
<Badge
bg="danger"
pill
onClick={removeSelf}
style={{ cursor: "pointer" }}
>
&times;
</Badge>
</span>
</Card.Title>
</Card.Header>
<Card.Body>
<Card.Title>{item.name}</Card.Title>
Item price: <Price priceAtom={item.price} />
<Badge
bg="danger"
pill
onClick={removeSelf}
style={{ cursor: "pointer" }}
>
&times;
</Badge>
<SplitBetween splitBetweenAtom={item.splitBetween} />
</Card.Body>
</Card>

View file

@ -0,0 +1,55 @@
import { atom, Atom, useAtom } from "jotai";
import { useState } from "react";
import { ListGroup } from "react-bootstrap";
import Person, { IPerson } from "./Person";
export interface Props {
splitBetweenAtom: Atom<Atom<IPerson>[]>;
}
export default function SplitBetween({ splitBetweenAtom }: Props) {
const [splitBetween, setSplitBetween] = useAtom(splitBetweenAtom);
const [input, setInput] = useState("");
const [editing, setEditing] = useState(false);
const startEditing = (_) => {
setInput("");
setEditing(true);
};
const addPerson = (e) => {
e.preventDefault();
setSplitBetween([...splitBetween, atom({ name: input })]);
setEditing(false);
};
return (
<div>
Split between ({splitBetween.length}):
<ListGroup horizontal>
{splitBetween.map((a, i) => (
<Person
personAtom={a}
key={`split-${i}`}
splitBetweenAtom={splitBetweenAtom}
/>
))}
<ListGroup.Item onClick={startEditing}>
{editing ? (
<form onSubmit={addPerson}>
<input
autoFocus={true}
type="text"
value={input}
onBlur={(_) => setEditing(false)}
onInput={(e) => setInput(e.target.value)}
/>
</form>
) : (
"[+]"
)}
</ListGroup.Item>
</ListGroup>
</div>
);
}

View file

@ -42,7 +42,7 @@ const Home: NextPage = () => {
placeholder="Add item..."
onInput={(e) => setInput(e.target.value)}
value={input}
style={{ padding: "8px", fontSize: "1.5em" }}
style={{ padding: "8px 16px", fontSize: "1.5em" }}
/>
</Form>
@ -70,12 +70,6 @@ const Home: NextPage = () => {
</div>
</>
)}
<small>
<a href="https://github.com/iptq/wisesplit/">[source]</a>
&middot;
<a href="https://www.gnu.org/licenses/agpl-3.0.txt">[license]</a>
</small>
</main>
);
};