diff --git a/src/app/whiskyjournal/page.tsx b/src/app/whiskyjournal/page.tsx
index c13254b..12b1102 100644
--- a/src/app/whiskyjournal/page.tsx
+++ b/src/app/whiskyjournal/page.tsx
@@ -26,17 +26,6 @@ export default function WhiskyJournalPage() {
-
- Cam's whisky journal
- }
- >
- Add new whisky
-
-
diff --git a/src/components/irishbingo.tsx b/src/components/irishbingo.tsx
index 2bbe5b4..f6959e8 100644
--- a/src/components/irishbingo.tsx
+++ b/src/components/irishbingo.tsx
@@ -96,8 +96,7 @@ export default function IrishBingo() {
};
const [modalCardOpened, setModalCardOpened] = useState(false);
- const [modalInstructionsOpened, setModalIntstructionsOpened] =
- useState(false);
+ const [modalInstructionsOpened, setModalInstructionsOpened] = useState(false);
return (
@@ -114,7 +113,7 @@ export default function IrishBingo() {
variant="subtle"
size="lg"
aria-label="Open game instructions modal"
- onClick={() => setModalIntstructionsOpened(true)}
+ onClick={() => setModalInstructionsOpened(true)}
>
@@ -124,7 +123,7 @@ export default function IrishBingo() {
setModalIntstructionsOpened(false)}
+ onClose={() => setModalInstructionsOpened(false)}
role="dialog"
aria-modal="true"
aria-labelledby="ib_instructions"
@@ -201,7 +200,7 @@ export default function IrishBingo() {
diff --git a/src/components/whiskyjournal.tsx b/src/components/whiskyjournal.tsx
index b7ea93f..11993ba 100644
--- a/src/components/whiskyjournal.tsx
+++ b/src/components/whiskyjournal.tsx
@@ -9,11 +9,22 @@ import {
Accordion,
TextInput,
ActionIcon,
+ Title,
+ Tooltip,
+ Modal,
+ Container,
+ Center,
} from "@mantine/core";
-import { IconX } from "@tabler/icons-react";
+import {
+ IconX,
+ IconDownload,
+ IconInfoCircle,
+ IconPlus,
+} from "@tabler/icons-react";
import { WhiskyCard } from "@/components/whiskycard";
import BackToTop from "@/components/backtotop";
import { readWhiskyJournal } from "@/services/whiskyjournal";
+import { WhiskyPricingScale, WhiskyRatingScale } from "./whiskyscoringscales";
export interface Whisky {
last_edited: Date;
@@ -49,6 +60,7 @@ export default function WhiskyJournal() {
fetchWhiskies();
}, []);
+
const whiskyData = whiskies;
const [grainFilter, setGrainFilter] = useState(null);
@@ -137,12 +149,132 @@ export default function WhiskyJournal() {
{ value: "ageDesc", label: "Age Descending" },
];
+ const [modalScalesOpened, setModalScalesOpened] = useState(false);
+
if (loading) {
return Fetching journal...;
}
+ const exportToCSV = () => {
+ const headers = [
+ "Last Edited",
+ "Whisky ID",
+ "Name",
+ "Distillery",
+ "Country/Region",
+ "Age",
+ "Grain",
+ "ABV",
+ "Rating",
+ "Price",
+ "Notes",
+ ];
+ const rows = searchedWhiskyData.map((whisky) => [
+ `"${whisky.last_edited.toISOString()}"`,
+ `"${whisky.whisky_id}"`,
+ `"${whisky.name}"`,
+ `"${whisky.distillery}"`,
+ `"${whisky.country_region}"`,
+ `"${whisky.age}"`,
+ `"${whisky.grain}"`,
+ `"${whisky.abv}"`,
+ `"${whisky.rating}"`,
+ `"${whisky.price}"`,
+ `"${whisky.notes}"`,
+ ]);
+
+ const csvContent =
+ "data:text/csv;charset=utf-8," +
+ [headers, ...rows].map((e) => e.join(",")).join("\n");
+
+ const encodedUri = encodeURI(csvContent);
+ const link = document.createElement("a");
+ link.setAttribute("href", encodedUri);
+ const today = new Date().toISOString().split("T")[0];
+ link.setAttribute("download", `whisky_journal_${today}.csv`);
+ document.body.appendChild(link);
+ link.click();
+ document.body.removeChild(link);
+ };
+
return (
<>
+
+
+ Cam's whisky journal
+
+ setModalScalesOpened(true)}
+ >
+
+
+
+
+ }
+ >
+ Add new whisky
+
+
+
+ setModalScalesOpened(false)}
+ role="dialog"
+ aria-modal="true"
+ aria-labelledby="whisky_scales"
+ withCloseButton={false}
+ transitionProps={{
+ transition: "fade",
+ duration: 300,
+ timingFunction: "linear",
+ }}
+ overlayProps={{
+ backgroundOpacity: 0.75,
+ blur: 3,
+ }}
+ >
+
+
+ Whisky rating scales
+
+
+
+ Pricing scale
+
+
+
+
+
+ Rating scale
+
+
+
+
+
+
+
+
+
+
Sort and filter
@@ -210,25 +342,36 @@ export default function WhiskyJournal() {
- setSearchQuery("")}
- variant="default"
- aria-label="Clear search query"
- >
-
-
- )
- }
- />
+
+ setSearchQuery("")}
+ variant="default"
+ aria-label="Clear search query"
+ >
+
+
+ )
+ }
+ />
+
+ }
+ >
+ Download CSV
+
+
Showing {searchedWhiskyData.length} of {whiskyData.length} whiskies
diff --git a/src/components/whiskyjournaledit.tsx b/src/components/whiskyjournaledit.tsx
index 48fe5a2..8ad6fe6 100644
--- a/src/components/whiskyjournaledit.tsx
+++ b/src/components/whiskyjournaledit.tsx
@@ -11,7 +11,6 @@ import {
Stack,
Text,
Textarea,
- List,
Rating,
Select,
NumberInput,
@@ -22,6 +21,10 @@ import { deleteWhisky, updateWhisky } from "@/services/whiskyjournal";
import { Whisky } from "@/components/whiskycard";
import { useRouter } from "next/navigation";
import { IconTaxPound } from "@tabler/icons-react";
+import {
+ WhiskyPricingScale,
+ WhiskyRatingScale,
+} from "@/components/whiskyscoringscales";
export const WhiskyJournalEdit = ({ whiskyData }: { whiskyData: Whisky }) => {
const [modalOpened, setModalOpened] = useState(false);
@@ -156,6 +159,9 @@ export const WhiskyJournalEdit = ({ whiskyData }: { whiskyData: Whisky }) => {
Rate the whisky out of 5 *
+
+
+
@@ -163,11 +169,9 @@ export const WhiskyJournalEdit = ({ whiskyData }: { whiskyData: Whisky }) => {
How pricey is the whisky?
*
-
- Under £40 a bottle
- £40 - £85 a bottle
- Over £85 a bottle
-
+
+
+
{
export const WhiskyRatingScale = () => {
return (
- Would only drink again if paid
Unhappy about drinking again
Shrugs, can drink it
- Tasty, would order at a bar
- Would happily buy bottles of it
+ Solid, though perhaps unspectacular
+ Tasty, would choose to order at a bar
+ Exceptional, top tier
);
};
diff --git a/tests/public-database/01_whiskyjournal.spec.ts b/tests/public-database/01_whiskyjournal.spec.ts
index fd6ffc1..71963ac 100644
--- a/tests/public-database/01_whiskyjournal.spec.ts
+++ b/tests/public-database/01_whiskyjournal.spec.ts
@@ -57,3 +57,18 @@ test("Can search whiskies by name", async ({ page }) => {
/Johnnie Walker Black Label/,
);
});
+
+const fs = require("fs");
+test("Download CSV and check contents", async ({ page }) => {
+ await page.goto("/whiskyjournal");
+ const [download] = await Promise.all([
+ page.waitForEvent("download"),
+ page.getByRole("button", { name: "Download CSV" }).click(),
+ ]);
+
+ const path = await download.path();
+ const csv = fs.readFileSync(path, "utf-8");
+ const rows = csv.split("\n");
+
+ expect(rows.length).toBeGreaterThan(30);
+});