Skip to content

Commit

Permalink
use form and useFormStatus
Browse files Browse the repository at this point in the history
  • Loading branch information
cdleveille committed Jun 9, 2024
1 parent 2f7e1e3 commit b414c5f
Show file tree
Hide file tree
Showing 5 changed files with 87 additions and 46 deletions.
Binary file modified bun.lockb
Binary file not shown.
44 changes: 26 additions & 18 deletions src/components/bag/BagAdd.tsx
Original file line number Diff line number Diff line change
@@ -1,31 +1,23 @@
"use client";

import { useEffect, useRef, useState } from "react";
import { useFormStatus } from "react-dom";
import toast from "react-hot-toast";

import { useAuth } from "@clerk/nextjs";
import { useApi, useKeyPress } from "@hooks";
import { useApi } from "@hooks";
import AddIcon from "@mui/icons-material/Add";
import ClearIcon from "@mui/icons-material/Clear";
import { Button, IconButton, Stack, TextField } from "@mui/material";
import CircularProgress from "@mui/material/CircularProgress";

import type { BagAddProps } from "@types";
import type { BagAddFormProps, BagAddProps } from "@types";

export const BagAdd = ({ onClose }: BagAddProps) => {
const [name, setName] = useState("");

const { isLoading, error, setError, createBag } = useApi();
const { userId } = useAuth();

const inputRef = useRef<HTMLInputElement>(null);

useEffect(() => {
const timeout = setTimeout(() => {
inputRef?.current?.focus?.();
}, 100);
return () => clearTimeout(timeout);
}, []);
const { error, setError, createBag } = useApi();

const onChange = (event: React.ChangeEvent<HTMLInputElement>) => {
setError("");
Expand All @@ -34,18 +26,34 @@ export const BagAdd = ({ onClose }: BagAddProps) => {
setName(name);
};

const disabled = name.length === 0 || isLoading;

const onSubmit = async () => {
if (disabled) return;
if (!userId) return setError("Please sign in to manage bags");
const res = await createBag({ userId, bagName: name });
if (res.error) return;
onClose();
toast.success(`Added ${res.name}`);
};

useKeyPress("Enter", onSubmit);
return (
<form action={onSubmit}>
<BagAddForm name={name} setName={setName} onChange={onChange} error={error} />
</form>
);
};

export const BagAddForm = ({ name, setName, onChange, error }: BagAddFormProps) => {
const { pending } = useFormStatus();

const inputRef = useRef<HTMLInputElement>(null);

useEffect(() => {
const timeout = setTimeout(() => {
inputRef?.current?.focus?.();
}, 100);
return () => clearTimeout(timeout);
}, []);

const disabled = name.length === 0 || pending;

return (
<Stack className="form" justifyContent="center" alignItems="center" spacing="3rem">
Expand Down Expand Up @@ -91,10 +99,10 @@ export const BagAdd = ({ onClose }: BagAddProps) => {
<Button
size="large"
variant="contained"
endIcon={isLoading ? <CircularProgress size="22px" /> : <AddIcon />}
endIcon={pending ? <CircularProgress size="22px" /> : <AddIcon />}
sx={{ fontSize: "1.25rem", padding: "0.5rem 2rem" }}
disabled={disabled}
onClick={onSubmit}
type="submit"
>
Add
</Button>
Expand Down
28 changes: 19 additions & 9 deletions src/components/bag/BagDelete.tsx
Original file line number Diff line number Diff line change
@@ -1,13 +1,15 @@
"use client";

import { useFormStatus } from "react-dom";
import toast from "react-hot-toast";

import { useApi, useKeyPress } from "@hooks";
import { useApi } from "@hooks";
import DeleteIcon from "@mui/icons-material/Delete";
import { Button, CircularProgress, Stack } from "@mui/material";

import type { BagDeleteProps } from "@types";

import type { BagDeleteProps, BagDeleteFormProps } from "@types";
export const BagDelete = ({ bag, onClose }: BagDeleteProps) => {
const { isLoading, error, deleteBag } = useApi();
const { error, deleteBag } = useApi();

const onSubmit = async () => {
const res = await deleteBag({ bagId: bag.id });
Expand All @@ -16,14 +18,22 @@ export const BagDelete = ({ bag, onClose }: BagDeleteProps) => {
toast.success(`Deleted ${bag.name}`);
};

useKeyPress("Enter", onSubmit);
return (
<form action={onSubmit}>
<BagDeleteForm name={bag.name} error={error} />
</form>
);
};

const BagDeleteForm = ({ name, error }: BagDeleteFormProps) => {
const { pending } = useFormStatus();

return (
<Stack className="form" justifyContent="center" alignItems="center" spacing="3rem">
<div className="form-title">Delete Bag</div>
<Stack spacing="0.5rem" alignItems="center">
<div style={{ fontSize: "1.25rem", fontWeight: 500, color: "#757575" }}>
Are you sure you want to delete {bag.name}?
Are you sure you want to delete {name}?
</div>
<div className="error" style={{ height: "1.25rem" }}>
{error}
Expand All @@ -32,11 +42,11 @@ export const BagDelete = ({ bag, onClose }: BagDeleteProps) => {
<Button
size="large"
variant="contained"
endIcon={isLoading ? <CircularProgress size="22px" /> : <DeleteIcon />}
endIcon={pending ? <CircularProgress size="22px" /> : <DeleteIcon />}
sx={{ fontSize: "1.25rem", padding: "0.5rem 2rem" }}
color="error"
onClick={onSubmit}
disabled={isLoading}
disabled={pending}
type="submit"
>
Delete
</Button>
Expand Down
46 changes: 27 additions & 19 deletions src/components/bag/BagEdit.tsx
Original file line number Diff line number Diff line change
@@ -1,30 +1,23 @@
"use client";

import { useEffect, useRef, useState } from "react";
import { useFormStatus } from "react-dom";
import toast from "react-hot-toast";

import { useAuth } from "@clerk/nextjs";
import { useApi, useKeyPress } from "@hooks";
import { useApi } from "@hooks";
import ClearIcon from "@mui/icons-material/Clear";
import SaveIcon from "@mui/icons-material/Save";
import { Button, CircularProgress, IconButton, Stack, TextField } from "@mui/material";
import { Button, IconButton, Stack, TextField } from "@mui/material";
import CircularProgress from "@mui/material/CircularProgress";

import type { BagEditProps } from "@types";
import type { BagEditFormProps, BagEditProps } from "@types";

export const BagEdit = ({ bag, onClose }: BagEditProps) => {
const [name, setName] = useState(bag.name);

const { isLoading, error, setError, editBagName } = useApi();
const { userId } = useAuth();

const inputRef = useRef<HTMLInputElement>(null);

useEffect(() => {
const timeout = setTimeout(() => {
inputRef?.current?.focus?.();
}, 100);
return () => clearTimeout(timeout);
}, []);
const { error, setError, editBagName } = useApi();

const onChange = (event: React.ChangeEvent<HTMLInputElement>) => {
setError("");
Expand All @@ -33,18 +26,34 @@ export const BagEdit = ({ bag, onClose }: BagEditProps) => {
setName(name);
};

const disabled = name.length === 0 || name === bag.name || isLoading;

const onSubmit = async () => {
if (disabled) return;
if (!userId) return setError("Please sign in to manage bags");
const res = await editBagName({ bagId: bag.id, bagName: name });
if (res.error) return;
onClose();
toast.success(`Renamed to ${res.name}`);
};

useKeyPress("Enter", onSubmit);
return (
<form action={onSubmit}>
<BagEditForm name={name} setName={setName} onChange={onChange} error={error} initialBagName={bag.name} />
</form>
);
};

export const BagEditForm = ({ name, setName, onChange, error, initialBagName }: BagEditFormProps) => {
const { pending } = useFormStatus();

const inputRef = useRef<HTMLInputElement>(null);

useEffect(() => {
const timeout = setTimeout(() => {
inputRef?.current?.focus?.();
}, 100);
return () => clearTimeout(timeout);
}, []);

const disabled = name.length === 0 || name === initialBagName || pending;

return (
<Stack className="form" justifyContent="center" alignItems="center" spacing="3rem">
Expand Down Expand Up @@ -90,11 +99,10 @@ export const BagEdit = ({ bag, onClose }: BagEditProps) => {
<Button
size="large"
variant="contained"
endIcon={isLoading ? <CircularProgress size="22px" /> : <SaveIcon />}
endIcon={pending ? <CircularProgress size="22px" /> : <SaveIcon />}
sx={{ fontSize: "1.25rem", padding: "0.5rem 2rem" }}
disabled={disabled}
type="submit"
onClick={onSubmit}
>
Save
</Button>
Expand Down
15 changes: 15 additions & 0 deletions src/types/props.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import type { Bag, Disc, ViewOption } from "@types";
import type { Dispatch, SetStateAction } from "react";

export type AppContextProviderProps = {
children: React.ReactNode;
Expand Down Expand Up @@ -36,6 +37,20 @@ export type BagEditProps = {
onClose: () => void;
};

export type BagAddFormProps = {
name: string;
setName: Dispatch<SetStateAction<string>>;
onChange: (event: React.ChangeEvent<HTMLInputElement>) => void;
error: string | null;
};

export type BagEditFormProps = BagAddFormProps & { initialBagName: string };

export type BagDeleteFormProps = {
name: string;
error: string | null;
};

export type BagDeleteProps = {
bag: Bag;
onClose: () => void;
Expand Down

0 comments on commit b414c5f

Please sign in to comment.