Skip to content

Commit

Permalink
Reintroduce ability to add children to listings (#216)
Browse files Browse the repository at this point in the history
* Remove unnecessary layer of indirection

* Re-introduce ability to add children to listings
  • Loading branch information
chennisden authored Jul 31, 2024
1 parent e027be0 commit 0ecd9ed
Showing 1 changed file with 124 additions and 64 deletions.
188 changes: 124 additions & 64 deletions frontend/src/pages/NewListing.tsx
Original file line number Diff line number Diff line change
@@ -1,73 +1,62 @@
import TCButton from "components/files/TCButton";
import { paths } from "gen/api";
import { useAlertQueue } from "hooks/alerts";
import { useAuthentication } from "hooks/auth";
import { Dispatch, FormEvent, SetStateAction, useState } from "react";
import { Col, Form } from "react-bootstrap";
import { useTheme } from "hooks/theme";
import { ChangeEvent, FormEvent, useEffect, useState } from "react";
import { Col, Form, Row } from "react-bootstrap";
import { useNavigate } from "react-router-dom";

interface ListingFormProps {
title: string;
name: string;
setName: Dispatch<SetStateAction<string>>;
description: string;
setDescription: Dispatch<SetStateAction<string>>;
handleSubmit: (event: FormEvent<HTMLFormElement>) => void;
}

const ListingForm = (props: ListingFormProps) => {
const { title, name, setName, description, setDescription, handleSubmit } =
props;

return (
<>
<h1>{title}</h1>
<Form onSubmit={handleSubmit} className="mb-3">
{/* Name */}
<Col md={12} className="mb-4">
<label htmlFor="name">Name</label>
<Form.Control
id="name"
className="mt-2"
type="text"
onChange={(e) => {
setName(e.target.value);
}}
value={name}
required
/>
</Col>

{/* Description */}
<Col md={12} className="mb-4">
<label htmlFor="desc">Description</label>
<Form.Control
id="desc"
className="mt-2"
as="textarea"
onChange={(e) => {
setDescription(e.target.value);
}}
value={description}
/>
</Col>

{/* Submit */}
<Col md={12} className="mb-4">
<TCButton type="submit">Submit</TCButton>
</Col>
</Form>
</>
);
};
type ListingDumpResponse =
paths["/listings/dump"]["get"]["responses"][200]["content"]["application/json"];

const NewListing = () => {
const auth = useAuthentication();
const [name, setName] = useState<string>("");
const [description, setDescription] = useState<string>("");
const [listings, setListings] = useState<ListingDumpResponse | null>(null);
const [children, setChildren] = useState<string[]>([]); // Store the ids of each child

const { addAlert, addErrorAlert } = useAlertQueue();
const { theme } = useTheme();
const navigate = useNavigate();

const handleChildrenChange = (
index: number,
e: ChangeEvent<HTMLInputElement | HTMLTextAreaElement>,
) => {
const { value } = e.target;
const newChildren = [...children];
newChildren[index] = value;
setChildren(newChildren);
};

const handleAddChild = () => {
setChildren([...children, ""]);
};

const handleRemoveChild = (index: number) => {
const newChildren = children.filter((_, i) => i !== index);
setChildren(newChildren);
};

// Fetch all listings to use for children.
useEffect(() => {
const fetchListings = async () => {
try {
const { data, error } = await auth.client.GET("/listings/dump");
if (error) {
addErrorAlert(error);
} else {
setListings(data);
}
} catch (err) {
addErrorAlert(err);
}
};
fetchListings();
}, []);

// On submit, add the listing to the database and navigate to the
// newly-created listing.
const handleSubmit = async (event: FormEvent<HTMLFormElement>) => {
Expand All @@ -90,14 +79,85 @@ const NewListing = () => {
};

return (
<ListingForm
title="Create Listing"
name={name}
setName={setName}
description={description}
setDescription={setDescription}
handleSubmit={handleSubmit}
/>
<>
<h1 className="display-6">Create Listing</h1>
<Form onSubmit={handleSubmit} className="mb-3">
{/* Name */}
<label htmlFor="name">Name</label>
<Form.Control
id="name"
className="mt-2"
type="text"
onChange={(e) => {
setName(e.target.value);
}}
value={name}
required
/>

{/* Description */}
<label htmlFor="desc">Description</label>
<Form.Control
id="desc"
className="mt-2"
as="textarea"
onChange={(e) => {
setDescription(e.target.value);
}}
value={description}
/>

<p>Children</p>
{children.map((id, index) => (
<Row key={index} className="mb-3">
<Col>
<label htmlFor={"child-" + index}>Listing</label>
<Form.Control
id={"child-" + index}
className="mb-1"
as="select"
name="child_id"
value={id}
onChange={(e) => handleChildrenChange(index, e)}
required
>
<option value="" disabled>
Select a Listing
</option>
{listings &&
listings.listings.map((listing, index) => (
<option key={index} value={listing.id}>
{listing.name} ({listing.id})
</option>
))}
</Form.Control>
</Col>
<Col md={12}>
<TCButton
className="mb-2 mt-2"
variant="danger"
onClick={() => handleRemoveChild(index)}
>
Remove
</TCButton>
</Col>
</Row>
))}

<TCButton
className="mb-3"
variant={theme === "dark" ? "outline-light" : "outline-dark"}
onClick={handleAddChild}
>
Add Child
</TCButton>

{/* Submit */}
<Col md={12} className="mb-4">
<TCButton type="submit">Submit</TCButton>
</Col>
</Form>
</>
);
};

Expand Down

0 comments on commit 0ecd9ed

Please sign in to comment.