diff --git a/Next/interfaces/product.ts b/Next/lib/product.ts
similarity index 68%
rename from Next/interfaces/product.ts
rename to Next/lib/product.ts
index 2c1cdd6..934a5ff 100644
--- a/Next/interfaces/product.ts
+++ b/Next/lib/product.ts
@@ -20,4 +20,15 @@ export interface ProductFormState {
},
errors: string[],
busy: boolean,
+}
+
+export function validateForm(form): string[] {
+ let errors: string[] = [];
+ if (!form.name) {
+ errors.push("Name required");
+ }
+ if (!form.price) {
+ errors.push("Price required");
+ }
+ return errors;
}
\ No newline at end of file
diff --git a/Next/pages/product/create.tsx b/Next/pages/product/create.tsx
index df586cd..c09f22c 100644
--- a/Next/pages/product/create.tsx
+++ b/Next/pages/product/create.tsx
@@ -1,66 +1,48 @@
-import React, { ChangeEvent } from 'react';
+import React, { useEffect, useState } from 'react';
+import { useRouter } from 'next/router';
import { Layout } from '../shared/Layout';
import { ProductClient } from '../../APIClient';
import Swal from 'sweetalert2';
import ProductForm from '../../components/ProductForm';
-import Errors from '../../components/Errors';
import Link from 'next/link';
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
import { faArrowLeft } from '@fortawesome/free-solid-svg-icons';
-import { ProductFormState } from '../../interfaces/product';
+import { validateForm } from '../../lib/product';
-class CreateProduct extends React.Component<{}, ProductFormState> {
- constructor(props) {
- super(props)
- this.state = {
- form: {
- name: "",
- price: 0,
- },
- errors: [],
- busy: false,
- }
- }
- onNameChanged(newName) {
- this.setState({
- form: {
+function Errors({ errors }) {
+ return errors.map(x => (
+
{x}
+ ));
+}
+
+function CreateProduct() {
+ let [form, setForm] = useState({ name: "", price: 0 });
+ let [busy, setBusy] = useState(false);
+ let [errors,setErrors] = useState([""]);
+
+ const onNameChanged = (newName: string) => {
+ setForm(
+ {
name: newName,
- price: this.state.form.price,
+ price: form.price,
}
+ );
+ }
+ const onPriceChanged = (newPrice: number) => {
+ setForm({
+ name: form.name,
+ price: newPrice,
});
}
- onPriceChanged(newPrice) {
- this.setState({
- form: {
- name: this.state.form.name,
- price: newPrice
- }
- });
- }
- async validate() {
- let errors: string[] = [];
- if (!this.state.form.name) {
- errors.push("Name required");
- }
- if (!this.state.form.price) {
- errors.push("Price required");
- }
- await new Promise((resolve) => {
- this.setState({
- errors
- }, () => resolve(undefined));
- })
+ const validate = () => {
+ let errors: string[] = validateForm(form);
+ setErrors(errors);
return errors.length == 0;
}
- async onSubmit() {
- if (await this.validate()) {
- await new Promise((resolve) => {
- this.setState({
- busy: true,
- }, () => resolve(undefined));
- })
+ const onSubmit = async () => {
+ if (validate()) {
+ setBusy(true);
try {
- const form = this.state.form;
const client = new ProductClient();
await client.post({
name: form.name,
@@ -68,44 +50,37 @@ class CreateProduct extends React.Component<{}, ProductFormState> {
})
Swal.fire({
title: "Submitted!",
- text: "Product is now in database",
+ text: "Product is added in database",
})
} catch (error) {
} finally {
- await new Promise((resolve) => {
- this.setState({
- busy: false,
- }, () => resolve(undefined));
- })
-
+ setBusy(false);
}
}
}
- render() {
- return (
-
- )
- }
-}
+ return (
+
+ );
+}
export default function CreateProductPage() {
return (
diff --git a/Next/pages/product/edit/[id].tsx b/Next/pages/product/edit/[id].tsx
index 6dac913..3c21ebe 100644
--- a/Next/pages/product/edit/[id].tsx
+++ b/Next/pages/product/edit/[id].tsx
@@ -1,5 +1,5 @@
-import React, { ChangeEvent } from 'react';
-import { withRouter, NextRouter, useRouter } from 'next/router';
+import React, { useEffect, useState } from 'react';
+import { useRouter } from 'next/router';
import { Layout } from '../../shared/Layout';
import { ProductClient } from '../../../APIClient';
import Swal from 'sweetalert2';
@@ -7,90 +7,69 @@ import ProductForm from '../../../components/ProductForm';
import Link from 'next/link';
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
import { faArrowLeft } from '@fortawesome/free-solid-svg-icons';
-import { ProductDataProps, ProductFormState } from '../../../interfaces/product';
+import { validateForm } from '../../../lib/product';
function Errors({ errors }) {
return errors.map(x => (
{x}
));
}
-class EditProduct extends React.Component {
- constructor(props) {
- super(props)
- const id = props.productID;
- this.state = {
- form: {
- name: "",
- price: 0,
- },
- errors: [],
- busy: false,
- }
+
+function EditProduct({ productID }) {
+ if (typeof productID != "string") {
+ return (
+
+
+ )
}
- async componentDidMount() {
+ let [form, setForm] = useState({ name: "", price: 0 });
+ let [busy, setBusy] = useState(false);
+ let [errors,setErrors] = useState([""]);
+
+ const getInitialData = async() => {
const client = new ProductClient();
- await new Promise((resolve) => {
- this.setState({
- busy: true,
- }, () => resolve(undefined));
- })
- if (this.props.productID) {
- let data = await client.get(this.props.productID);
- await new Promise((resolve) => {
- this.setState({
- busy: false,
- }, () => resolve(undefined));
- })
- this.setState({
- form: {
- name: data.name,
- price: data.price,
- }
- });
- }
+ let data = await client.get(productID);
+ setBusy(false);
+ setForm(
+ {
+ name: data.name,
+ price: data.price,
+ }
+ );
}
- onNameChanged(newName: string) {
- this.setState({
- form: {
+ // Startup
+ useEffect(() => {
+ setBusy(true);
+ if (productID) {
+ getInitialData();
+ }
+ }, [productID]);
+
+ const onNameChanged = (newName: string) => {
+ setForm(
+ {
name: newName,
- price: this.state.form.price,
+ price: form.price,
}
+ );
+ }
+ const onPriceChanged = (newPrice: number) => {
+ setForm({
+ name: form.name,
+ price: newPrice,
});
}
- onPriceChanged(newPrice: number) {
- this.setState({
- form: {
- name: this.state.form.name,
- price: newPrice,
- }
- });
- }
- async validate() {
- let errors: string[] = [];
- if (!this.state.form.name) {
- errors.push("Name required");
- }
- if (!this.state.form.price) {
- errors.push("Email required");
- }
- await new Promise((resolve) => {
- this.setState({
- errors
- }, () => resolve(undefined));
- })
+ const validate = () => {
+ let errors: string[] = validateForm(form);
+ setErrors(errors);
return errors.length == 0;
}
- async onSubmit() {
- if (await this.validate()) {
- await new Promise((resolve) => {
- this.setState({
- busy: true,
- }, () => resolve(undefined));
- })
+ const onSubmit = async () => {
+ if (validate()) {
+ setBusy(true);
try {
- const form = this.state.form;
const client = new ProductClient();
- await client.put(this.props.productID, {
+ await client.put(productID, {
name: form.name,
price: form.price,
})
@@ -101,43 +80,31 @@ class EditProduct extends React.Component {
} catch (error) {
} finally {
- await new Promise((resolve) => {
- this.setState({
- busy: false,
- }, () => resolve(undefined));
- })
-
+ setBusy(false);
}
}
}
- render() {
- if (typeof this.props.productID != "string") {
- return (
-
-
- )
- }
- return (
-
+ );
}
export default function EditProductPage() {
diff --git a/Next/pages/product/index.tsx b/Next/pages/product/index.tsx
index 1cbbdaa..6d7f239 100644
--- a/Next/pages/product/index.tsx
+++ b/Next/pages/product/index.tsx
@@ -7,7 +7,7 @@ import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
import { faEdit, faTrash } from '@fortawesome/free-solid-svg-icons';
import { useRouter } from 'next/router';
import Link from 'next/link';
-import { DeleteProductProps, ProductDataProps, ProductListRowsProps, ProductState } from '../../interfaces/product';
+import { DeleteProductProps, ProductDataProps, ProductListRowsProps, ProductState } from '../../lib/product';
const DeleteProductButton: React.FunctionComponent = ({ productID, onDelete }) => {
const onClickDelete = async () => {
diff --git a/Next/pages/shared/Layout.tsx b/Next/pages/shared/Layout.tsx
index 6d1a3d5..ca24974 100644
--- a/Next/pages/shared/Layout.tsx
+++ b/Next/pages/shared/Layout.tsx
@@ -18,7 +18,7 @@ const NavLink: React.FunctionComponent<{href: string}> = ({href, children}) => {
if(active) {
return "page";
} else {
- return null;
+ return undefined;
}
}
const active = router.pathname == href;
@@ -26,7 +26,7 @@ const NavLink: React.FunctionComponent<{href: string}> = ({href, children}) => {
return (
- {children}
+ {children}
);
@@ -53,6 +53,8 @@ const NavBar: React.FunctionComponent<{}> = () => {
Home
Todo
+ Customer
+ Product
diff --git a/TestAppRuna/Shop.sqlite.db b/TestAppRuna/Shop.sqlite.db
index 77747a9..cccb038 100644
Binary files a/TestAppRuna/Shop.sqlite.db and b/TestAppRuna/Shop.sqlite.db differ