Skip to content

Commit

Permalink
Add files via upload
Browse files Browse the repository at this point in the history
  • Loading branch information
StMannyAkinso authored Oct 2, 2024
1 parent 58fb0d7 commit 716dcf0
Show file tree
Hide file tree
Showing 16 changed files with 906 additions and 43 deletions.
56 changes: 44 additions & 12 deletions Scripts/Ambitions/ui.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,27 +7,59 @@
* @param {Array<Object>} categories - List of categories associated with the ambition.
*/
export function renderAmbitionDetails(ambition, container, categories) {
const currentId = Number(ambition["Ambition-ID"]);
const nextAmbition = Math.min(currentId + 1, 4);
const prevAmbition = Math.max(currentId - 1, 1);
if (!ambition) {
container.innerHTML = "<p>Ambition not found.</p>";
container.innerHTML = `<p class="text-red-500 font-semibold">Ambition not found.</p>`;
return;
}

// Generate the categories HTML with Tailwind styling
const categoriesHtml = categories
.map(
(category) =>
`<li><a href="categories.html?id=${encodeURIComponent(
category["Category-ID"]
)}">${category["Category-Name"]}</a></li>`
`<li class="mb-2">
<a href="categories.html?id=${encodeURIComponent(
category["Category-ID"]
)}"
class="text-blue-900 hover:text-yellow-500 transition-colors duration-300">
<img src="Images/Categories/${
category["Category-Name"]
}.png" class="icon" alt="">
<h4>${category["Category-Name"]}</h4>
</a>
</li>`
)
.join("");

// Populate the container with the ambition details using Tailwind styling
container.innerHTML = `
<h1>${ambition["Ambition-Name"]}</h1>
<p>${ambition["Intro-Text"]}</p>
<img src="${ambition["Ambition-Intro-Image"]}" alt="${ambition["Ambition-Name"]} Image">
<h2>Categories</h2>
<ul>
${categoriesHtml}
</ul>
`;
<h1 class="text-4xl font-bold text-gray-800 mb-4">
${ambition["Ambition-Name"]}
</h1>
<div class="flex py-8 px-6 bg-gray-50 rounded-lg shadow-lg">
<div class="max-50">
<p class="text-lg text-gray-600 mb-6 px-6">
${ambition["Intro-Text"]}
</p>
<h3 class="text-2xl font-semibold mb-4">Categories</h2>
<ul class="list-disc list-inside">
${categoriesHtml}
</ul>
<div class="ambition-nav-buttons">
<a href="/ambitions.html?id=${prevAmbition}"><button>Previous Ambition</button></a>
<a href="/ambitions.html?id=${nextAmbition}"><button>Next Ambition</button></a>
</div>
</div>
<div class="flex centred">
<img src="Images/Ambition Introductions/${ambition["Ambition-ID"]}.png"
alt="${ambition["Ambition-Name"]} Image"
class="w-full h-auto rounded-lg shadow-md mb-6">
</div>
</div>
`;
}
2 changes: 1 addition & 1 deletion Scripts/Categories/data.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,9 @@ export async function getCategoryById(categoryId) {
name: item["Category-Name"],
ambitionId: item["Ambition-ID"],
introText: item["Category-Intro-Text"],
takeaways: item["Category-Takeaways"],
summary1: item["Category-Summary-1"],
summary2: item["Category-Summary-2"],
summary3: item["Category-Summary-3"],
}))
.find((category) => category.id === categoryId);
}
Expand Down
69 changes: 53 additions & 16 deletions Scripts/Categories/ui.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,31 +7,68 @@
* @param {Array<Object>} charts - List of charts associated with the category.
*/
export function renderCategoryDetails(category, container, charts) {
const currentId = Number(category.id);
const nextCategory = Math.min(currentId + 1, 11); // Ensures nextCategory does not exceed CategoryID 11
const prevCategory = Math.max(currentId - 1, 1);

if (!category) {
container.innerHTML = "<p>Category not found.</p>";
container.innerHTML = "<p class='text-red-500'>Category not found.</p>";
return;
}

const chartsHtml = charts
.map(
(chart) =>
`<li><a href="charts.html?id=${encodeURIComponent(chart.id)}">${
chart.name
}</a></li>`
`<li class="ml-4 text-sm">
<a href="charts.html?id=${encodeURIComponent(chart.id)}"
class="text-blue-600 hover:text-blue-800">
${chart.name}
</a>
</li>`
)
.join("");

container.innerHTML = `
<h1>${category.name}</h1>
<p>${category.introText}</p>
<h2>Charts</h2>
<ul>
${chartsHtml}
</ul>
<h3>Takeaways</h3>
<p>${category.takeaways}</p>
<h3>Summary</h3>
<p>${category.summary1}</p>
<p>${category.summary2}</p>
`;
<h1 class="text-3xl font-bold text-gray-800 mb-4">${category.name}<img src="Images/Categories/${category.name}.png" class="icon inline-block ml-2" alt=""></h1>
<div class="flex flex-col lg:flex-row gap-8 mb-8">
<div class="flex-1 p-6 bg-white shadow-lg rounded-lg">
<h3 class="text-2xl font-semibold mb-2">Introduction to ${category.name}</h3>
<p class="text-sm text-gray-700">${category.introText}</p>
</div>
<div class="flex-1 p-6 bg-white shadow-lg rounded-lg">
<h3 class="text-2xl font-semibold mb-2">Charts</h3>
<ul class="list-disc list-inside text-gray-600">
${chartsHtml}
</ul>
</div>
</div>
<h3 class="text-2xl font-semibold mb-4">${category.name} Summary</h3>
<div class="grid grid-cols-1 lg:grid-cols-3 gap-4 mb-8">
<div class="p-6 bg-white shadow-lg rounded-lg">
<p class="text-gray-700">${category.summary1}</p>
</div>
<div class="p-6 bg-white shadow-lg rounded-lg">
<p class="text-gray-700">${category.summary2}</p>
</div>
<div class="p-6 bg-white shadow-lg rounded-lg">
<p class="text-gray-700">${category.summary3}</p>
</div>
</div>
<div class="flex justify-between">
<a href="/categories.html?id=${prevCategory}">
<button class="">
Previous Category
</button>
</a>
<a href="/categories.html?id=${nextCategory}">
<button class="">
Next Category
</button>
</a>
</div>
`;
}
13 changes: 13 additions & 0 deletions Scripts/Charts/data.js
Original file line number Diff line number Diff line change
Expand Up @@ -20,3 +20,16 @@ export async function fetchChartMetadata(chartId) {
export async function fetchChartData(filePath) {
return await fetchJSON(`Data/Charts-JSON/${filePath}`);
}

/**
* Fetch GeoJSON data from the specified path.
* @param {string} geojsonPath - The path to the GeoJSON file.
* @returns {Promise<Object>} - The GeoJSON data.
*/
export async function fetchGeoJSONData(geojsonPath) {
const response = await fetch(geojsonPath);
if (!response.ok) {
throw new Error(`Failed to fetch GeoJSON data from ${geojsonPath}`);
}
return await response.json();
}
2 changes: 2 additions & 0 deletions Scripts/Charts/index.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
// Scripts/Charts/data.js

import { fetchChartMetadata, fetchChartData } from "./data.js";
import { updateChartUI, showError } from "./ui.js";
import { renderBarChart } from "../Renderers/barChart.js";
Expand Down
95 changes: 93 additions & 2 deletions Scripts/Charts/ui.js
Original file line number Diff line number Diff line change
@@ -1,26 +1,68 @@
import { getCategoryById, getChartsByCategoryId } from "../Categories/data.js";
import { renderMap } from "../Renderers/renderMap.js";
import { renderMapBar } from "../Renderers/renderMapBar.js";
import { renderMapLine } from "../Renderers/renderMapLine.js";

/**
* Update the UI with the chart metadata.
* Update the UI with the chart metadata and display category.
* @param {Object} chartMetadata - The metadata for the chart.
*/
export function updateChartUI(chartMetadata) {
export async function updateChartUI(chartMetadata) {
const chartContainer = document.querySelector(".chart-container");
const chartTitle = document.querySelector(".chart-container h1");
const mapTitle = document.querySelector(".map-container h1");
const tableCommentary = document.getElementById("table-commentary");
const pageCommentary = document.getElementById("page-commentary");
const wardMapButton = document.getElementById("ward-map-button");
const chartButton = document.getElementById("chart-button");
const previousButton = document.getElementById("previous-chart");
const nextButton = document.getElementById("next-chart");
const commentaryContainer = document.getElementById("commentary");
const mapContainer = document.querySelector(".map-container");
const wardChartContainer = document.querySelector(".ward-chart");
const backToChartButton = document.getElementById("back-to-chart-button");
const mapSvgContainer = document.getElementById("map-container-svg"); // Container for the ward map
const categoryContainer = document.getElementById("category-container"); // Assuming a container to display the category

if (chartMetadata) {
// Update chart title and page title
const titleText = chartMetadata["Chart-Name"];
chartTitle.textContent = titleText;
mapTitle.textContent = titleText;
document.title = `Chart | ${chartMetadata["Chart-Name"]}`; // Set the HTML page title

// Update commentaries
tableCommentary.textContent = chartMetadata["Table Commentary"];
pageCommentary.textContent = chartMetadata["Page Commentary"];

// Fetch and display the category name
const categoryId = chartMetadata["Category-ID"]; // Assuming category ID is part of the chart metadata
if (categoryId) {
try {
const categoryData = await getCategoryById(categoryId);
if (categoryData) {
// Create the anchor element
const categoryLink = document.createElement("a");
categoryLink.href = `/categories.html?id=${categoryId}`; // URL for the category page
categoryLink.style.textDecoration = "none"; // Optional: remove underline for the link

// Create the button element
const categoryButton = document.createElement("button");
categoryButton.textContent = categoryData.name; // Set the button text to the category name
categoryButton.style.cursor = "pointer"; // Optional: make the button look clickable

// Append the button inside the anchor
categoryLink.appendChild(categoryButton);

// Clear the existing content in the category container and append the link
categoryContainer.innerHTML = "";
categoryContainer.appendChild(categoryLink);
}
} catch (error) {
console.error("Error fetching category data:", error);
}
}

// Update map button visibility
if (chartMetadata["Map-Type"] !== "N/A") {
wardMapButton.style.display = "inline-block";
Expand Down Expand Up @@ -57,6 +99,55 @@ export function updateChartUI(chartMetadata) {
if (nextButton) {
nextButton.href = `/charts.html?id=${nextId}`;
}

// Inside the wardMapButton event listener
wardMapButton.addEventListener("click", async () => {
// Hide chart and commentary containers
chartContainer.style.display = "none";
commentaryContainer.style.display = "none";
// Show the map container
mapContainer.style.display = "block";

// Step 1: Get the file path for the ward map
const geoJsonFilePath = "Data/Maps/lambeth-ward-map.geojson"; // Adjust this path if necessary

// Step 2: Get the file path for the ward chart data
const filePath = chartMetadata["File-Path"];
const fullPath = `Data/Charts-JSON/${filePath}`;

try {
// Fetch the ward chart data from the JSON file
const response = await fetch(fullPath);
const chartData = await response.json();

// Step 3: Check the Map-Type and render the ward map using renderMap
const mapType = chartMetadata["Map-Type"];
renderMap(mapSvgContainer.id, geoJsonFilePath, mapType, chartData); // Call renderMap to display the map

// Clear the previous chart before rendering a new one
const wardChartContainerId = "ward-chart"; // Assuming this is the container ID
d3.select(`#${wardChartContainerId}`).html("");

if (mapType === "bar") {
renderMapBar(wardChartContainerId, chartData);
} else if (mapType === "line") {
renderMapLine(wardChartContainerId, chartData);
} else {
console.error("Unknown Map-Type:", mapType);
}
} catch (error) {
console.error("Error loading chart data:", error);
}
});

// Add event listener to the Back to Chart button
chartButton.addEventListener("click", () => {
// Hide the map container
mapContainer.style.display = "none";
// Show chart and commentary containers
chartContainer.style.display = "block";
commentaryContainer.style.display = "block";
});
} else {
// Handle chart not found
chartTitle.textContent = "Chart Not Found";
Expand Down
30 changes: 26 additions & 4 deletions Scripts/Renderers/groupedBar.js
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,20 @@ export function renderGroupedBarChart(data, container, chartMetadata) {
// Add Y axis label
addYAxisLabel(svg, yLabel, margin, height);

// Add horizontal grid lines
svg
.append("g")
.attr("class", "grid")
.call(
d3
.axisLeft(yScale)
.tickSize(-width) // Extend grid lines across the chart
.tickFormat("") // Hide tick labels
)
.selectAll(".tick line")
.attr("stroke", "#ddd") // Set grid line color
.attr("stroke-width", 1); // Set grid line width

// Color scale
const colorScale = d3.scaleOrdinal(d3.schemeCategory10);

Expand All @@ -70,19 +84,19 @@ export function renderGroupedBarChart(data, container, chartMetadata) {
.attr("class", "bar-group")
.attr("transform", (d) => `translate(${xScale(d.key)}, 0)`);

// Add the bars with interactive effects
// Add the bars with interactive effects and animation
barGroups
.selectAll(".bar")
.data((d) => d.values)
.enter()
.append("rect")
.attr("class", "bar")
.attr("x", (d, i) => i * (xScale.bandwidth() / mainLocations.length))
.attr("y", (d) => yScale(+d.value))
.attr("y", height) // Start from the bottom
.attr("width", xScale.bandwidth() / mainLocations.length)
.attr("height", (d) => height - yScale(+d.value))
.attr("height", 0) // Initial height of 0
.attr("fill", (d) => colorScale(d.location))
.style("cursor", "pointer") // Set cursor to pointer
.style("cursor", "pointer")
.on("mouseover", function (event, d) {
d3.select(this).attr("fill", d3.rgb(colorScale(d.location)).brighter(1)); // Darken color on hover
})
Expand All @@ -92,6 +106,14 @@ export function renderGroupedBarChart(data, container, chartMetadata) {
.append("title")
.text((d) => `${d.location}: ${d.value}%`);

// Animate the bars to grow from 0 height to their actual value
svg
.selectAll(".bar")
.transition() // Start the transition
.duration(1000) // 1 second duration
.attr("y", (d) => yScale(+d.value)) // Final y position
.attr("height", (d) => height - yScale(+d.value)); // Final height based on data

// Add a legend
const legend = svg
.selectAll(".legend")
Expand Down
Loading

0 comments on commit 716dcf0

Please sign in to comment.