table hover fix

This commit is contained in:
Owen Rees
2023-06-19 23:17:21 +02:00
parent a4a0e0a669
commit ffbc8db21d
9 changed files with 98 additions and 34 deletions
+13 -21
View File
@@ -1,33 +1,25 @@
//TODO readme // TODO change tests to follow best practices https://docs.cypress.io/guides/references/best-practices
// TODO tests for tournament page:
- map and table mounts in tournament page <- get data to send to map/table
---------------------------------------------------------------- ----------------------------------------------------------------
//TODO hover on table needs fixing - this only seemed to happen once I moved the logic into its own hook <- error is occurring on all hovers at the moment.
//TODO hover on table needs fixing - this only seemed to happen once I moved the logic into its own hook <- error is occurring on all hovers at the moment. Client/SSR issue? //TODO fix table hover colours
-----------------------------------------------------------------
//TODO about page
//TODO contact page needs working mailer
//TODO font size on mobile screen //TODO font size on mobile screen
//TODO need a 'return to top' arrow button on smaller screens //TODO need a 'return to top' arrow button on smaller screens
//TODO SEO - next headers etc
----------------------------------------------------------------
//TODO logo for navbar and favicon
//TODO mobile map needs improving //TODO mobile map needs improving
//TODO multi-language i18n support - https://nextjs.org/docs/app/building-your-application/routing/internationalization //TODO multi-language i18n support - https://nextjs.org/docs/app/building-your-application/routing/internationalization
//TODO tests for tournois, testing the loading of map and table, then counting the markers
//TODO logo for navbar and favicon
//TODO document my new hook <- consider removing as I believe this is the reason hover is broken
//TODO error handling //TODO error handling
//TODO e2e tests for tournament page:
- make sure number of markers = tournamentData.length
//TODO about page
//TODO contact page needs working mailer
//TODO SEO
//TODO consider offering GraphQL support //TODO consider offering GraphQL support
//TODO move smaller ui components into a new folder, and make them reusable - such as using generic prop names //TODO move smaller ui components into a new folder, and make them reusable - such as using generic prop names
//TODO readme
@@ -3,8 +3,8 @@ import { dateOrderingFrance } from "@/utils/dbDateOrdering";
/** /**
* Tournament data API endpoint * Tournament data API endpoint
* @route /api/tournaments/france * @route /api/v1/tournaments/france
* @internal * @public
*/ */
export const revalidate = 3600; // revalidate cache every 6 hours export const revalidate = 3600; // revalidate cache every 6 hours
export async function GET() { export async function GET() {
+53 -9
View File
@@ -2,19 +2,60 @@
import { TournamentDataProps } from "@/types"; import { TournamentDataProps } from "@/types";
import { useEffect, useState } from "react"; import { useEffect, useState } from "react";
import useTournamentDataFilter from "@/hooks/useTournamentFilter";
import SearchBar from "@/components/SearchBar"; import SearchBar from "@/components/SearchBar";
export default function TournamentTable({ export default function TournamentTable({
tournamentData, tournamentData,
}: TournamentDataProps) { }: TournamentDataProps) {
const [tournamentFilter, setTournamentFilter] = useState(""); // text from search bar let tableData;
const [searchQuery, setSearchQuery] = useState(""); // text from search bar
const [filteredTournamentData, setFilteredTournamentData] = const [filteredTournamentData, setFilteredTournamentData] =
useTournamentDataFilter(tournamentData); useState(tournamentData);
useEffect(() => { useEffect(() => {
setFilteredTournamentData(tournamentFilter); setFilteredTournamentData(
}, [tournamentFilter]); tournamentData.filter((t) => t.town.includes(searchQuery.toUpperCase()))
);
}, [searchQuery]);
// TODO move this section into its own function
if (filteredTournamentData.length === 0) {
tableData = (
<tr className="bg-white text-gray-900 dark:bg-gray-800 dark:text-white">
<td colSpan={4} className="p-3">
No tournaments found
</td>
</tr>
);
} else {
tableData = filteredTournamentData.map((t) => (
<tr
className="text-gray-900 bg-white dark:bg-gray-800 dark:text-white hover:bg-gray-200 dark:hover:bg-gray-900"
key={t._id}
>
<td className="p-3">
<a href={t.url} target="_blank">
{t.date}
</a>
</td>
<td className="p-3">
<a href={t.url} target="_blank">
{t.town}
</a>
</td>
<td className="p-3">
<a href={t.url} target="_blank">
{t.tournament}
</a>
</td>
<td className="p-3">
<a href={t.url} target="_blank">
{t.time_control}
</a>
</td>
</tr>
));
}
const stickyHeader = const stickyHeader =
"sticky top-0 p-3 bg-teal-600 text-white dark:bg-gray-600"; "sticky top-0 p-3 bg-teal-600 text-white dark:bg-gray-600";
@@ -22,10 +63,13 @@ export default function TournamentTable({
return ( return (
<section className="w-full grid auto-rows-max pb-20 lg:h-[calc(100vh-174px)] lg:col-start-2 lg:col-end-3"> <section className="w-full grid auto-rows-max pb-20 lg:h-[calc(100vh-174px)] lg:col-start-2 lg:col-end-3">
<SearchBar <SearchBar
tournamentFilter={tournamentFilter} tournamentFilter={searchQuery}
setTournamentFilter={setTournamentFilter} setTournamentFilter={setSearchQuery}
/> />
<table className="relative table-fixed w-full text-center text-xs"> <table
className="relative table-fixed w-full text-center text-xs"
data-cy="tournament-table"
>
<thead> <thead>
<tr> <tr>
<th className={stickyHeader}>Date</th> <th className={stickyHeader}>Date</th>
@@ -34,7 +78,7 @@ export default function TournamentTable({
<th className={stickyHeader}>Cadence</th> <th className={stickyHeader}>Cadence</th>
</tr> </tr>
</thead> </thead>
<tbody>{filteredTournamentData}</tbody> <tbody>{tableData}</tbody>
</table> </table>
</section> </section>
); );
+27
View File
@@ -0,0 +1,27 @@
let tableRows: number;
describe("Data fetching for map", () => {
it("map markers is equal to table rows", () => {
cy.visit("/tournois");
cy.get('[data-cy="tournament-table"]')
.find("tr")
.then((rows) => {
tableRows = rows.length - 1;
});
cy.get(".leaflet-marker-icon").then((markers) => {
expect(markers.length).to.eq(tableRows);
});
});
});
describe("Data fetching from API endpoints", () => {
it("api call should equal website data count", () => {
cy.request("GET", "http://localhost:3000/api/v1/tournaments/france").then(
(response) => {
expect(response.status).to.eq(200);
const responseData = response.body;
const itemCount = responseData.length;
expect(itemCount).to.eq(tableRows);
}
);
});
});
Binary file not shown.
Binary file not shown.
Binary file not shown.
+1 -2
View File
@@ -1,8 +1,7 @@
import { Tournament } from "@/types"; import { Tournament } from "@/types";
import { useState } from "react"; import { useState } from "react";
// TODO change 'any' // TODO delete after testing
// TODO document this hook with TSDoc
const useTournamentDataFilter = ( const useTournamentDataFilter = (
initialState: Tournament[] initialState: Tournament[]
): (any | ((searchQuery: string) => void))[] => { ): (any | ((searchQuery: string) => void))[] => {
@@ -0,0 +1,2 @@
GET http://localhost:3000/api/v1/tournaments/france
Accept: application/json