diff --git a/package-lock.json b/package-lock.json
index 6b0ffb4..b2d5072 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -14,6 +14,7 @@
"@tauri-apps/api": "^2",
"@tauri-apps/plugin-opener": "^2",
"@tauri-apps/plugin-store": "^2.2.0",
+ "solid-icons": "^1.1.0",
"solid-js": "^1.9.3",
"vite-plugin-inline-css-modules": "^0.0.8"
},
@@ -1803,6 +1804,15 @@
"seroval": "^1.0"
}
},
+ "node_modules/solid-icons": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/solid-icons/-/solid-icons-1.1.0.tgz",
+ "integrity": "sha512-IesTfr/F1ElVwH2E1110s2RPXH4pujKfSs+koT8rwuTAdleO5s26lNSpqJV7D1+QHooJj18mcOiz2PIKs0ic+A==",
+ "license": "MIT",
+ "peerDependencies": {
+ "solid-js": "*"
+ }
+ },
"node_modules/solid-js": {
"version": "1.9.5",
"resolved": "https://registry.npmjs.org/solid-js/-/solid-js-1.9.5.tgz",
diff --git a/package.json b/package.json
index 5dd1a79..6dc922a 100644
--- a/package.json
+++ b/package.json
@@ -17,6 +17,7 @@
"@tauri-apps/api": "^2",
"@tauri-apps/plugin-opener": "^2",
"@tauri-apps/plugin-store": "^2.2.0",
+ "solid-icons": "^1.1.0",
"solid-js": "^1.9.3",
"vite-plugin-inline-css-modules": "^0.0.8"
},
diff --git a/src/App.css b/src/App.css
index c0c621b..7bee737 100644
--- a/src/App.css
+++ b/src/App.css
@@ -83,9 +83,12 @@
.puzzle-header {
display: flex;
- align-items: center;
+ align-items: baseline;
flex-direction: row;
- > h1 {
+ margin-bottom: 1em;
+ > h2 {
+ font-size: 2em;
+ line-height: 1;
flex-grow: 1;
text-align: left;
margin: 0;
@@ -96,6 +99,10 @@
display: flex;
flex-direction: row;
gap: calc(1 * var(--unit));
+ & button {
+ display: flex;
+ align-items: center;
+ }
}
.puzzle-row {
diff --git a/src/Dashboard.tsx b/src/Dashboard.tsx
index 817e21c..0ab0cca 100644
--- a/src/Dashboard.tsx
+++ b/src/Dashboard.tsx
@@ -1,36 +1,76 @@
-import { For } from "solid-js";
+import { For, Show, createMemo } from "solid-js";
import useAppModel from "./useAppModel";
-import { A } from "@solidjs/router";
import { css } from 'vite-plugin-inline-css-modules'
const styles = css`
- calendar: {
- display: "grid",
- gridTemplateColumns: "repeat(7, 1fr)",
- },
- entry: (solved: boolean) => {
- return {
- borderRadius: "50%",
- backgroundColor: solved ? "green" : "gray",
+ .calendar {
+ column-width: 7em;
+ column-gap: 0.3em;
+ }
+ .entry {
+ width: 0.8em;
+ margin: 0.1em;
+ display: inline-block;
+ height: 0.8em;
+ border-radius: 25%;
+ background-color: gray;
+ }
+ .entryBlank {
+ background: none;
+ }
+ .nextPuzzle {
+ display: flex;
+ justify-content: center;
+ width: 100%;
+ font-size: 3em;
+ line-height: 1;
+ padding: 1em;
+ color: var(--color-foreground);
+ background-color: var(--group-green);
+ margin-bottom: 1em;
+ &:hover, &:focus-visible, &:active {
+ color: var(--color-foreground);
+ outline: none;
+ background-color: var(--group-yellow);
}
- },
+ }
`
+const colorStrings = [
+ 'var(--group-purple)',
+ 'var(--group-blue)',
+ 'var(--group-green)',
+ 'var(--group-yellow)',
+]
+
export default function Dashboard() {
const { connections, store } = useAppModel();
+ const nextUnsolvedId = createMemo(() => {
+ return connections.find(x => store.solutions[x.id] === undefined)?.id
+ })
return (
-
-
- {(item) => {
- const isSolved = store.solutions[item.id] !== undefined;
- return (
-
- );
- }}
-
+
);
}
diff --git a/src/FitText.tsx b/src/FitText.tsx
index ba56869..f48b59e 100644
--- a/src/FitText.tsx
+++ b/src/FitText.tsx
@@ -2,17 +2,16 @@ import { createEffect, createSignal, type Accessor } from "solid-js";
export default function FitText(props: { body: Accessor
}) {
let textRef: SVGTextElement | undefined;
- const [width, setWidth] = createSignal(100);
- const [height, setHeight] = createSignal(100);
+ const [viewBox, setViewbox] = createSignal()
- createEffect(() => {
+ createEffect(async () => {
props.body();
+ await Promise.resolve()
const bounds = textRef?.getBBox();
if (bounds === undefined) {
return;
}
- setWidth(bounds.width);
- setHeight(bounds.height);
+ setViewbox(`0 0 ${bounds.width} ${bounds.height}`)
});
return (
@@ -21,15 +20,14 @@ export default function FitText(props: { body: Accessor }) {
width: "100%",
"max-height": "40%",
}}
- viewBox={`0 0 ${width()} ${height()}`}
- overflow="visible"
+ viewBox={viewBox()}
fill="currentcolor"
>
diff --git a/src/useAppModel.ts b/src/useAppModel.ts
index 450dd62..0cb5867 100644
--- a/src/useAppModel.ts
+++ b/src/useAppModel.ts
@@ -5,7 +5,7 @@ import { tauriStorage } from "@solid-primitives/storage/tauri";
type Solution = {
id: number
- mistakes: number
+ guesses: number
}
type AppStore = {
@@ -24,10 +24,10 @@ export default function useAppModel() {
storage,
}
);
- function setSolution(id: number, mistakes: number) {
+ function setSolution(id: number, guesses: number) {
setStore("solutions", id, {
id,
- mistakes
+ guesses
})
}
diff --git a/src/usePuzzleModel.ts b/src/usePuzzleModel.ts
index b6eae5c..e58c7c6 100644
--- a/src/usePuzzleModel.ts
+++ b/src/usePuzzleModel.ts
@@ -2,6 +2,7 @@ import { Accessor, createEffect } from "solid-js";
import connections from "./assets/connections.json";
import { shuffleArray } from "./utils";
import { createStore } from "solid-js/store";
+import useAppModel from "./useAppModel";
type Connection = (typeof connections)[number];
type Answer = Connection["answers"][number];
@@ -12,7 +13,8 @@ function fromIndex(index: number): [number, number] {
return [row, col];
}
-type AppStore = {
+type PuzzleStore = {
+ guesses: number;
pinnedCount: number;
selected: number[];
solvedGroups: Answer[];
@@ -20,16 +22,22 @@ type AppStore = {
};
export default function usePuzzleModel(id: Accessor
) {
- const [store, setStore] = createStore({
+ const [store, setStore] = createStore({
+ guesses: 0,
pinnedCount: 0,
selected: [],
solvedGroups: [],
- puzzle: shuffleArray(Array.from({ length: 16 }, (_, i) => i)),
+ puzzle: [],
});
+ const {
+ setSolution
+ } = useAppModel()
+
createEffect(() => {
id()
setStore({
+ guesses: 0,
pinnedCount: 0,
selected: [],
solvedGroups: [],
@@ -53,6 +61,7 @@ export default function usePuzzleModel(id: Accessor) {
};
const handleGuess = () => {
+ setStore('guesses', x => x+1)
const selected = store.puzzle.length === 4 ? [0, 1, 2, 3] : store.selected;
const selectedAnswers = selected.map((x) => getFromPuzzle(x));
const { level } = selectedAnswers[0];
@@ -75,12 +84,11 @@ export default function usePuzzleModel(id: Accessor) {
});
const newSolvedGroup = answers().find((x) => x.level === level);
if (newSolvedGroup != null) {
- setStore({
- solvedGroups: [...store.solvedGroups, newSolvedGroup],
- });
+ setStore('solvedGroups', x => x.concat(newSolvedGroup))
}
if (store.puzzle.length === 0) {
// completely solved!
+ setSolution(id(), store.guesses)
}
};