diff --git a/public/lapiz.png b/public/lapiz.png new file mode 100644 index 0000000..676ff53 Binary files /dev/null and b/public/lapiz.png differ diff --git a/src/app/layout.tsx b/src/app/layout.tsx index 828d36b..3796391 100644 --- a/src/app/layout.tsx +++ b/src/app/layout.tsx @@ -16,7 +16,7 @@ export default function RootLayout({ children: React.ReactNode }) { return ( - +
diff --git a/src/app/pedidos/cliente/[id]/page.tsx b/src/app/pedidos/cliente/[id]/page.tsx index 6761c12..6067629 100644 --- a/src/app/pedidos/cliente/[id]/page.tsx +++ b/src/app/pedidos/cliente/[id]/page.tsx @@ -1,3 +1,87 @@ -export default function Page({ params }: { params: { id: string } }) { - return
My Post: {params.id}
-} \ No newline at end of file +'use client' +import { Input } from '@/components/Input'; +import { useForm } from 'react-hook-form'; +import Button from '@/components/Button'; +import { useRouter } from 'next/navigation'; +import { useEffect, useState } from 'react'; +import { Toolbar } from '@/components/Toolbar'; +import useFetchWithAuth from '@/hooks/useFetchWithAuth'; +import saveWithAuth from '@/hooks/saveWithAuth'; + +const ClientePage = ({ params }: { params: { id: string } }) => { + + const router = useRouter(); + const entityId =params.id; + const [cliente, setCliente] = useState({ + id: 0, + cedula: '', + nombreCompleto: '', + }); + const { register, setValue,getValues,handleSubmit, formState: { errors } } = useForm( + { + defaultValues: { + ...cliente + } + } + ); + + const getInitData = async () => { + if (!entityId || entityId=="0") + return; + const { data, error } = await useFetchWithAuth("cliente/" + entityId); + + if (!error) { + + if (data.id!=0){ + setValue("id", data['id']) + setValue("cedula", data['cedula']) + setValue("nombreCompleto", data['nombreCompleto']) + setCliente(data) + } + + } else { + console.log(error) + } + } + + const onSubmit = async (entity: any) => { + try { + let endpoint = "cliente"; + + const { data, error } = await saveWithAuth(endpoint, entityId, entity); + if (error) { + console.log(error); + } else { + router.push("pedidos/"+endpoint+"/"+ data.id) + } + } catch (e) { + console.log("Post error:"); + console.table(e); + } + } + + + useEffect(() => { + getInitData(); + }, []) + + return ( + <> +
+ +
+
+ + + +
+
+ + + ) +} + +export default ClientePage; diff --git a/src/app/pedidos/cliente/page.tsx b/src/app/pedidos/cliente/page.tsx index 6e47124..fcb1010 100644 --- a/src/app/pedidos/cliente/page.tsx +++ b/src/app/pedidos/cliente/page.tsx @@ -1,24 +1,20 @@ +import { Toolbar } from '@/components/Toolbar'; import Head from '@/components/table/Head' import TBody from '@/components/table/TBody'; -import { FC } from 'react' -interface Props { -} - -const ListadoCliente:FC = () => { +const ListadoCliente = () => { return ( <> - -
-

Listado de cliente

-
- +
+ +

Listado de clientes

+
+
-
- -
+
+ ) } diff --git a/src/app/pedidos/layout.tsx b/src/app/pedidos/layout.tsx index 3ef6da6..3f9575b 100644 --- a/src/app/pedidos/layout.tsx +++ b/src/app/pedidos/layout.tsx @@ -2,6 +2,7 @@ import Navbar from '@/components/Navbar' import './../globals.css' import { Inter } from 'next/font/google' import Sidebar from '@/components/Sidebar' +import { Toolbar } from '@/components/Toolbar' const inter = Inter({ subsets: ['latin'] }) @@ -20,7 +21,6 @@ export default function RootLayout({ <>
- {children}
diff --git a/src/app/pedidos/producto/page.tsx b/src/app/pedidos/producto/page.tsx index 72af797..983b28d 100644 --- a/src/app/pedidos/producto/page.tsx +++ b/src/app/pedidos/producto/page.tsx @@ -1,26 +1,22 @@ -import Navbar from '@/components/Navbar' +import { Toolbar } from '@/components/Toolbar' import Head from '@/components/table/Head' import TBody from '@/components/table/TBody' -import { FC } from 'react' -interface Props { -} - -const ListadoProducto:FC = () => { - return ( - <> -
-

Listado de producto

-
- - - +const Listadoproducto = () => { + return ( + <> +
+ +

Listado de productos

+
+
+ +
-
- -
- - ) + + + + ) } -export default ListadoProducto \ No newline at end of file +export default Listadoproducto \ No newline at end of file diff --git a/src/components/Button.tsx b/src/components/Button.tsx index 1f7e2e8..030c7ac 100644 --- a/src/components/Button.tsx +++ b/src/components/Button.tsx @@ -5,15 +5,17 @@ import { FC } from 'react' interface Props { label: string, - onClick: () => void - + onClick?: () => void + type?:"button" | "submit" | "reset" | undefined + className?: string } -const Button:FC = ({label, onClick}) => { +const Button:FC = ({label, onClick=()=>{},type='button', className}) => { return ( <> - diff --git a/src/components/Input.tsx b/src/components/Input.tsx new file mode 100644 index 0000000..98d50f4 --- /dev/null +++ b/src/components/Input.tsx @@ -0,0 +1,26 @@ +import React from 'react'; +import { FC } from 'react' +import { UseFormRegister,FieldValues } from 'react-hook-form'; + +interface Props { + id: string, + label: string, + type?:"text"|"password"|"checkbox"|"hidden"|"number"|"date"|"datetime-local", + register: UseFormRegister +} + +export const Input:FC = ({id,label,type="text", register}) => { + return ( + <> +
+ + +
+ + + ) +} diff --git a/src/components/Manytoone.tsx b/src/components/Manytoone.tsx new file mode 100644 index 0000000..1035a66 --- /dev/null +++ b/src/components/Manytoone.tsx @@ -0,0 +1,55 @@ +import React, { FC, useEffect, useState } from 'react' +import { Controller, Control } from 'react-hook-form'; +import useFetchWithAuth from '@/hooks/useFetchWithAuth'; + +interface Props { + + entity: string, + control: Control +} + +export const Manytoone: FC = ({entity, control }) => { + + + + const [data, setData] = useState([{id:0,nombre:'Select one'}]); + useEffect(() => { + async function fetchData() { + try { + const { data, error } = await useFetchWithAuth(entity.toLowerCase()); + setData(data); + + } catch (trace) { + console.error(trace); + } + } + fetchData(); + }, [entity]); + + return ( + <> + + ( + + )} + name={entity} + control={control} + /> + + + + ) +} + + + diff --git a/src/components/Toolbar.tsx b/src/components/Toolbar.tsx new file mode 100644 index 0000000..fda09b3 --- /dev/null +++ b/src/components/Toolbar.tsx @@ -0,0 +1,58 @@ +'use client' +import { FC } from 'react' +import Link from 'next/link' + + +interface Props { + pathForm: string + pathList: string + entityName: string + currentEntity: string +} + +export const Toolbar: FC = ({ + pathForm, + pathList, + entityName, + currentEntity, +}) => { + + return ( + <> + +
+ + + +

+
+ +
+

+
+ + + + ) +} diff --git a/src/components/table/TBody.tsx b/src/components/table/TBody.tsx index 14ecde6..33e25b5 100644 --- a/src/components/table/TBody.tsx +++ b/src/components/table/TBody.tsx @@ -31,12 +31,12 @@ const TBody:FC = ({columnas, endpoint}) => { {entidades && entidades.map((entidad) => ( - + - Editar + {columnas.map((columna)=> ( diff --git a/src/hooks/saveWithAuth.ts b/src/hooks/saveWithAuth.ts new file mode 100644 index 0000000..eb954f0 --- /dev/null +++ b/src/hooks/saveWithAuth.ts @@ -0,0 +1,43 @@ +import Cookies from 'js-cookie'; + +const fecher = async (url: string, id:string, token: string, data:any) => { + return await fetch(url, { + method: id==="0" ? 'POST': 'PATCH', + mode: 'cors', + headers: { + 'Authorization' :token, + 'Content-Type': 'application/json', + 'Accept':'application/json' + }, + body: data, + }); + } + + const saveWithAuth = async (url: string, id:string, body:any) => { + url= process.env.API_URL+"/api/"+url+"/"; + if ( Number(id)>0){ + url = url + id +"/" + } + const token = Cookies.get('token') || ""; + let data; + let error; + try{ + data = JSON.stringify(body); + console.log(url) + const response = await fecher(url, id, token, data) + if (response.ok){ + data = await response.json(); + }else { + error = "Servidor: "+ ((await response.json()).trace).substring(1,300); + } + }catch (e){ + error = "Cliente: "+e; + } + return { + data, + error + } + + } + + export default saveWithAuth; \ No newline at end of file diff --git a/src/hooks/useBasicAuth.tsx b/src/hooks/useBasicAuth.tsx index b5c281e..2b0b5e5 100644 --- a/src/hooks/useBasicAuth.tsx +++ b/src/hooks/useBasicAuth.tsx @@ -11,13 +11,13 @@ const fecher = async (url:string, token: string) => { const useBasicAuth = async (username: string, password: string) => { let bearerToken = ""; try { - console.log("ingreso en el useBasicAuth") + const token = 'Basic '+ Buffer.from(username+":"+password).toString('base64'); - console.log(token) + const baseUrl = process.env.API_URL; - console.log(baseUrl) + const response = await fecher(baseUrl+'/login', token); - console.log(response) + if (response.ok){ bearerToken = response.headers.get("Authorization") || ""; diff --git a/src/hooks/useFetchWithAuth.tsx b/src/hooks/useFetchWithAuth.tsx index 94294ae..93d7437 100644 --- a/src/hooks/useFetchWithAuth.tsx +++ b/src/hooks/useFetchWithAuth.tsx @@ -11,6 +11,7 @@ const fecher = async (url:string, token: string) => { const useBasicAuth = async (endpoint:string) => { let data = null; + let error; try { const token = Cookies.get("token")|| ""; @@ -21,14 +22,16 @@ const useBasicAuth = async (endpoint:string) => { if (response.ok){ data = await response.json(); - - } - } catch (error) { - console.log(error) + }else { + error = "Servidor: "+ ((await response.json()).trace); + } + } catch (err) { + error = "Cliente: "+err; } return{ - data + data, + error } } diff --git a/tailwind.config.js b/tailwind.config.js index 74da8f8..3a5badd 100644 --- a/tailwind.config.js +++ b/tailwind.config.js @@ -15,4 +15,7 @@ module.exports = { }, }, plugins: [require("daisyui")], + daisyui: { + themes: ["light", "dark", "cmyk"], + }, }