Fix typescript errors

This commit is contained in:
Michael Zhang 2022-10-25 13:26:48 -05:00
parent c9750fdc5f
commit 4be8903816
Signed by: michael
GPG key ID: BDA47A31A3C8EE6B
11 changed files with 77 additions and 72 deletions

View file

@ -1,13 +1,9 @@
import { Atom, useAtom } from "jotai";
import { useState } from "react";
import { PrimitiveAtom, useAtom } from "jotai";
import { SyntheticEvent, useState } from "react";
import styled from "styled-components";
export interface CanBeConvertedToString {
toString(): string;
}
export interface Props<T extends CanBeConvertedToString> {
valueAtom: Atom<T>;
export interface Props<T> {
valueAtom: PrimitiveAtom<T>;
formatter?: (arg: T) => string;
inputType?: string;
validator: (arg: string) => T | null;
@ -33,7 +29,7 @@ const EditingBox = styled.input`
border-radius: 5px;
`;
export default function EditBox<T extends CanBeConvertedToString>({
export default function EditBox<T>({
valueAtom,
formatter,
inputType,
@ -44,11 +40,11 @@ export default function EditBox<T extends CanBeConvertedToString>({
const [editing, setEditing] = useState(false);
const startEditing = (_: any) => {
setValueInput(value.toString());
setValueInput(String(value));
setEditing(true);
};
const finalize = (e: Event) => {
const finalize = (e: SyntheticEvent) => {
e.preventDefault();
const validateResult = validator(valueInput);
if (validateResult !== null) {
@ -66,14 +62,14 @@ export default function EditBox<T extends CanBeConvertedToString>({
step="0.01"
value={valueInput}
onBlur={finalize}
onInput={(e) => setValueInput(e.target.value)}
onInput={(e) => setValueInput(e.currentTarget.value)}
/>
</form>
);
} else {
return (
<ClickableContainer onClick={startEditing}>
{formatter ? formatter(value) : value.toString()}
{formatter ? formatter(value) : String(value)}
</ClickableContainer>
);
}

View file

@ -1,6 +1,10 @@
import { Container, Navbar } from "react-bootstrap";
export default function Layout({ children }) {
export interface Props {
children: JSX.Element;
}
export default function Layout({ children }: Props) {
return (
<>
<Navbar bg="dark" variant="dark" expand="lg">
@ -31,6 +35,8 @@ export default function Layout({ children }) {
[license]
</a>
&middot;
{/* eslint-disable @next/next/no-img-element */}
<a href="https://github.com/iptq/wisesplit/stargazers">
<img
alt="GitHub stars"

View file

@ -1,16 +1,16 @@
import { Atom } from "jotai";
import { PrimitiveAtom } from "jotai";
import EditBox from "./EditBox";
export interface Props {
valueAtom: Atom<number>;
valueAtom: PrimitiveAtom<number>;
formatter?: (arg: number) => string;
}
export default function NumberEditBox({ valueAtom, formatter }: Props) {
const validator = (arg: string) => {
const validator = (arg: string): number | null => {
try {
const n = parseFloat(arg);
if (isNaN(n) || !isFinite(n)) return;
if (isNaN(n) || !isFinite(n)) return null;
return n;
} catch (e) {
return null;

View file

@ -1,21 +1,21 @@
import { Atom, useAtom, WritableAtom } from "jotai";
import { Badge, ListGroup } from "react-bootstrap";
import { PrimitiveAtom, useAtom } from "jotai";
import { Badge } from "react-bootstrap";
import EditBox from "./EditBox";
export interface IPerson {
name: Atom<string>;
name: PrimitiveAtom<string>;
}
export interface Props {
personAtom: Atom<IPerson>;
splitBetweenAtom: Atom<Atom<IPerson>[]>;
personAtom: PrimitiveAtom<IPerson>;
splitBetweenAtom: PrimitiveAtom<PrimitiveAtom<IPerson>[]>;
}
export default function Person({ personAtom, splitBetweenAtom }: Props) {
const [person] = useAtom(personAtom);
const [splitBetween, setSplitBetween] = useAtom(splitBetweenAtom);
const removeSelf = (_) => {
const removeSelf = (_: any) => {
setSplitBetween([...splitBetween.filter((x) => x != personAtom)]);
};

View file

@ -1,4 +1,4 @@
import { Atom, useAtom } from "jotai";
import { PrimitiveAtom, useAtom } from "jotai";
import { Badge, Card } from "react-bootstrap";
import { moneyFormatter } from "../lib/formatter";
import { receiptAtom } from "../lib/state";
@ -7,27 +7,23 @@ import NumberEditBox from "./NumberEditBox";
import { IPerson } from "./Person";
import SplitBetween from "./SplitBetween";
export interface IReceiptItem {
name: Atom<string>;
price: Atom<number>;
splitBetween: Atom<Atom<IPerson>[]>;
}
export type Receipt = PrimitiveAtom<IReceiptItem>[];
function Price({ priceAtom }) {
return (
<NumberEditBox valueAtom={priceAtom} formatter={moneyFormatter.format} />
);
export interface IReceiptItem {
name: PrimitiveAtom<string>;
price: PrimitiveAtom<number>;
splitBetween: PrimitiveAtom<PrimitiveAtom<IPerson>[]>;
}
export interface Props {
itemAtom: Atom<IReceiptItem>;
itemAtom: PrimitiveAtom<IReceiptItem>;
}
export default function ReceiptItem({ itemAtom }: Props) {
const [receipt, setReceipt] = useAtom(receiptAtom);
const [item, _] = useAtom(itemAtom);
const removeSelf = (_) => {
const removeSelf = (_: any) => {
setReceipt([...receipt.filter((x) => x != itemAtom)]);
};
@ -39,7 +35,10 @@ export default function ReceiptItem({ itemAtom }: Props) {
<EditBox valueAtom={item.name} validator={(s) => s} />
</h3>
<span>
<Price priceAtom={item.price} />
<NumberEditBox
valueAtom={item.price}
formatter={moneyFormatter.format}
/>
<Badge
bg="danger"
pill

View file

@ -1,10 +1,10 @@
import { atom, Atom, useAtom } from "jotai";
import { useState } from "react";
import { Button, Form, ListGroup } from "react-bootstrap";
import { atom, PrimitiveAtom, useAtom } from "jotai";
import { SyntheticEvent, useState } from "react";
import { Button, Form } from "react-bootstrap";
import Person, { IPerson } from "./Person";
export interface Props {
splitBetweenAtom: Atom<Atom<IPerson>[]>;
splitBetweenAtom: PrimitiveAtom<PrimitiveAtom<IPerson>[]>;
}
export default function SplitBetween({ splitBetweenAtom }: Props) {
@ -12,14 +12,14 @@ export default function SplitBetween({ splitBetweenAtom }: Props) {
const [input, setInput] = useState("");
const [editing, setEditing] = useState(false);
const startEditing = (_) => {
const startEditing = (_: any) => {
setInput("");
setEditing(true);
};
const addPerson = (e) => {
const addPerson = (e: SyntheticEvent) => {
e.preventDefault();
const person = { name: atom(input) };
const person: IPerson = { name: atom(input) };
setSplitBetween([...splitBetween, atom(person)]);
setEditing(false);
};
@ -43,7 +43,7 @@ export default function SplitBetween({ splitBetweenAtom }: Props) {
value={input}
placeholder="Add person to split with..."
onBlur={(_) => setEditing(false)}
onInput={(e) => setInput(e.target.value)}
onInput={(e) => setInput(e.currentTarget.value)}
/>
</Form>
) : (

View file

@ -4,7 +4,11 @@ export interface ParsedInput {
splitBetween: Set<string>;
}
export function ParsedInputDisplay({ input }) {
export interface Props {
input: string;
}
export function ParsedInputDisplay({ input }: Props) {
const parsed = parseInput(input);
const formatter = new Intl.NumberFormat("en-US", {

View file

@ -1,5 +1,7 @@
import { atom, PrimitiveAtom } from "jotai";
import { IReceiptItem } from "../components/ReceiptItem";
import { SetAtom } from "jotai/core/atom";
import { IPerson } from "../components/Person";
import { IReceiptItem, Receipt } from "../components/ReceiptItem";
import parseInput from "./parseInput";
export const totalAtom = atom(0);
@ -39,16 +41,23 @@ export const receiptTotalAtom = atom((get) => {
return { subtotal: subtotalSum, totalMap: newTotals };
});
export function addLine(line: string, setReceipt) {
export function addLine(
line: string,
receipt: Receipt,
setReceipt: SetAtom<Receipt, void>
) {
let parsed = parseInput(line);
console.log(parsed);
const name = atom(parsed.itemName);
const price = atom(parsed.price || 0);
const splitBetween = atom(
[...parsed.splitBetween].map((a) => atom({ name: a }))
);
setReceipt((prev) => [
...prev,
atom<IReceiptItem>({ name, price, splitBetween }),
]);
const name: PrimitiveAtom<string> = atom(parsed.itemName);
const price: PrimitiveAtom<number> = atom(parsed.price || 0);
const splitBetween: PrimitiveAtom<PrimitiveAtom<IPerson>[]> = atom<
PrimitiveAtom<IPerson>[]
>([...parsed.splitBetween].map((a) => atom<IPerson>({ name: atom(a) })));
const newReceiptItem = atom({
name,
price,
splitBetween,
});
setReceipt([...receipt, newReceiptItem]);
}

View file

@ -7,10 +7,7 @@ const nextConfig = {
styledComponents: true,
},
typescript: {
// TODO: Move fast and break things lmao
ignoreBuildErrors: true,
},
typescript: {},
};
module.exports = nextConfig;

View file

@ -1,6 +1,6 @@
import { useAtom } from "jotai";
import type { NextPage } from "next";
import { useState } from "react";
import { SyntheticEvent, useState } from "react";
import { Form } from "react-bootstrap";
import NumberEditBox from "../components/NumberEditBox";
import ReceiptItem from "../components/ReceiptItem";
@ -24,9 +24,9 @@ const Home: NextPage = () => {
currency: "USD",
});
const add = (e) => {
const add = (e: SyntheticEvent) => {
e.preventDefault();
addLine(input, setReceipt);
addLine(input, receipt, setReceipt);
setInput("");
return false;
};
@ -42,7 +42,7 @@ const Home: NextPage = () => {
autoFocus={true}
type="text"
placeholder="Add item..."
onInput={(e) => setInput(e.target.value)}
onInput={(e) => setInput(e.currentTarget.value)}
value={input}
style={{ padding: "8px 16px", fontSize: "1.5em" }}
/>

View file

@ -1,6 +0,0 @@
import solid from "solid-start/vite";
import { defineConfig } from "vite";
export default defineConfig({
plugins: [solid()],
});