Some cleaning

This commit is contained in:
Damillora 2021-03-29 16:53:55 +07:00
parent 297a732676
commit 539e531272
8 changed files with 115 additions and 115 deletions

View File

@ -1,47 +1,72 @@
import { faChevronUp } from "@fortawesome/free-solid-svg-icons"; import { faChevronUp } from "@fortawesome/free-solid-svg-icons";
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
import React, { useEffect, useState } from "react"; import React, { useState } from "react";
import { validateForm } from "../lib/product";
import Errors from "./Errors";
export default function ProductForm({ name, price, onNameChange, onPriceChange, onSubmit, busy }) { export default function ProductForm({ name, price, onFormChange, onSubmit, busy }) {
let [form,setForm] = useState({ let [form, setForm] = useState({
name: "", name: "",
value: "", value: "",
}) });
let [formBusy,setFormBusy] = useState(false); let [errors, setErrors] = useState({
let nameChanged = (e: React.ChangeEvent<HTMLInputElement>) => { name: new Array<string>(),
price: new Array<string>(),
});
let nameChanged = (e: React.ChangeEvent<HTMLInputElement>) => {
name = e.target.value; name = e.target.value;
onNameChange(e.target.value); setErrors(validateForm({name,price}));
onFormChange({ name, price });
} }
let priceChanged = (e: React.ChangeEvent<HTMLInputElement>) => { let priceChanged = (e: React.ChangeEvent<HTMLInputElement>) => {
price = e.target.value; price = e.target.value;
onPriceChange(e.target.value); setErrors(validateForm({name,price}));
onFormChange({ name, price });
} }
let submit = (e: React.MouseEvent<HTMLButtonElement>) => { let isValid = (prop) => {
if(errors[prop].length > 0) {
return "form-control is-invalid";
} else {
return "form-control is-valid";
}
}
let submit = (e: React.FormEvent<HTMLFormElement>) => {
e.preventDefault() e.preventDefault()
onSubmit(); let currentErrors = validateForm({ name, price});
if (currentErrors.name.length === 0 && currentErrors.price.length === 0) {
onSubmit();
}
} }
formBusy = busy;
useEffect(() => {
setFormBusy(busy);
},[busy]);
return ( return (
<form> <div>
<fieldset disabled={formBusy}>
<div className="mb-3"> <form onSubmit={submit}>
<label htmlFor="name">Name</label> <fieldset disabled={busy}>
<input className="form-control" id="name" value={name} onChange={nameChanged}></input> <div>
</div> <label htmlFor="name">Name</label>
<div className="mb-3"> <input className={isValid("name")} id="name" value={name} onChange={nameChanged}></input>
<label htmlFor="email">Price</label> </div>
<input type="number" className="form-control" id="price" value={price} onChange={priceChanged}></input> <div className="mb-3">
</div> <Errors errors={errors.name} />
<div className="mb-3"> </div>
<button type="submit" className="btn btn-primary" onClick={submit}>
<FontAwesomeIcon icon={faChevronUp}/> Submit <div>
<label htmlFor="price">Price</label>
<input type="number" className={isValid("price")} id="price" value={price} onChange={priceChanged}></input>
</div>
<div className="mb-3">
<Errors errors={errors.price} />
</div>
<div className="mb-3">
<button type="submit" className="btn btn-primary">
<FontAwesomeIcon icon={faChevronUp} /> Submit
</button> </button>
</div> </div>
</fieldset> </fieldset>
</form> </form>
</div>
); );
} }

View File

