This commit is contained in:
dominicjk
2024-04-15 11:04:16 -06:00
33 changed files with 1025 additions and 137 deletions

View File

@@ -0,0 +1,5 @@
body {
/* background-image: url('./../img/grass-background.png'); Specify the path to your background image */
/* background-repeat: repeat; Set the background image to repeat both horizontally and vertically */
/* background-size: 1000px; Set the size of the background image for each repeat */
}

View File

@@ -0,0 +1,66 @@
#club-page-body {
display: flex;
flex-direction: column;
width: 100%;
}
#club-information-container {
height: 100px;
width: fit-content;
margin: 20px;
background: linear-gradient(to right, white, rgb(245, 245, 245), rgb(227, 227, 227)); /* Gradient from white to gray */
padding: 10px 20px; /* Adjust padding as needed */
transform: skewX(-20deg); /* Skew the banner to create a triangular side */
cursor: pointer; /* Change cursor to pointer on hover */
box-shadow: 0px 3px 4px rgba(0, 0, 0, 0.4);
display: flex; /* Use flexbox for layout */
align-items: center; /* Center content vertically */
/* Add any other styling you need for the club information container */
}
#club-information-container::after {
content: '';
position: absolute;
top: 0;
right: 0;
bottom: 0;
width: 8px; /* Width of the red strip */
background-color: red; /* Red color */
}
#club-logo {
margin: 0px 30px;
transform: skewX(20deg); /* Skew the banner to create a triangular side */
}
#club-title {
transform: skewX(20deg); /* Skew the banner to create a triangular side */
margin-right: 20px;
}
#club-flag {
transform: skewX(20deg); /* Skew the banner to create a triangular side */
height: 20px;
margin-right: 200px;
}
#club-stats-container {
width: 100%;
display: flex;
flex: 1;
}
#club-stats-container .container {
margin: 0 10px;
background-color: #eaeaea; /* Example background color */
border: 1px solid gray;
border-radius: 8px;
box-shadow: 0px 3px 4px rgba(0, 0, 0, 0.4);
/* Add any other styling you need for the club table container */
}

View File

@@ -0,0 +1,6 @@
#club-top-scorers-container {
flex: 1;
background-color: #dcdcdc; /* Example background color */
width: 40%;
/* Add any other styling you need for the top scorers container */
}

View File

@@ -1,28 +0,0 @@
#league-page-body {
display: flex;
flex-direction: column;
height: 100vh;
}
#league-information-container {
height: 100px;
background-color: #f0f0f0; /* Example background color */
/* Add any other styling you need for the league information container */
}
#league-stats-container {
display: flex;
flex: 1;
}
#league-table-container {
flex: 1;
background-color: #eaeaea; /* Example background color */
/* Add any other styling you need for the league table container */
}
#top-scorers-container {
flex: 1;
background-color: #dcdcdc; /* Example background color */
/* Add any other styling you need for the top scorers container */
}

View File

