mirror of
https://github.com/TheRealOwenRees/echecsfrance.git
synced 2026-07-23 12:36:57 +00:00
table hover fix
This commit is contained in:
@@ -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() {
|
||||||
@@ -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>
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -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,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
|
||||||
Reference in New Issue
Block a user