Listing and Filtering Application (PERCON A.S.)
This project is a web application that lists holidays in Germany, the Netherlands, France, and Belgium, allowing users to filter data by country, state, holiday type, year, and month. The application is built with Supabase, Next.js 15, and TypeScript (.tsx).
- Frontend Framework: Built with Next.js (v15) and TypeScript.
- Backend: Uses Supabase for API operations.
- Database: Stores holiday data and filter options in Supabase.
- Holiday Listing: Displays holidays for the specified countries with relevant details.
- Filtering Options: Users can filter holidays by:
- Country (e.g., Germany, Netherlands)
- State (dynamically filtered by selected country)
- Holiday Type (e.g., public, observance)
- Year and Month (yearly and monthly filter options)
- Pagination: Allows navigation through holiday listings across multiple pages.
- Dynamic Filtering: Filters are dynamically updated based on selected criteria (e.g., states filter updates according to selected country).
- Node.js: Ensure Node.js is installed.
- Supabase Account: Sign up at Supabase and set up a project.
- Environment Variables: Add the following environment variables in a
.env.local
file:NEXT_PUBLIC_SUPABASE_URL
: Your Supabase project URL.NEXT_PUBLIC_SUPABASE_ANON_KEY
: Your Supabase anonymous key.
-
Clone this repository:
git clone <repository-url> cd <project-directory>
-
Install dependencies:
npm install
-
Set up environment variables in a
.env.local
file:NEXT_PUBLIC_SUPABASE_URL=your_supabase_url NEXT_PUBLIC_SUPABASE_ANON_KEY=your_supabase_anon_key
-
Start the development server:
npm run dev
-
Access the application at
http://localhost:3000
.
This project requires several tables on Supabase to manage holiday information: countries
, states
, and holidays
. Below are the steps to create these tables, along with the necessary SQL queries.
The project uses three main tables: countries
, states
, and holidays
. Each table should be structured as follows.
The countries
table stores each country's name and the count of holidays within that country.
CREATE TABLE countries (
id SERIAL PRIMARY KEY,
name VARCHAR(255) NOT NULL,
holiday_count INTEGER DEFAULT 0
);
id
: Auto-incrementing unique identifier.name
: Name of the country.holiday_count
: Stores the number of holidays associated with this country. Default value is0
.
The states
table stores the states or regions within a country.
CREATE TABLE states (
id SERIAL PRIMARY KEY,
name VARCHAR(255) NOT NULL,
country_id INTEGER REFERENCES countries(id) ON DELETE CASCADE
);
id
: Auto-incrementing unique identifier.name
: Name of the state or region.country_id
: Foreign key that references an entry in thecountries
table. When a country is deleted, all associated states will also be deleted (ON DELETE CASCADE
).
The holidays
table stores details of each holiday and associates it with a specific country and/or state.
CREATE TABLE holidays (
id SERIAL PRIMARY KEY,
date DATE NOT NULL,
name VARCHAR(255) NOT NULL,
color CHAR(7) DEFAULT '#FFFFFF',
state_id INTEGER REFERENCES states(id) ON DELETE SET NULL,
type VARCHAR(50) CHECK (type IN ('Official', 'Religious')),
country_id INTEGER REFERENCES countries(id) ON DELETE CASCADE
);
id
: Auto-incrementing unique identifier.date
: Date of the holiday.name
: Name of the holiday.color
: Color code for the holiday (in hex format, e.g.,#16a34a
).state_id
: Foreign key that references an entry in thestates
table. If the state is deleted, this value is set toNULL
(ON DELETE SET NULL
).type
: Type of holiday, restricted toOfficial
orReligious
values (CHECK
constraint).country_id
: Foreign key that references an entry in thecountries
table. When a country is deleted, all associated holidays are also deleted (ON DELETE CASCADE
).
To keep the holiday_count
in the countries
table up to date, you can set up a TRIGGER
and FUNCTION
that will update this count each time a holiday is added or removed.
CREATE OR REPLACE FUNCTION update_holiday_count()
RETURNS TRIGGER AS $$
BEGIN
IF TG_OP = 'INSERT' THEN
UPDATE countries
SET holiday_count = holiday_count + 1
WHERE id = NEW.country_id;
ELSIF TG_OP = 'DELETE' THEN
UPDATE countries
SET holiday_count = holiday_count - 1
WHERE id = OLD.country_id;
END IF;
RETURN NULL;
END;
$$ LANGUAGE plpgsql;
CREATE TRIGGER trigger_update_holiday_count
AFTER INSERT OR DELETE ON holidays
FOR EACH ROW
EXECUTE FUNCTION update_holiday_count();
This TRIGGER
will activate the update_holiday_count
function each time an INSERT
or DELETE
operation occurs on the holidays
table, keeping the holiday_count
field in the countries
table accurate.
app/page.tsx
: Main page component containing the holiday listing, filter panel, and pagination.components/FilterPanel.tsx
: Contains filter components for country, state, type, year, and month.components/HolidayList.tsx
: Displays holiday information with transition effects for visual appeal.components/Pagination.tsx
: Controls pagination for navigating through holidays.lib/supabaseClient.ts
: Sets up and exports the Supabase client for API calls.
This application interacts with two primary API endpoints hosted in Supabase:
/api/filters
: Provides filter options such as countries, states, and holiday types./api/holidays
: Retrieves holiday data based on applied filters and pagination.
- Select Filters: Use the Filter Panel to select criteria for filtering holidays.
- Browse Results: View holidays that match selected filters.
- Pagination: Navigate through pages if results exceed the items per page limit.
To adjust the application behavior or add new filters, you can modify the FilterPanel
and HolidayList
components to incorporate additional filtering logic or adjust the Supabase query logic as needed.
This project is open-source and available under the MIT License.
- Next.js for the powerful React framework.
- Supabase for the backend API and database.