@@ -0,0 +1,142 @@
/*
==============================================================
OVERALL PAGE STYLES
==============================================================
*/
#league-page-body
{
/* --- SIZE CONTAINER --- */
width: 100%; /* Set the width to the full width of screen */
padding: 10px 100px; /* Create some distance between page boundries and elements */
/* --- FORMAT CHILD ITEMS (Table and Leading Scorers Cards) --- */
display: flex; /* Enable flexbox layout */
flex-direction: column; /* Arrange child elements vertically */
}
/*
=================================
LEAGUE INFORMATION HEADER
=================================
*/
/* Stylization for League Information Header Card */
#league-information-container
{
/* --- POSITION CONTAINER --- */
align-items: center; /* Center content vertically */
margin: 20px;
/* --- SIZE CONTAINER --- */
height: 100px;
width: fit-content;
padding: 10px 20px; /* Adjust padding as needed */
/* --- STYLE CONTAINER --- */
background: linear-gradient(to right, white, rgb(245, 245, 245), rgb(227, 227, 227)); /* Gradient from white to gray */
transform: skewX(-20deg); /* Skew the banner to create a triangular side */
box-shadow: 0px 3px 8px rgba(0, 0, 0, 0.4);
/* --- FORMAT CHILD ITEMS (logo, league name, flag) --- */
display: flex; /* Enable flexbox layout */
flex-direction: row; /* Arrange child elements horizontally */
}
/*
===========================
LEAGUE INFORMATION CHILD ITEMS
===========================
*/
/* Adds Red Diagonal Strip at the end of the #league-information-container */
#league-information-container::after
{
content: '';
position: absolute;
top: 0;
right: 0;
bottom: 0;
width: 8px; /* Width of the red strip */
background-color: red; /* Red color */
}
/* Styling for League Logo in League Information Header */
#league-logo
{
margin: 0px 30px;
transform: skewX(20deg); /* Skew the banner to create a triangular side */
height: 80%;
}
/* Styling for League Title in League Information Header */
#league-title
{
transform: skewX(20deg); /* Skew the banner to create a triangular side */
margin-right: 20px;
}
/* Styling for FLag in League Information Header */
#league-flag
{
transform: skewX(20deg); /* Skew the banner to create a triangular side */
height: 20px;
margin-right: 200px;
}
/*
=============================================
CARDS IN PAGE BODY
=============================================
*/
#table-and-top-scorers-containers {
display: flex;
flex-direction: row;
}
/* Styling for Standings and Top Scorers Cards */
#table-stats-container, #top-scorers-stats-container
{
/* --- POSITION CONTAINER --- */
margin: 0 10px;
margin-bottom: 20px;
/* --- SIZE CONTAINER --- */
padding: 15px;
/* --- STYLE CONTAINER --- */
background: linear-gradient(to top, rgb(216, 216, 216), rgb(236, 236, 236), rgb(241, 240, 240));
border: 1px solid gray;
box-shadow: 0px 3px 8px rgba(0, 0, 0, 0.5);
}
/*
==============================================================
HOVER STYLES
==============================================================
*/
/* Hover Styling for Standings and Top Scorers Cards */
#table-stats-container:hover, #top-scorers-stats-container:hover
{
transform: scale(1.01); /* Scale the row by 1.1 on hover */
box-shadow: 0px 3px 10px rgba(0, 0, 0, 0.3);
}
/*
==============================================================
DYNAMIC PAGE WIDTH STYLES
==============================================================
*/
/* Width of Screen is Less Than 950px */
@media (max-width: 1230px)
{
#table-and-top-scorers-containers {
display: flex;
flex-direction: column;
}
}

View File

@@ -0,0 +1,130 @@
/*
=================================
TABLE ADN HEADER CONTAINER
=================================
*/
/* Container for table and header */
#league-table-container
{
width: 60%;
justify-content: center;
align-items: center;
margin-right: 30px;
transition: transform 0.3s ease; /* Add smooth transition effect */
}
/*
=================================
TABLE CONTAINER
=================================
*/
/* Container for Table */
#table-stats-container
{
width: 100%;
}
/* Table that holds all the standing information */
#standings-table
{
width: 100%;
padding: 15px;
/* Table Header Styling */
th
{
border-bottom: 3px solid red; /* Add red bottom border */
}
/* Data in Row Style */
td
{
padding: 5px;
}
/* Every Odd Row in Table Style */
tbody tr:nth-child(odd)
{
background-color: #d2d2d2; /* Light gray for odd rows */
}
}
/*
===========================
TABLE COLUMNS STYLE
===========================
*/
/* Club Logo Column in Table Style */
#club-logo-column {
width: 25px;
/* Club Logo Style */
#table-club-logo
{
width: 25px;
margin-right: 5px;
cursor: pointer;
}
}
/* Club Name Column in Table Style */
#club-name-column
{
font-weight: 500;
cursor: pointer;
}
/* Points Column in Table Style */
#points-column
{
font-weight: bolder;
}
/*
==============================================================
HOVER STYLES
==============================================================
*/
/* Add hover effect to table rows */
#standings-table tbody tr:hover
{
/* Create border around row on hover */
border: 1px solid lightgray;
border-radius: 10px;
/* Make club logo larger on hover */
#table-club-logo
{
width: 32px;
}
/* Undeline club name on hover */
#club-name-column
{
text-decoration: underline; /* Add underline effect */
}
}
/*
==============================================================
DYNAMIC PAGE WIDTH STYLES
==============================================================
*/
/* Stlye for Screens Smaller than 1230px */
@media (max-width: 1230px)
{
#league-table-container
{
align-items: center;
width: 75%;
min-width: 580px;
}
}