@ -13,22 +13,29 @@ export interface ProductListRowsProps {
export interface ProductState { export interface ProductState {
product: ProductListItem[] product: ProductListItem[]
} }
export interface ProductFormEntry {
name: string,
price: number,
}
export interface ProductFormState { export interface ProductFormState {
form: { form: ProductFormEntry,
name: string,
price: number,
},
errors: string[], errors: string[],
busy: boolean, busy: boolean,
} }
export function validateForm(form): string[] { export function validateForm(form: ProductFormEntry) {
let errors: string[] = []; let errors: {name: string[],price: string[]} = {
name: [],
price: [],
};
if (!form.name) { if (!form.name) {
errors.push("Name required"); errors.name.push("Name required");
} }
if (!form.price) { if (!form.price) {
errors.push("Price required"); errors.price.push("Price required");
}
if (form.price < 0) {
errors.price.push("Price must be positive");
} }
return errors; return errors;
} }

View File

@ -18,45 +18,27 @@ function Errors({ errors }) {
function CreateProduct() { function CreateProduct() {
let [form, setForm] = useState({ name: "", price: 0 }); let [form, setForm] = useState({ name: "", price: 0 });
let [busy, setBusy] = useState(false); let [busy, setBusy] = useState(false);
let [errors,setErrors] = useState([""]); let [errors, setErrors] = useState([""]);
const onNameChanged = (newName: string) => { const onFormChanged = (form) => {
setForm( setForm(form);
{
name: newName,
price: form.price,
}
);
}
const onPriceChanged = (newPrice: number) => {
setForm({
name: form.name,
price: newPrice,
});
}
const validate = () => {
let errors: string[] = validateForm(form);
setErrors(errors);
return errors.length == 0;
} }
const onSubmit = async () => { const onSubmit = async () => {
if (validate()) { setBusy(true);
setBusy(true); try {
try { const client = new ProductClient();
const client = new ProductClient(); await client.post({
await client.post({ name: form.name,
name: form.name, price: form.price,
price: form.price, })
}) Swal.fire({
Swal.fire({ title: "Submitted!",
title: "Submitted!", text: "Product is added in database",
text: "Product is added in database", })
}) } catch (error) {
} catch (error) {
} finally { } finally {
setBusy(false); setBusy(false);
}
} }
} }
@ -72,8 +54,7 @@ function CreateProduct() {
name={form.name} name={form.name}
price={form.price} price={form.price}
busy={busy} busy={busy}
onNameChange={onNameChanged} onFormChange={onFormChanged}
onPriceChange={onPriceChanged}
onSubmit={onSubmit} /> onSubmit={onSubmit} />
<ul> <ul>
<Errors errors={errors}></Errors> <Errors errors={errors}></Errors>

View File

@ -45,20 +45,10 @@ function EditProduct({ productID }) {
} }
}, [productID]); }, [productID]);
const onNameChanged = (newName: string) => { const onFormChanged = (form) => {
setForm( setForm(form);
{
name: newName,
price: form.price,
}
);
}
const onPriceChanged = (newPrice: number) => {
setForm({
name: form.name,
price: newPrice,
});
} }
const validate = () => { const validate = () => {
let errors: string[] = validateForm(form); let errors: string[] = validateForm(form);
setErrors(errors); setErrors(errors);
@ -97,8 +87,7 @@ function EditProduct({ productID }) {
name={form.name} name={form.name}
price={form.price} price={form.price}
busy={busy} busy={busy}
onNameChange={onNameChanged} onFormChange={onFormChanged}
onPriceChange={onPriceChanged}
onSubmit={onSubmit} /> onSubmit={onSubmit} />
<ul> <ul>
<Errors errors={errors}></Errors> <Errors errors={errors}></Errors>

View File

@ -55,7 +55,7 @@ const ProductListItemRows: React.FunctionComponent<ProductListRowsProps> = ({ pr
</tbody> </tbody>
) )
} }
class Product extends React.Component<{},ProductState> { class Product extends React.Component<{}, ProductState> {
constructor(props) { constructor(props) {
super(props); super(props);
this.state = { this.state = {
@ -83,11 +83,7 @@ class Product extends React.Component<{},ProductState> {
try { try {
const client = new ProductClient(); const client = new ProductClient();
await client.delete(productId); await client.delete(productId);
// Remove the product in the state by filter()ing it this.getProducts();
let product = this.state.product.filter(x => x.productID != productId);
this.setState({
product
})
Swal.fire({ Swal.fire({
title: "Deleted!", title: "Deleted!",
text: "Product is deleted in database", text: "Product is deleted in database",
@ -100,22 +96,24 @@ class Product extends React.Component<{},ProductState> {
return ( return (
<div className="container px-4 mx-auto"> <div className="container px-4 mx-auto">
<h1>Products</h1> <h1>Products</h1>
<table className="table table-hover table-striped table-sm">
<tr>
<th>ID</th>
<th>Name</th>
<th>Price</th>
<th>Edit</th>
<th>Delete</th>
</tr>
<ProductListItemRows products={this.state.product} onDelete={this.deleteProduct.bind(this)}>
</ProductListItemRows>
</table>
<Link href="/product/create"> <Link href="/product/create">
<a className="btn btn-primary btn-large"> <a className="btn btn-primary btn-large">
Create Create
</a> </a>
</Link> </Link>
<table className="table table-hover table-striped table-sm">
<thead>
<tr>
<th>ID</th>
<th>Name</th>
<th>Price</th>
<th>Edit</th>
<th>Delete</th>
</tr>
</thead>
<ProductListItemRows products={this.state.product} onDelete={this.deleteProduct.bind(this)}>
</ProductListItemRows>
</table>
</div> </div>
); );
} }

View File

@ -65,7 +65,7 @@ namespace TestAppRuna.API
{ {
if(ModelState.IsValid == false) if(ModelState.IsValid == false)
{ {
return BadRequest(); return BadRequest(ModelState);
} }
var customer = new Customer() var customer = new Customer()
{ {

View File

@ -63,9 +63,9 @@ namespace TestAppRuna.API
[HttpPost] [HttpPost]
public async Task<ActionResult<string>> Post([FromBody] ProductCreateUpdateModel model) public async Task<ActionResult<string>> Post([FromBody] ProductCreateUpdateModel model)
{ {
if(ModelState.IsValid == false) if (ModelState.IsValid == false)
{ {
return BadRequest(); return BadRequest(ModelState);
} }
Product product = new Product Product product = new Product
{ {
@ -82,14 +82,14 @@ namespace TestAppRuna.API
[HttpPut("{id}")] [HttpPut("{id}")]
public async Task<ActionResult<string>> Put(Guid id, [FromBody] ProductCreateUpdateModel model) public async Task<ActionResult<string>> Put(Guid id, [FromBody] ProductCreateUpdateModel model)
{ {
if(ModelState.IsValid == false) if (ModelState.IsValid == false)
{ {
return BadRequest(); return BadRequest(ModelState);
} }
var data = await DB.Products var data = await DB.Products
.Where(Q => Q.ProductID == id) .Where(Q => Q.ProductID == id)
.FirstOrDefaultAsync(); .FirstOrDefaultAsync();
if(data == null) if (data == null)
{ {
return NotFound(); return NotFound();
} }
@ -106,7 +106,7 @@ namespace TestAppRuna.API
var data = await DB.Products var data = await DB.Products
.Where(Q => Q.ProductID == id) .Where(Q => Q.ProductID == id)
.FirstOrDefaultAsync(); .FirstOrDefaultAsync();
if(data == null) if (data == null)
{ {
return NotFound(); return NotFound();
} }
@ -128,7 +128,7 @@ namespace TestAppRuna.API
[StringLength(255)] [StringLength(255)]
public string Name { get; set; } public string Name { get; set; }
[Required] [Required]
[Range(double.Epsilon,double.MaxValue)] [Range(double.Epsilon, double.MaxValue)]
public decimal Price { get; set; } public decimal Price { get; set; }
} }
} }

Binary file not shown.