-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #1 from SamHillierDev/dev
Further development
- Loading branch information
Showing
7 changed files
with
324 additions
and
13 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,63 @@ | ||
<script setup lang="ts"> | ||
import { ref, computed } from "vue"; | ||
interface Game { | ||
product: string; | ||
} | ||
const props = defineProps<{ games: Game[] }>(); | ||
const emits = defineEmits<{ | ||
(event: "gameSelected", value: string): void; | ||
}>(); | ||
const uniqueSortedGames = computed(() => { | ||
const uniqueGames = Array.from( | ||
new Map(props.games.map((game) => [game.product, game])).values(), | ||
); | ||
return uniqueGames.sort((a, b) => a.product.localeCompare(b.product)); | ||
}); | ||
const selectedGame = ref(""); | ||
const handleSelection = (event: Event) => { | ||
selectedGame.value = (event.target as HTMLSelectElement).value; | ||
emits("gameSelected", selectedGame.value); | ||
}; | ||
const clearSelection = () => { | ||
selectedGame.value = ""; | ||
emits("gameSelected", ""); | ||
}; | ||
</script> | ||
|
||
<template> | ||
<div> | ||
<h2 class="mb-4 text-xl font-semibold">Select a Game</h2> | ||
<div class="flex items-center gap-2"> | ||
<select | ||
v-model="selectedGame" | ||
@change="handleSelection" | ||
class="w-full rounded border bg-blue-50 px-2 py-1 text-gray-900 dark:border-gray-600 dark:bg-slate-700 dark:text-gray-100" | ||
> | ||
<option value="" disabled class="text-gray-400 dark:text-gray-500"> | ||
Select a game | ||
</option> | ||
<option | ||
v-for="game in uniqueSortedGames" | ||
:key="game.product" | ||
:value="game.product" | ||
class="text-gray-900 dark:text-gray-100" | ||
> | ||
{{ game.product }} | ||
</option> | ||
</select> | ||
<button | ||
v-if="selectedGame" | ||
@click="clearSelection" | ||
class="cursor-pointer rounded bg-[#29377C] px-4 py-1 text-white transition hover:bg-[#4f5a99]" | ||
> | ||
Clear | ||
</button> | ||
</div> | ||
</div> | ||
</template> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,78 @@ | ||
<script setup lang="ts"> | ||
import { computed } from "vue"; | ||
import LineGraph from "./LineGraph.vue"; | ||
interface DataEntry { | ||
product: string; | ||
date: string; | ||
} | ||
const props = defineProps<{ | ||
data: DataEntry[]; | ||
selectedGame: string; | ||
}>(); | ||
const monthsOf2024 = [ | ||
{ id: "2024-01", label: "Jan 24" }, | ||
{ id: "2024-02", label: "Feb 24" }, | ||
{ id: "2024-03", label: "Mar 24" }, | ||
{ id: "2024-04", label: "Apr 24" }, | ||
{ id: "2024-05", label: "May 24" }, | ||
{ id: "2024-06", label: "Jun 24" }, | ||
{ id: "2024-07", label: "Jul 24" }, | ||
{ id: "2024-08", label: "Aug 24" }, | ||
{ id: "2024-09", label: "Sep 24" }, | ||
{ id: "2024-10", label: "Oct 24" }, | ||
{ id: "2024-11", label: "Nov 24" }, | ||
{ id: "2024-12", label: "Dec 24" }, | ||
]; | ||
const chartData = computed(() => { | ||
if (!props.selectedGame) { | ||
return { | ||
labels: monthsOf2024.map((m) => m.label), | ||
dataset: new Array(12).fill(0), | ||
}; | ||
} | ||
const filteredData = props.data.filter( | ||
(entry) => entry.product === props.selectedGame, | ||
); | ||
const mentionsByMonth = filteredData.reduce( | ||
(acc, entry) => { | ||
const month = new Date(entry.date).toISOString().slice(0, 7); | ||
if (monthsOf2024.some((m) => m.id === month)) { | ||
acc[month] = (acc[month] || 0) + 1; | ||
} | ||
return acc; | ||
}, | ||
{} as Record<string, number>, | ||
); | ||
const dataset = monthsOf2024.map((month) => mentionsByMonth[month.id] || 0); | ||
return { | ||
labels: monthsOf2024.map((m) => m.label), | ||
dataset, | ||
}; | ||
}); | ||
const chartTitle = computed( | ||
() => | ||
`Mentions in 2024${props.selectedGame ? ` - ${props.selectedGame}` : ""}`, | ||
); | ||
</script> | ||
|
||
<template> | ||
<div> | ||
<h2 class="mb-6 text-2xl font-semibold">{{ chartTitle }}</h2> | ||
<LineGraph | ||
:labels="chartData.labels" | ||
:dataset="chartData.dataset" | ||
:chartTitle="chartTitle" | ||
xAxisLabel="Month" | ||
yAxisLabel="Mentions" | ||
/> | ||
</div> | ||
</template> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,103 @@ | ||
<script setup lang="ts"> | ||
import { ref, watch, onMounted } from "vue"; | ||
import { | ||
Chart, | ||
LineController, | ||
LineElement, | ||
PointElement, | ||
LinearScale, | ||
Title, | ||
CategoryScale, | ||
Tooltip, | ||
Legend, | ||
} from "chart.js"; | ||
import type { ChartData, ChartConfiguration } from "chart.js"; | ||
Chart.register( | ||
LineController, | ||
LineElement, | ||
PointElement, | ||
LinearScale, | ||
Title, | ||
CategoryScale, | ||
Tooltip, | ||
Legend, | ||
); | ||
const props = defineProps<{ | ||
labels: string[]; | ||
dataset: number[]; | ||
chartTitle?: string; | ||
xAxisLabel?: string; | ||
yAxisLabel?: string; | ||
}>(); | ||
const chartCanvas = ref<HTMLCanvasElement | null>(null); | ||
let chartInstance: Chart<"line", number[], string> | null = null; | ||
const updateChart = () => { | ||
if (!chartCanvas.value) return; | ||
if (chartInstance) { | ||
chartInstance.destroy(); | ||
} | ||
const data: ChartData<"line", number[], string> = { | ||
labels: props.labels, | ||
datasets: [ | ||
{ | ||
label: "Mentions", | ||
data: props.dataset, | ||
borderColor: "#34479b", | ||
backgroundColor: "rgba(41, 55, 124, 0.5)", | ||
tension: 0.3, | ||
}, | ||
], | ||
}; | ||
const config: ChartConfiguration<"line", number[], string> = { | ||
type: "line", | ||
data, | ||
options: { | ||
responsive: true, | ||
maintainAspectRatio: false, | ||
plugins: { | ||
title: { | ||
display: true, | ||
text: props.chartTitle || "Line Chart", | ||
}, | ||
}, | ||
scales: { | ||
x: { | ||
title: { | ||
display: true, | ||
text: props.xAxisLabel || "X-Axis", | ||
}, | ||
}, | ||
y: { | ||
title: { | ||
display: true, | ||
text: props.yAxisLabel || "Y-Axis", | ||
}, | ||
beginAtZero: true, | ||
}, | ||
}, | ||
animation: { | ||
duration: 1000, | ||
easing: "easeInOutQuad", | ||
}, | ||
}, | ||
}; | ||
chartInstance = new Chart(chartCanvas.value, config); | ||
}; | ||
onMounted(updateChart); | ||
watch(() => [props.labels, props.dataset], updateChart); | ||
</script> | ||
|
||
<template> | ||
<div class="h-100 w-full"> | ||
<canvas ref="chartCanvas"></canvas> | ||
</div> | ||
</template> |
Oops, something went wrong.