View File

@@ -0,0 +1,96 @@
/*
=================================
TABLE ADN HEADER CONTAINER
=================================
*/
#top-scorers-container
{
width: 40%;
}
#top-scorers-stats-container {
/* Table Header Styling */
th
{
border-bottom: 3px solid red; /* Add red bottom border */
}
tr
{
padding: 3px;
}
/* Data in Row Style */
td
{
padding: 5px;
}
}
/*
===========================
TABLE COLUMNS STYLE
===========================
*/
#goals-column
{
text-align: center;
font-size: 20px;
font-weight: bolder;
}
#top-scorers-logo
{
width: 25px;
margin: 0 15px;
cursor: pointer;
}
#player-name-column
{
font-size: 14px;
font-weight: bold;
padding-right: 15px;
}
#club-name-column
{
padding-right: 15px;
}
/*
==============================================================
HOVER STYLES
==============================================================
*/
#top-scorers-stats-container tbody tr:hover
{
border: 1px solid lightgray;
#top-scorers-logo {
width: 32px;
}
#club-name-column {
text-decoration: underline;
}
}
/*
==============================================================
DYNAMIC PAGE WIDTH STYLES
==============================================================
*/
@media (max-width: 1230px) {
#top-scorers-container {
align-items: center;
width: 75%;
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 10 MiB

View File

@@ -1,7 +0,0 @@
function redirectToLeaguePage(leagueName) {
// Append the league name to the URL
var url = "/league/" + leagueName.toLowerCase().replace(/\s+/g, '-');
// Redirect to the league page
window.location.href = url;
}

View File

@@ -0,0 +1,29 @@
document.addEventListener("DOMContentLoaded", function() {
var goalDifferenceCells = document.querySelectorAll("#goal-difference-column"); // Selecting the cells in the goal_difference column
goalDifferenceCells.forEach(function(cell) {
var goalDifference = parseInt(cell.textContent);
var color;
if (goalDifference < 0)
{
// Gradually darken the text color for negative goal differences
var darkenFactor = Math.ceil(goalDifference / -10); // Calculate the darken factor
var shade = Math.max(0, 255 - darkenFactor * 25); // Calculate the shade of red
color = "rgb(" + shade + ", 0, 0)"; // Create the color value
}
else if (goalDifference > 0)
{
// Gradually darken the text color for positive goal differences
var darkenFactor = Math.floor(goalDifference / 10); // Calculate the darken factor
var shade = Math.max(0, 155 - darkenFactor * 15); // Adjusted the starting point to make greens darker
color = "rgb(0, " + shade + ", 0)"; // Create the color value
}
else
{
color = "inherit"; // If goal difference is 0, leave text color unchanged
}
cell.style.color = color; // Apply the calculated color
});
});

View File

@@ -0,0 +1,75 @@
const axios = require('axios');
// Middleware function to fetch clubs data
const fetchClubsData = async (req, res, next) => {
try {
// Extract club ID from the URL
const clubID = req.params.clubID;
// Make GET request to the API endpoint using the club ID
const response = await axios.get(`http://api.football-data.org/v4/teams/${clubID}/?offset=&limit=`, {
headers: {
'X-Auth-Token': '0aa1ed31245d4a36b1ef5a79150324b3', // Add your API key here
},
});
// Extract relevant data from the API response
const clubData = response.data;
// Attach the data to res.locals
res.locals.club = {
area: {
id: clubData.area.id,
name: clubData.area.name,
code: clubData.area.code,
club_flag: clubData.area.flag,
},
club_id: clubData.id,
name: clubData.name,
shortName: clubData.shortName,
tla: clubData.tla,
crest: clubData.crest,
address: clubData.address,
website: clubData.website,
founded: clubData.founded,
clubColors: clubData.clubColors,
venue: clubData.venue,
runningCompetitions: clubData.runningCompetitions.map(competition => ({
id: competition.id,
name: competition.name,
code: competition.code,
type: competition.type,
emblem: competition.emblem
})),
coach: {
id: clubData.coach.id,
firstName: clubData.coach.firstName,
lastName: clubData.coach.lastName,
name: clubData.coach.name,
dateOfBirth: clubData.coach.dateOfBirth,
nationality: clubData.coach.nationality,
contract: {
start: clubData.coach.contract.start,
until: clubData.coach.contract.until
}
},
squad: clubData.squad.map(player => ({
id: player.id,
name: player.name,
position: player.position,
dateOfBirth: player.dateOfBirth,
nationality: player.nationality
})),
staff: clubData.staff,
lastUpdated: clubData.lastUpdated
};
next();
} catch (error) {
console.error('Error fetching clubs data:', error);
res.locals.club = null; // Set to null if there's an error
next(); // Call next middleware or route handler
}
};
module.exports = fetchClubsData;

View File

@@ -0,0 +1,44 @@
const axios = require('axios');
// Middleware function to fetch leagues data
const fetchLeagueScorerData = async (req, res, next) => {
try {
// Extract league ID from the URL
const leagueID = req.params.leagueID;
// Make GET request to the API endpoint using the league ID
const response = await axios.get(`http://api.football-data.org/v4/competitions/${leagueID}/scorers?season&limit=20`, {
headers: {
'X-Auth-Token': '0aa1ed31245d4a36b1ef5a79150324b3', // Add your API key here
},
});
// Extract relevant data from the API response
const scorerData = response.data;
// Attach the data to res.locals
res.locals.topScorers = {
scorers: scorerData.scorers.map(player => ({
player: {
player_id: player.player.id,
player_name: player.player.name,
},
team: {
team_id: player.player.id,
team_name: player.team.name,
team_crest: player.team.crest,
},
games_played: player.playedMatches,
goals: player.goals,
}))
};
next();
} catch (error) {
console.error('Error fetching leagues data:', error);
res.locals.topScorers = null; // Set to null if there's an error
next(); // Call next middleware or route handler
}
};
module.exports = fetchLeagueScorerData;

View File

@@ -0,0 +1,52 @@
const axios = require('axios');
// Middleware function to fetch leagues data
const fetchLeaguesData = async (req, res, next) => {
try {
// Extract league ID from the URL
const leagueID = req.params.leagueID;
// Make GET request to the API endpoint using the league ID
const response = await axios.get(`http://api.football-data.org/v4/competitions/${leagueID}/standings?season`, {
headers: {
'X-Auth-Token': '0aa1ed31245d4a36b1ef5a79150324b3', // Add your API key here
},
});
// Extract relevant data from the API response
const leagueData = response.data;
// Attach the data to res.locals
res.locals.league = {
area: {
league_flag: leagueData.area.flag,
},
competition: {
league_id: leagueData.competition.id,
league_name: leagueData.competition.name,
league_emblem: leagueData.competition.emblem
},
standings: leagueData.standings[0].table.map(team => ({
table: {
league_position: team.position,
team_id: team.team.id,
team_name: team.team.name,
team_crest: team.team.crest
},
games_played: team.playedGames,
wins: team.won,
losses: team.lost,
draws: team.draw,
goal_difference: team.goalDifference,
points: team.points
}))
};
next();
} catch (error) {
console.error('Error fetching leagues data:', error);
res.locals.league = null; // Set to null if there's an error
next(); // Call next middleware or route handler
}
};
module.exports = fetchLeaguesData;

View File

@@ -0,0 +1,44 @@
const axios = require('axios');
// Middleware function to fetch leagues data
const fetchLeagueScorerData = async (req, res, next) => {
try {
// Extract league ID from the URL
const leagueID = req.params.leagueID;
// Make GET request to the API endpoint using the league ID
const response = await axios.get(`http://api.football-data.org/v4/competitions/${leagueID}/scorers?season&limit=20`, {
headers: {
'X-Auth-Token': '0aa1ed31245d4a36b1ef5a79150324b3', // Add your API key here
},
});
// Extract relevant data from the API response
const scorerData = response.data;
// Attach the data to res.locals
res.locals.topScorers = {
scorers: scorerData.scorers.map(player => ({
player: {
player_id: player.player.id,
player_name: player.player.name,
},
team: {
team_id: player.team.id,
team_name: player.team.name,
team_crest: player.team.crest,
},
games_played: player.playedMatches,
goals: player.goals,
}))
};
next();
} catch (error) {
console.error('Error fetching leagues data:', error);
res.locals.topScorers = null; // Set to null if there's an error
next(); // Call next middleware or route handler
}
};
module.exports = fetchLeagueScorerData;

View File

@@ -9,6 +9,9 @@ const convert_time = (req, res, next) => {
if (match.minute === "FINISHED") {
match.minute = "FT";
}
else if (match.minute === "IN_PLAY") {
match.minute = "IP"
}
else if (match.minute === "TIMED") {
match.minute = "TM";
}

View File

@@ -0,0 +1,18 @@
const express = require('express');
const app = express();
// generate-league-routes.js
// Define a function to generate league routes
module.exports = function generateClubRoutes(app) {
// Define a route to handle requests to "/league/:leagueName"
app.get('/club/:clubID', (req, res) => {
// Extract the league name from the URL parameters
const clubID = req.params.clubID;
// Render the league page template using Handlebars
res.render('pages/club-page', { clubID: clubID });
});
};

View File

@@ -0,0 +1,17 @@
// Add click event listener to club logos
document.querySelectorAll('#table-club-logo, #club-name, #top-scorers-logo, #club-name-column').forEach(element => {
element.addEventListener('click', (event) => {
// Get the club ID from the clicked club logo's clubID attribute
const clubId = element.getAttribute('clubID');
redirectToClubPage(clubId);
});
});
// Function to redirect to the club page
function redirectToClubPage(clubID) {
// Append the club ID to the URL
var url = "/club/" + clubID;
// Redirect to the club page
window.location.href = url;
}

View File

@@ -6,12 +6,12 @@ const app = express();
// Define a function to generate league routes
module.exports = function generateLeagueRoutes(app) {
// Define a route to handle requests to "/league/:leagueName"
app.get('/league/:leagueName', (req, res) => {
app.get('/league/:leagueID', (req, res) => {
// Extract the league name from the URL parameters
const leagueName = req.params.leagueName;
const leagueID = req.params.leagueID;
// Render the league page template using Handlebars
res.render('pages/league-page', { leagueName: leagueName });
res.render('pages/leagues-page', { leagueID: leagueID });
});
};

View File

@@ -0,0 +1,21 @@
const axios = require('axios');
const fetchTeamNames = async (selectedLeague) => {
try {
const response = await axios({
url: `http://api.football-data.org/v4/competitions/${selectedLeague}/teams`,
method: 'GET',
headers: {
'X-Auth-Token': '0aa1ed31245d4a36b1ef5a79150324b3',
},
});
const teams = response.data.teams.map(team => team.name);
return teams;
} catch (error) {
console.error('Error fetching teams data:', error);
return [];
}
};
module.exports = fetchTeamNames;

View File

@@ -0,0 +1,7 @@
function redirectToLeaguePage(leagueID) {
// Append the league name to the URL
var url = "/league/" + leagueID;
// Redirect to the league page
window.location.href = url;
}