Skip to content

Commit

Permalink
feat(frontend): implement resources listing pages
Browse files Browse the repository at this point in the history
  • Loading branch information
gabrielborgesdm committed Jun 4, 2024
1 parent 3e8b66b commit b50335d
Show file tree
Hide file tree
Showing 4 changed files with 273 additions and 212 deletions.
15 changes: 7 additions & 8 deletions frontend/src/components/Layout.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,12 @@ import { Outlet } from "react-router-dom";
import { Navbar } from "./Navbar";

const Layout: React.FC = () => (
<>
<Navbar />
<div className="sm:rounded-lg w-1/2 mx-auto mt-4">
<Outlet />
</div>
</>
<>
<Navbar />
<div className="sm:rounded-lg w-1/2 mx-auto mt-4">
<Outlet />
</div>
</>
);

export default Layout

export default Layout;
133 changes: 82 additions & 51 deletions frontend/src/components/Navbar.tsx
Original file line number Diff line number Diff line change
@@ -1,63 +1,94 @@
import React, { useState } from "react";
import { useLocation } from 'react-router-dom';
import { useLocation } from "react-router-dom";

export const Navbar: React.FC = () => {
const location = useLocation();

const location = useLocation();
const [nav, setNav] = useState(false);

const [nav, setNav] = useState(false);
const handleNav = () => {
setNav(!nav);
};

const handleNav = () => {
setNav(!nav);
};
const verifyCurrentRouteAndApplyStylingClasses = (path: string) => {
if (location.pathname === path) {
return "bg-gray-900 text-white rounded-md px-3 py-2 text-sm font-medium";
}

const verifyCurrentRouteAndApplyStylingClasses = (path: string) => {
console.log(location.pathname)
if (location.pathname === path) {
return "bg-gray-900 text-white rounded-md px-3 py-2 text-sm font-medium"
}
return "text-gray-300 hover:bg-gray-700 hover:text-white rounded-md px-3 py-2 text-sm font-medium";
};

return "text-gray-300 hover:bg-gray-700 hover:text-white rounded-md px-3 py-2 text-sm font-medium"
}
return (
<nav className="bg-gray-800">
<div className="mx-auto max-w-7xl px-2 sm:px-6 lg:px-8">
<div className="relative flex h-16 items-center justify-between">
<div className="absolute inset-y-0 left-0 flex items-center sm:hidden">
<button
onClick={handleNav}
type="button"
className="relative inline-flex items-center justify-center rounded-md p-2 text-gray-400 hover:bg-gray-700 hover:text-white focus:outline-none focus:ring-2 focus:ring-inset focus:ring-white"
aria-controls="mobile-menu"
aria-expanded="false"
>
<span className="absolute -inset-0.5"></span>
<span className="sr-only">Open main menu</span>

<svg
className="block h-6 w-6"
fill="none"
viewBox="0 0 24 24"
strokeWidth="1.5"
stroke="currentColor"
aria-hidden="true"
>
<path strokeLinecap="round" strokeLinejoin="round" d="M3.75 6.75h16.5M3.75 12h16.5m-16.5 5.25h16.5" />
</svg>

return (
<nav className="bg-gray-800">
<div className="mx-auto max-w-7xl px-2 sm:px-6 lg:px-8">
<div className="relative flex h-16 items-center justify-between">
<div className="absolute inset-y-0 left-0 flex items-center sm:hidden">

<button onClick={handleNav} type="button" className="relative inline-flex items-center justify-center rounded-md p-2 text-gray-400 hover:bg-gray-700 hover:text-white focus:outline-none focus:ring-2 focus:ring-inset focus:ring-white" aria-controls="mobile-menu" aria-expanded="false">
<span className="absolute -inset-0.5"></span>
<span className="sr-only">Open main menu</span>

<svg className="block h-6 w-6" fill="none" viewBox="0 0 24 24" strokeWidth="1.5" stroke="currentColor" aria-hidden="true">
<path strokeLinecap="round" strokeLinejoin="round" d="M3.75 6.75h16.5M3.75 12h16.5m-16.5 5.25h16.5" />
</svg>

<svg className="hidden h-6 w-6" fill="none" viewBox="0 0 24 24" strokeWidth="1.5" stroke="currentColor" aria-hidden="true">
<path strokeLinecap="round" strokeLinejoin="round" d="M6 18L18 6M6 6l12 12" />
</svg>
</button>
</div>
<div className="flex flex-1 items-center justify-center sm:items-stretch sm:justify-start">
<span className="flex flex-shrink-0 items-center text-white">Book's Manager</span>
<div className="hidden sm:ml-6 sm:block">
<div className="flex space-x-4">
<a href="/" className={verifyCurrentRouteAndApplyStylingClasses("/")} aria-current="page">Books</a>
<a href="/authors" className={verifyCurrentRouteAndApplyStylingClasses("/authors")}>Authors</a>
</div>
</div>
</div>
</div>
<svg
className="hidden h-6 w-6"
fill="none"
viewBox="0 0 24 24"
strokeWidth="1.5"
stroke="currentColor"
aria-hidden="true"
>
<path strokeLinecap="round" strokeLinejoin="round" d="M6 18L18 6M6 6l12 12" />
</svg>
</button>
</div>
<div className="flex flex-1 items-center justify-center sm:items-stretch sm:justify-start">
<span className="flex flex-shrink-0 items-center text-white">Book&apos;s Manager</span>
<div className="hidden sm:ml-6 sm:block">
<div className="flex space-x-4">
<a href="/" className={verifyCurrentRouteAndApplyStylingClasses("/")} aria-current="page">
Books
</a>
<a href="/authors" className={verifyCurrentRouteAndApplyStylingClasses("/authors")}>
Authors
</a>
</div>
</div>
</div>
</div>
</div>

<div className={`sm:hidden ${!nav && "hidden"}`} id="mobile-menu">
<div className="space-y-1 px-2 pb-3 pt-2">
<a href="/" className="bg-gray-900 text-white block rounded-md px-3 py-2 text-base font-medium" aria-current="page">Books</a>
<a href="/authors" className="text-gray-300 hover:bg-gray-700 hover:text-white block rounded-md px-3 py-2 text-base font-medium">Authors</a>
</div>
</div>
</nav>
)
}
<div className={`sm:hidden ${!nav && "hidden"}`} id="mobile-menu">
<div className="space-y-1 px-2 pb-3 pt-2">
<a
href="/"
className="bg-gray-900 text-white block rounded-md px-3 py-2 text-base font-medium"
aria-current="page"
>
Books
</a>
<a
href="/authors"
className="text-gray-300 hover:bg-gray-700 hover:text-white block rounded-md px-3 py-2 text-base font-medium"
>
Authors
</a>
</div>
</div>
</nav>
);
};
169 changes: 92 additions & 77 deletions frontend/src/pages/Authors/Authors.tsx
Original file line number Diff line number Diff line change
@@ -1,87 +1,102 @@
import React, { useEffect, useState } from 'react';
import ManagementService from 'services/managementService';
import { useFilterHook } from 'components/Hooks/UseFilterHook';
import { Author } from 'types/author';

const managementService = new ManagementService()
import React, { useEffect, useState } from "react";
import ManagementService from "services/managementService";
import { useFilterHook } from "components/Hooks/UseFilterHook";
import { Author } from "types/author";

const managementService = new ManagementService();

const Authors: React.FC = () => {
const [authors, setAuthors] = useState<Author[]>([])
const { handleChangeFilter, shouldFilterInWith } = useFilterHook();

useEffect(() => {
loadAuthors()
}, [])

const loadAuthors = async () => {
const authors = await managementService.getAuthors()
const [authors, setAuthors] = useState<Author[]>([]);
const { handleChangeFilter, shouldFilterInWith } = useFilterHook();

setAuthors(authors)
}
useEffect(() => {
loadAuthors();
}, []);

const loadAuthors = async () => {
const authors = await managementService.getAuthors();

return (
<>
<div className="flex items-center py-2 justify-between">
<label htmlFor="table-search" className="sr-only">Search</label>
<div className="relative">
<div className="absolute inset-y-0 rtl:inset-r-0 start-0 flex items-center ps-3 pointer-events-none">
<svg className="w-4 h-4 text-gray-500 dark:text-gray-400" aria-hidden="true" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 20 20">
<path stroke="currentColor" strokeLinecap="round" strokeLinejoin="round" strokeWidth="2" d="m19 19-4-4m0-7A7 7 0 1 1 1 8a7 7 0 0 1 14 0Z" />
</svg>
</div>
<input type="text" id="table-search" onChange={handleChangeFilter} className="block py-3 ps-10 text-sm border rounded-lg w-80 focus:ring-blue-500 focus:border-blue-500 " placeholder="Search for items" />
</div>
<a href='/authors/create' className="max-sm:w-full bg-blue-500 hover:bg-blue-700 text-white font-bold py-2 px-4 rounded">
+ Add author
</a>
</div>
<hr />
<div className='block max-h-[78dvh] overflow-y-auto'>
<table className="w-full text-sm text-left rtl:text-right text-gray-500">
<thead className="text-xs uppercase ">
<tr>
setAuthors(authors);
};

<th scope="col" className="px-1 py-3">
Author
</th>
<th scope="col" className="px-1 py-3">
Nationality
</th>
<th scope="col" className="px-1 py-3">
Birth date
</th>
<th scope="col" className="px-1 py-3">
E-mail
</th>
</tr>
</thead>
<tbody>
{authors?.length > 0 && authors.map(({ name, nationality, birthDate, email, id }: Author) => (
shouldFilterInWith(name, nationality, birthDate, email, id)
&& (
<tr key={id} className="border-b hover:bg-gray-50">
<th scope="row" className="px-1 py-4 font-medium text-gray-900 whitespace-nowrap">
{name}
</th>
<td className="px-1 py-4">
{nationality}
</td>
<td className="px-1 py-4">
{birthDate}
</td>
<td className="px-1 py-4">
{email}
</td>
</tr>
)
))}
</tbody>
</table>
</div>
</>
);
return (
<>
<div className="flex items-center py-2 justify-between">
<label htmlFor="table-search" className="sr-only">
Search
</label>
<div className="relative">
<div className="absolute inset-y-0 rtl:inset-r-0 start-0 flex items-center ps-3 pointer-events-none">
<svg
className="w-4 h-4 text-gray-500 dark:text-gray-400"
aria-hidden="true"
xmlns="http://www.w3.org/2000/svg"
fill="none"
viewBox="0 0 20 20"
>
<path
stroke="currentColor"
strokeLinecap="round"
strokeLinejoin="round"
strokeWidth="2"
d="m19 19-4-4m0-7A7 7 0 1 1 1 8a7 7 0 0 1 14 0Z"
/>
</svg>
</div>
<input
type="text"
id="table-search"
onChange={handleChangeFilter}
className="block py-3 ps-10 text-sm border rounded-lg w-80 focus:ring-blue-500 focus:border-blue-500 "
placeholder="Search for items"
/>
</div>
<a
href="/authors/create"
className="max-sm:w-full bg-blue-500 hover:bg-blue-700 text-white font-bold py-2 px-4 rounded"
>
+ Add author
</a>
</div>
<hr />
<div className="block max-h-[78dvh] overflow-y-auto">
<table className="w-full text-sm text-left rtl:text-right text-gray-500">
<thead className="text-xs uppercase ">
<tr>
<th scope="col" className="px-1 py-3">
Author
</th>
<th scope="col" className="px-1 py-3">
Nationality
</th>
<th scope="col" className="px-1 py-3">
Birth date
</th>
<th scope="col" className="px-1 py-3">
E-mail
</th>
</tr>
</thead>
<tbody>
{authors?.length > 0 &&
authors.map(
({ name, nationality, birthDate, email, id }: Author) =>
shouldFilterInWith(name, nationality, birthDate, email, id) && (
<tr key={id} className="border-b hover:bg-gray-50">
<th scope="row" className="px-1 py-4 font-medium text-gray-900 whitespace-nowrap">
{name}
</th>
<td className="px-1 py-4">{nationality}</td>
<td className="px-1 py-4">{birthDate}</td>
<td className="px-1 py-4">{email}</td>
</tr>
),
)}
</tbody>
</table>
</div>
</>
);
};

export default Authors;
Loading

0 comments on commit b50335d

Please sign in to comment.