From 9cb62afba8562054f5282ee19dc2f6675b600a25 Mon Sep 17 00:00:00 2001 From: Simon Lemieux <1105380+simlmx@users.noreply.github.com> Date: Sat, 22 Jun 2024 23:46:32 +0000 Subject: [PATCH 1/3] Simplify makefile and fix `make watch` --- Makefile | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/Makefile b/Makefile index 5b42000..7a13d7d 100644 --- a/Makefile +++ b/Makefile @@ -4,12 +4,12 @@ install: .PHONY: build build: - cd ui && pnpm run lingui:extract && pnpm run lingui:compile - pnpm run -r build + cd ui && pnpm lingui:extract && pnpm lingui:compile + pnpm -r build .PHONY: test test: - pnpm run -r test + pnpm -r test .PHONY: format format: @@ -25,8 +25,8 @@ check-format: .PHONY: watch watch: - pnpm run -r watch + pnpm -r --parallel watch .PHONY: dev dev: - cd ui && pnpm run dev + cd ui && pnpm dev From 79a0c281c482b77a5530866e34e257c9d2698217 Mon Sep 17 00:00:00 2001 From: Simon Lemieux <1105380+simlmx@users.noreply.github.com> Date: Sat, 22 Jun 2024 23:47:47 +0000 Subject: [PATCH 2/3] Very minimal first page of Categorio * Add tailwind * Make a starting point for the "Write" view --- game/src/index.ts | 91 ++++++++--- pnpm-lock.yaml | 284 ++++++++++++++++++++++++++++++++++ ui/package.json | 9 +- ui/postcss.config.cjs | 6 + ui/src/Board.tsx | 140 ++++++++++++----- ui/src/index.css | 38 ++--- ui/src/locales/en/messages.po | 12 +- ui/src/locales/fr/messages.po | 12 +- ui/src/useFonts.ts | 19 +++ ui/tailwind.config.ts | 28 ++++ 10 files changed, 538 insertions(+), 101 deletions(-) create mode 100644 ui/postcss.config.cjs create mode 100644 ui/src/useFonts.ts create mode 100644 ui/tailwind.config.ts diff --git a/game/src/index.ts b/game/src/index.ts index ee8b5f6..66033ac 100644 --- a/game/src/index.ts +++ b/game/src/index.ts @@ -1,42 +1,83 @@ import { UserId } from "@lefun/core"; import { createMove, GameDef, Moves, PlayerMove } from "@lefun/game"; -type Player = { - isRolling: boolean; - diceValue?: number; +const NUM_ROUNDS = 3; + +// Hard-code some categories for now. +const CATEGORIES = [ + "Something You Can Drink", + "Place With Lots of People", + "Horror Movies", + "Animal", + "Small Fruit", + "Thing That Is Frozen", + "Flower", + "Color", + "Something you write with", + "In a House", + // Should we use 10 or 12? + // "Something Blue", + // "Pop Artist", +]; + +const NUM_CATEGORIES = CATEGORIES.length; + +export type Phase = "write" | "review"; + +export type B = { + categories: string[]; + + // Info of the current round. + round: number; + phase: Phase; + letter: string; }; -export type Board = { - count: number; - players: Record; +export type PB = { + // An array of answers for each round. + answers: string[][]; }; -const [ROLL, roll] = createMove("roll"); +type WritePayload = { + index: number; + answer: string; +}; -const moves: Moves = { - [ROLL]: { - executeNow({ board, userId }) { - board.players[userId].isRolling = true; - }, - execute({ board, userId, random }) { - board.players[userId].diceValue = random.d6(); - board.players[userId].isRolling = false; +const [WRITE, write] = createMove("write"); + +const moves: Moves = { + [WRITE]: { + executeNow({ board, playerboard, payload }) { + const { answer, index } = payload as WritePayload; + const { round } = board; + playerboard.answers[round][index] = answer; }, }, }; -const game: GameDef = { - initialBoards: ({ players }) => ({ - board: { - count: 0, - players: Object.fromEntries( - players.map((userId) => [userId, { isRolling: false }]), - ), - }, - }), +const game: GameDef = { + initialBoards: ({ players }) => { + const board = { + categories: CATEGORIES, + round: 0, + // TODO No letter to start with, then a count them and then only we pick the letter. + letter: "A", + phase: "write" as const, + }; + + const playerboards: Record = {}; + + for (const userId of players) { + playerboards[userId] = { + answers: Array(NUM_ROUNDS).fill(Array(NUM_CATEGORIES).fill("")), + }; + } + + return { board, playerboards }; + }, moves, minPlayers: 1, maxPlayers: 10, }; -export { game, roll }; +export { game, write }; diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index e02a10b..af7e180 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -60,6 +60,9 @@ importers: '@lingui/conf': specifier: ^4.11.1 version: 4.11.1(typescript@5.5.2) + '@lingui/core': + specifier: ^4.11.1 + version: 4.11.1 '@lingui/macro': specifier: ^4.11.1 version: 4.11.1(@lingui/react@4.11.1(react@18.3.1))(babel-plugin-macros@3.1.0)(typescript@5.5.2) @@ -90,6 +93,12 @@ importers: '@vitejs/plugin-react': specifier: ^4.3.1 version: 4.3.1(vite@5.3.1(@types/node@20.14.8)) + autoprefixer: + specifier: ^10.4.19 + version: 10.4.19(postcss@8.4.38) + postcss: + specifier: ^8.4.38 + version: 8.4.38 react: specifier: ^18.3.1 version: 18.3.1 @@ -105,6 +114,9 @@ importers: rollup-plugin-postcss: specifier: ^4.0.2 version: 4.0.2(postcss@8.4.38) + tailwindcss: + specifier: ^3.4.4 + version: 3.4.4 typescript: specifier: ^5.5.2 version: 5.5.2 @@ -114,6 +126,10 @@ importers: packages: + '@alloc/quick-lru@5.2.0': + resolution: {integrity: sha512-UrcABB+4bUrFABwbluTIBErXwvbsU/V7TZWfmbgJfbkwiBuziS9gxdODUyuiecfdGQ85jglMW6juS3+z5TsKLw==} + engines: {node: '>=10'} + '@ampproject/remapping@2.3.0': resolution: {integrity: sha512-30iZtAPgz+LTIYoeivqYo853f02jBYSd5uGnGpkFV0M3xOt9aN73erkgYAmZU43x4VfqcnLxW9Kpg3R5LC4YYw==} engines: {node: '>=6.0.0'} @@ -884,10 +900,16 @@ packages: resolution: {integrity: sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==} engines: {node: '>=12'} + any-promise@1.3.0: + resolution: {integrity: sha512-7UvmKalWRt1wgjL1RrGxoSJW/0QZFIegpeGvZG9kjp8vrRu55XTHbwnqq2GpXm9uLbcuhxm3IqX9OB4MZR1b2A==} + anymatch@3.1.3: resolution: {integrity: sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==} engines: {node: '>= 8'} + arg@5.0.2: + resolution: {integrity: sha512-PYjyFOLKQ9y57JvQ6QLo8dAgNqswh8M1RMJYdQduT6xbWSgK36P/Z/v+p888pM69jMMfS8Xd8F6I1kQ/I9HUGg==} + argparse@2.0.1: resolution: {integrity: sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==} @@ -895,6 +917,13 @@ packages: resolution: {integrity: sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==} engines: {node: '>=8'} + autoprefixer@10.4.19: + resolution: {integrity: sha512-BaENR2+zBZ8xXhM4pUaKUxlVdxZ0EZhjvbopwnXmxRUfqDmwSpC2lAi/QXvx7NRdPCo1WKEcEF6mV64si1z4Ew==} + engines: {node: ^10 || ^12 || >=14} + hasBin: true + peerDependencies: + postcss: ^8.1.0 + babel-plugin-macros@3.1.0: resolution: {integrity: sha512-Cg7TFGpIr01vOQNODXOOaGz2NpCU5gl8x1qJFbb6hbZxR7XrcE2vtbAsTAbJ7/xwJtUuJEw8K8Zr/AE0LHlesg==} engines: {node: '>=10', npm: '>=6'} @@ -941,6 +970,10 @@ packages: resolution: {integrity: sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==} engines: {node: '>=6'} + camelcase-css@2.0.1: + resolution: {integrity: sha512-QOSvevhslijgYwRx6Rv7zKdMF8lbRmx+uQGx2+vDc+KI/eBnsy9kit5aj23AgGu3pa4t9AgwbnXWqS+iOY+2aA==} + engines: {node: '>= 6'} + camelcase@6.3.0: resolution: {integrity: sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==} engines: {node: '>=10'} @@ -966,6 +999,10 @@ packages: resolution: {integrity: sha512-9+s+Od+W0VJJzawDma/gvBNQqkTiqYTWLuZoyAsivsI4AaWTCzHG06/TMjsf1cYe9Cb97UCEhjz7HvnPk2p/tw==} engines: {node: '>= 8.10.0'} + chokidar@3.6.0: + resolution: {integrity: sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==} + engines: {node: '>= 8.10.0'} + classnames@2.5.1: resolution: {integrity: sha512-saHYOzhIQs6wy2sVxTM6bUDsQO4F50V9RQ22qBpEdCW+I+/Wmke2HOl6lS6dTpdxVhb88/I6+Hs+438c3lfUow==} @@ -1016,6 +1053,10 @@ packages: resolution: {integrity: sha512-y4Mg2tXshplEbSGzx7amzPwKKOCGuoSRP/CjEdwwk0FOGlUbq6lKuoyDZTNZkmxHdJtp54hdfY/JUrdL7Xfdug==} engines: {node: '>=14'} + commander@4.1.1: + resolution: {integrity: sha512-NOKm8xhkzAjzFx8B2v5OAHT+u5pRQc2UCa2Vq9jYL/31o2wi9mxBA7LIFs3sV5VSC49z6pEhfbMULvShKj26WA==} + engines: {node: '>= 6'} + commander@7.2.0: resolution: {integrity: sha512-QrWXB+ZQSVPmIWIhtEO9H+gwHaMGYiF5ChvoJ+K9ZGHG/sVsa6yiesAD1GC/x46sET00Xlwo1u49RVVVzvcSkw==} engines: {node: '>= 10'} @@ -1115,10 +1156,16 @@ packages: defaults@1.0.4: resolution: {integrity: sha512-eFuaLoy/Rxalv2kr+lqMlUnrDWV+3j4pljOIJgLIhI058IQfWJ7vXhyEIHu+HtC738klGALYxOKDO0bQP3tg8A==} + didyoumean@1.2.2: + resolution: {integrity: sha512-gxtyfqMg7GKyhQmb056K7M3xszy/myH8w+B4RT+QXBQsvAOdc3XymqDDPHx1BgPgsdAA5SIifona89YtRATDzw==} + dir-glob@3.0.1: resolution: {integrity: sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==} engines: {node: '>=8'} + dlv@1.1.3: + resolution: {integrity: sha512-+HlytyjlPKnIG8XuRG8WvmBP8xs8P71y+SKKS6ZXWoEgLuePxtDoUEiH7WkdePWrQ5JBpE6aoVqfZfJUQkjXwA==} + dom-serializer@1.4.1: resolution: {integrity: sha512-VHwB3KfrcOOkelEG2ZOfxqLZdfkil8PtJi4P8N2MMXucZq2yLp75ClViUlOVwyoHEDjYU433Aq+5zWP61+RGag==} @@ -1204,6 +1251,9 @@ packages: resolution: {integrity: sha512-PXUUyLqrR2XCWICfv6ukppP96sdFwWbNEnfEMt7jNsISjMsvaLNinAHNDYyvkyU+SZG2BTSbT5NjG+vZslfGTA==} engines: {node: '>=14'} + fraction.js@4.3.7: + resolution: {integrity: sha512-ZsDfxO51wGAXREY55a7la9LScWpwv9RxIrYABrlvOFBlH/ShPnrtsXeuUIfXKKOVicNxQ+o8JTbJvjS4M89yew==} + fs-extra@8.1.0: resolution: {integrity: sha512-yhlQgA6mnOJUKOsRUFsgJdQCvkKhcz8tlZG5HBQfReYZy46OwLcY+Zia0mtdHsOo9y/hP+CxMN0TU9QxoOtG4g==} engines: {node: '>=6 <7 || >=8'} @@ -1230,6 +1280,10 @@ packages: resolution: {integrity: sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==} engines: {node: '>= 6'} + glob-parent@6.0.2: + resolution: {integrity: sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==} + engines: {node: '>=10.13.0'} + glob@10.4.2: resolution: {integrity: sha512-GwMlUF6PkPo3Gk21UxkCohOv0PLcIXVtKyLlpEI28R/cO/4eNOdmLk3CMW1wROV/WR/EsZOWAfBbBOqYvs88/w==} engines: {node: '>=16 || 14 >=14.18'} @@ -1418,6 +1472,10 @@ packages: resolution: {integrity: sha512-utWOt/GHzuUxnLKxB6dk81RoOeoNeHgbrXiuGk4yyF5qlRz+iIVWu56E2fqGHFrXz0QNUhLB/8nKqvRH66JKGQ==} engines: {node: '>=10'} + lilconfig@3.1.2: + resolution: {integrity: sha512-eop+wDAvpItUys0FWkHIKeC9ybYrTGbU41U5K7+bttZZeohvnY7M9dZ5kB21GNWiFT2q1OoPTvncPCgSOVO5ow==} + engines: {node: '>=14'} + lines-and-columns@1.2.4: resolution: {integrity: sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==} @@ -1507,6 +1565,9 @@ packages: mute-stream@0.0.8: resolution: {integrity: sha512-nnbWWOkoWyUsTjKrhgD0dcz22mdkSnpYqbEjIm2nhwhuxlSkpywJmBo8h0ZqJdkp73mb90SssHkN4rsRaBAfAA==} + mz@2.7.0: + resolution: {integrity: sha512-z81GNO7nnYMEhrGh9LeymoE4+Yr0Wn5McHIZMK5cfQCl+NDX08sCZgUc9/6MHni9IWuFLm1Z3HTCXu2z9fN62Q==} + nanoid@3.3.7: resolution: {integrity: sha512-eSRppjcPIatRIMC1U6UngP8XFcz8MQWGQdt1MTBQ7NaAmvXDfvNxbvWV3x2y6CdEUciCSsDHDQZbhYaB8QEo2g==} engines: {node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1} @@ -1519,6 +1580,10 @@ packages: resolution: {integrity: sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==} engines: {node: '>=0.10.0'} + normalize-range@0.1.2: + resolution: {integrity: sha512-bdok/XvKII3nUpklnV6P2hxtMNrCboOjAcyBuQnWEhO665FwrSNRxU+AqpsyvO6LgGYPspN+lu5CLtw4jPRKNA==} + engines: {node: '>=0.10.0'} + normalize-url@6.1.0: resolution: {integrity: sha512-DlL+XwOy3NxAQ8xuC0okPgK46iuVNAK01YN7RueYBqqFeGsBjV9XmCAzAdgt+667bCl5kPh9EqKKDwnaPG1I7A==} engines: {node: '>=10'} @@ -1526,6 +1591,14 @@ packages: nth-check@2.1.1: resolution: {integrity: sha512-lqjrjmaOoAnWfMmBPL+XNnynZh2+swxiX3WUE0s4yEHI6m+AwrK2UZOimIRl3X/4QctVqS8AiZjFqyOGrMXb/w==} + object-assign@4.1.1: + resolution: {integrity: sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==} + engines: {node: '>=0.10.0'} + + object-hash@3.0.0: + resolution: {integrity: sha512-RSn9F68PjH9HqtltsSnqYC1XXoWe9Bju5+213R98cNGttag9q9yAOTzdbsqvIa7aNm5WffBZFpWYr2aWrklWAw==} + engines: {node: '>= 6'} + object-property-assigner@1.3.0: resolution: {integrity: sha512-19A0RsC9rP9klCKHDPL/MeERxeopV9wyMNfP+eD2uKOafzLjF+OUEN4FoP6RAlCFHmerBPJ4ohNv/WrgaNpeIA==} @@ -1615,10 +1688,18 @@ packages: resolution: {integrity: sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==} engines: {node: '>=8.6'} + pify@2.3.0: + resolution: {integrity: sha512-udgsAY+fTnvv7kI7aaxbqwWNb0AHiB0qBO89PZKPkoTmGOgdbrHDKD+0B2X4uTfJ/FT1R09r9gTsjUjNJotuog==} + engines: {node: '>=0.10.0'} + pify@5.0.0: resolution: {integrity: sha512-eW/gHNMlxdSP6dmG6uJip6FXN0EQBwm2clYYd8Wul42Cwu/DK8HEftzsapcNdYe2MfLiIwZqsDk2RDEsTE79hA==} engines: {node: '>=10'} + pirates@4.0.6: + resolution: {integrity: sha512-saLsH7WeYYPiD25LDuLRRY/i+6HaPYr6G1OUlN39otzkSTxKnubR9RTxS3/Kk50s1g2JTgFwWQDQyplC5/SHZg==} + engines: {node: '>= 6'} + pkg-up@3.1.0: resolution: {integrity: sha512-nDywThFk1i4BQK4twPQ6TA4RT8bDY96yeuCVBWL3ePARCiEKDRSrNGbFIgUJpLp+XeIR65v8ra7WuJOFUBtkMA==} engines: {node: '>=8'} @@ -1667,6 +1748,18 @@ packages: peerDependencies: postcss: ^8.2.15 + postcss-import@15.1.0: + resolution: {integrity: sha512-hpr+J05B2FVYUAXHeK1YyI267J/dDDhMU6B6civm8hSY1jYJnBXxzKDKDswzJmtLHryrjhnDjqqp/49t8FALew==} + engines: {node: '>=14.0.0'} + peerDependencies: + postcss: ^8.0.0 + + postcss-js@4.0.1: + resolution: {integrity: sha512-dDLF8pEO191hJMtlHFPRa8xsizHaM82MLfNkUHdUtVEV3tgTp5oj+8qbEqYM57SLfc74KSbw//4SeJma2LRVIw==} + engines: {node: ^12 || ^14 || >= 16} + peerDependencies: + postcss: ^8.4.21 + postcss-load-config@3.1.4: resolution: {integrity: sha512-6DiM4E7v4coTE4uzA8U//WhtPwyhiim3eyjEMFCnUpzbrkK9wJHgKDT2mR+HbtSrd/NubVaYTOpSpjUl8NQeRg==} engines: {node: '>= 10'} @@ -1679,6 +1772,18 @@ packages: ts-node: optional: true + postcss-load-config@4.0.2: + resolution: {integrity: sha512-bSVhyJGL00wMVoPUzAVAnbEoWyqRxkjv64tUl427SKnPrENtq6hJwUojroMz2VB+Q1edmi4IfrAPpami5VVgMQ==} + engines: {node: '>= 14'} + peerDependencies: + postcss: '>=8.0.9' + ts-node: '>=9.0.0' + peerDependenciesMeta: + postcss: + optional: true + ts-node: + optional: true + postcss-merge-longhand@5.1.7: resolution: {integrity: sha512-YCI9gZB+PLNskrK0BB3/2OzPnGhPkBEwmwhfYk1ilBHYVAZB7/tkTHFBAnCrvBBOmeYyMYw3DMjT55SyxMBzjQ==} engines: {node: ^10 || ^12 || >=14.0} @@ -1744,6 +1849,12 @@ packages: peerDependencies: postcss: ^8.0.0 + postcss-nested@6.0.1: + resolution: {integrity: sha512-mEp4xPMi5bSWiMbsgoPfcP74lsWLHkQbZc3sY+jWYd65CUwXrUaTp0fmNpa01ZcETKlIgUdFN/MpS2xZtqL9dQ==} + engines: {node: '>=12.0'} + peerDependencies: + postcss: ^8.2.14 + postcss-normalize-charset@5.1.0: resolution: {integrity: sha512-mSgUJ+pd/ldRGVx26p2wz9dNZ7ji6Pn8VWBajMXFf8jk7vUoSrZ2lt/wZR7DtlZYKesmZI680qjr2CeFF2fbUg==} engines: {node: ^10 || ^12 || >=14.0} @@ -1883,6 +1994,9 @@ packages: resolution: {integrity: sha512-wS+hAgJShR0KhEvPJArfuPVN1+Hz1t0Y6n5jLrGQbkb4urgPE/0Rve+1kMB1v/oWgHgm4WIcV+i7F2pTVj+2iQ==} engines: {node: '>=0.10.0'} + read-cache@1.0.0: + resolution: {integrity: sha512-Owdv/Ft7IjOgm/i0xvNDZ1LrRANRfew4b2prF3OWMQLxLfu3bS8FVhCsrSCMK4lR56Y9ya+AThoTpDCTxCmpRA==} + readable-stream@3.6.2: resolution: {integrity: sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==} engines: {node: '>= 6'} @@ -1891,6 +2005,10 @@ packages: resolution: {integrity: sha512-cMhu7c/8rdhkHXWsY+osBhfSy0JikwpHK/5+imo+LpeasTF8ouErHrlYkwT0++njiyuDvc7OFY5T3ukvZ8qmFQ==} engines: {node: '>=8.10.0'} + readdirp@3.6.0: + resolution: {integrity: sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==} + engines: {node: '>=8.10.0'} + regenerator-runtime@0.14.1: resolution: {integrity: sha512-dYnhHh0nJoMfnkZs6GmmhFknAGRrLznOu5nc9ML+EJxGvrx6H7teuevqVqCuPcPK//3eDrrjQhehXVx9cnkGdw==} @@ -2025,6 +2143,11 @@ packages: peerDependencies: postcss: ^8.2.15 + sucrase@3.35.0: + resolution: {integrity: sha512-8EbVDiu9iN/nESwxeSxDKe0dunta1GOlHufmSSXxMD2z2/tMZpDMpvXQGsc+ajGo8y2uYUmixaSRUc/QPoQ0GA==} + engines: {node: '>=16 || 14 >=14.17'} + hasBin: true + supports-color@5.5.0: resolution: {integrity: sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==} engines: {node: '>=4'} @@ -2042,6 +2165,18 @@ packages: engines: {node: '>=10.13.0'} hasBin: true + tailwindcss@3.4.4: + resolution: {integrity: sha512-ZoyXOdJjISB7/BcLTR6SEsLgKtDStYyYZVLsUtWChO4Ps20CBad7lfJKVDiejocV4ME1hLmyY0WJE3hSDcmQ2A==} + engines: {node: '>=14.0.0'} + hasBin: true + + thenify-all@1.6.0: + resolution: {integrity: sha512-RNxQH/qI8/t3thXJDwcstUO4zeqo64+Uy/+sNVRBx4Xn2OX+OZ9oP+iJnNFqplFra2ZUVeKCSa2oVWi3T4uVmA==} + engines: {node: '>=0.8'} + + thenify@3.3.1: + resolution: {integrity: sha512-RVZSIV5IG10Hk3enotrhvz0T9em6cyHBLkH/YAZuKqd8hRkKhSfCGIcP2KUY0EPxndzANBmNllzWPwak+bheSw==} + through@2.3.8: resolution: {integrity: sha512-w89qg7PI8wAdvX60bMDP+bFoD5Dvhm9oLheFp5O4a2QF0cSBGsBX4qZmadPMvVqlLJBBci+WqGGOAPvcDeNSVg==} @@ -2060,6 +2195,9 @@ packages: tr46@1.0.1: resolution: {integrity: sha512-dTpowEjclQ7Kgx5SdBkqRzVhERQXov8/l9Ft9dVM9fmg0W0KQSVaXX9T4i6twCPNtYiZM53lpSSUAwJbFPOHxA==} + ts-interface-checker@0.1.13: + resolution: {integrity: sha512-Y/arvbn+rrz3JCKl9C4kVNfTfSm2/mEp5FSz5EsZSANGPSlQrpRI5M4PKF+mJnE52jOO90PnPSc3Ur3bTQw0gA==} + tslib@1.14.1: resolution: {integrity: sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==} @@ -2159,6 +2297,11 @@ packages: resolution: {integrity: sha512-r3vXyErRCYJ7wg28yvBY5VSoAF8ZvlcW9/BwUzEtUsjvX/DKs24dIkuwjtuprwJJHsbyUbLApepYTR1BN4uHrg==} engines: {node: '>= 6'} + yaml@2.4.5: + resolution: {integrity: sha512-aBx2bnqDzVOyNKfsysjA2ms5ZlnjSAW2eG3/L5G/CSujfjLJTJsEw1bGw8kCf04KodQWk1pxlGnZ56CRxiawmg==} + engines: {node: '>= 14'} + hasBin: true + zustand@4.5.2: resolution: {integrity: sha512-2cN1tPkDVkwCy5ickKrI7vijSjPksFRfqS6237NzT0vqSsztTNnQdHw9mmN7uBdk3gceVXU0a+21jFzFzAc9+g==} engines: {node: '>=12.7.0'} @@ -2176,6 +2319,8 @@ packages: snapshots: + '@alloc/quick-lru@5.2.0': {} + '@ampproject/remapping@2.3.0': dependencies: '@jridgewell/gen-mapping': 0.3.5 @@ -2904,15 +3049,29 @@ snapshots: ansi-styles@6.2.1: {} + any-promise@1.3.0: {} + anymatch@3.1.3: dependencies: normalize-path: 3.0.0 picomatch: 2.3.1 + arg@5.0.2: {} + argparse@2.0.1: {} array-union@2.1.0: {} + autoprefixer@10.4.19(postcss@8.4.38): + dependencies: + browserslist: 4.23.1 + caniuse-lite: 1.0.30001636 + fraction.js: 4.3.7 + normalize-range: 0.1.2 + picocolors: 1.0.1 + postcss: 8.4.38 + postcss-value-parser: 4.2.0 + babel-plugin-macros@3.1.0: dependencies: '@babel/runtime': 7.24.7 @@ -2962,6 +3121,8 @@ snapshots: callsites@3.1.0: {} + camelcase-css@2.0.1: {} + camelcase@6.3.0: {} caniuse-api@3.0.0: @@ -2998,6 +3159,18 @@ snapshots: optionalDependencies: fsevents: 2.3.3 + chokidar@3.6.0: + dependencies: + anymatch: 3.1.3 + braces: 3.0.3 + glob-parent: 5.1.2 + is-binary-path: 2.1.0 + is-glob: 4.0.3 + normalize-path: 3.0.0 + readdirp: 3.6.0 + optionalDependencies: + fsevents: 2.3.3 + classnames@2.5.1: {} cli-cursor@3.1.0: @@ -3034,6 +3207,8 @@ snapshots: commander@10.0.1: {} + commander@4.1.1: {} + commander@7.2.0: {} commondir@1.0.1: {} @@ -3152,10 +3327,14 @@ snapshots: dependencies: clone: 1.0.4 + didyoumean@1.2.2: {} + dir-glob@3.0.1: dependencies: path-type: 4.0.0 + dlv@1.1.3: {} + dom-serializer@1.4.1: dependencies: domelementtype: 2.3.0 @@ -3284,6 +3463,8 @@ snapshots: cross-spawn: 7.0.3 signal-exit: 4.1.0 + fraction.js@4.3.7: {} + fs-extra@8.1.0: dependencies: graceful-fs: 4.2.11 @@ -3307,6 +3488,10 @@ snapshots: dependencies: is-glob: 4.0.3 + glob-parent@6.0.2: + dependencies: + is-glob: 4.0.3 + glob@10.4.2: dependencies: foreground-child: 3.2.1 @@ -3489,6 +3674,8 @@ snapshots: lilconfig@2.1.0: {} + lilconfig@3.1.2: {} + lines-and-columns@1.2.4: {} loader-utils@3.3.1: {} @@ -3563,18 +3750,30 @@ snapshots: mute-stream@0.0.8: {} + mz@2.7.0: + dependencies: + any-promise: 1.3.0 + object-assign: 4.1.1 + thenify-all: 1.6.0 + nanoid@3.3.7: {} node-releases@2.0.14: {} normalize-path@3.0.0: {} + normalize-range@0.1.2: {} + normalize-url@6.1.0: {} nth-check@2.1.1: dependencies: boolbase: 1.0.0 + object-assign@4.1.1: {} + + object-hash@3.0.0: {} + object-property-assigner@1.3.0: {} object-property-extractor@1.0.11: {} @@ -3656,8 +3855,12 @@ snapshots: picomatch@2.3.1: {} + pify@2.3.0: {} + pify@5.0.0: {} + pirates@4.0.6: {} + pkg-up@3.1.0: dependencies: find-up: 3.0.0 @@ -3700,6 +3903,18 @@ snapshots: dependencies: postcss: 8.4.38 + postcss-import@15.1.0(postcss@8.4.38): + dependencies: + postcss: 8.4.38 + postcss-value-parser: 4.2.0 + read-cache: 1.0.0 + resolve: 1.22.8 + + postcss-js@4.0.1(postcss@8.4.38): + dependencies: + camelcase-css: 2.0.1 + postcss: 8.4.38 + postcss-load-config@3.1.4(postcss@8.4.38): dependencies: lilconfig: 2.1.0 @@ -3707,6 +3922,13 @@ snapshots: optionalDependencies: postcss: 8.4.38 + postcss-load-config@4.0.2(postcss@8.4.38): + dependencies: + lilconfig: 3.1.2 + yaml: 2.4.5 + optionalDependencies: + postcss: 8.4.38 + postcss-merge-longhand@5.1.7(postcss@8.4.38): dependencies: postcss: 8.4.38 @@ -3778,6 +4000,11 @@ snapshots: postcss-modules-values: 4.0.0(postcss@8.4.38) string-hash: 1.1.3 + postcss-nested@6.0.1(postcss@8.4.38): + dependencies: + postcss: 8.4.38 + postcss-selector-parser: 6.1.0 + postcss-normalize-charset@5.1.0(postcss@8.4.38): dependencies: postcss: 8.4.38 @@ -3899,6 +4126,10 @@ snapshots: dependencies: loose-envify: 1.4.0 + read-cache@1.0.0: + dependencies: + pify: 2.3.0 + readable-stream@3.6.2: dependencies: inherits: 2.0.4 @@ -3909,6 +4140,10 @@ snapshots: dependencies: picomatch: 2.3.1 + readdirp@3.6.0: + dependencies: + picomatch: 2.3.1 + regenerator-runtime@0.14.1: {} resolve-from@4.0.0: {} @@ -4059,6 +4294,16 @@ snapshots: postcss: 8.4.38 postcss-selector-parser: 6.1.0 + sucrase@3.35.0: + dependencies: + '@jridgewell/gen-mapping': 0.3.5 + commander: 4.1.1 + glob: 10.4.2 + lines-and-columns: 1.2.4 + mz: 2.7.0 + pirates: 4.0.6 + ts-interface-checker: 0.1.13 + supports-color@5.5.0: dependencies: has-flag: 3.0.0 @@ -4079,6 +4324,41 @@ snapshots: picocolors: 1.0.1 stable: 0.1.8 + tailwindcss@3.4.4: + dependencies: + '@alloc/quick-lru': 5.2.0 + arg: 5.0.2 + chokidar: 3.6.0 + didyoumean: 1.2.2 + dlv: 1.1.3 + fast-glob: 3.3.2 + glob-parent: 6.0.2 + is-glob: 4.0.3 + jiti: 1.21.6 + lilconfig: 2.1.0 + micromatch: 4.0.7 + normalize-path: 3.0.0 + object-hash: 3.0.0 + picocolors: 1.0.1 + postcss: 8.4.38 + postcss-import: 15.1.0(postcss@8.4.38) + postcss-js: 4.0.1(postcss@8.4.38) + postcss-load-config: 4.0.2(postcss@8.4.38) + postcss-nested: 6.0.1(postcss@8.4.38) + postcss-selector-parser: 6.1.0 + resolve: 1.22.8 + sucrase: 3.35.0 + transitivePeerDependencies: + - ts-node + + thenify-all@1.6.0: + dependencies: + thenify: 3.3.1 + + thenify@3.3.1: + dependencies: + any-promise: 1.3.0 + through@2.3.8: {} tmp@0.0.33: @@ -4095,6 +4375,8 @@ snapshots: dependencies: punycode: 2.3.1 + ts-interface-checker@0.1.13: {} + tslib@1.14.1: {} tslib@2.6.3: {} @@ -4164,6 +4446,8 @@ snapshots: yaml@1.10.2: {} + yaml@2.4.5: {} + zustand@4.5.2(@types/react@18.3.3)(immer@10.1.1)(react@18.3.1): dependencies: use-sync-external-store: 1.2.0(react@18.3.1) diff --git a/ui/package.json b/ui/package.json index 24c9125..0cbfea3 100644 --- a/ui/package.json +++ b/ui/package.json @@ -9,6 +9,7 @@ "types": "dist/types/index.d.ts", "scripts": { "build": "rm -rf ./dist && pnpm rollup --config", + "watch": "pnpm rollup --config --watch", "dev": "pnpm vite --host", "lingui:compile": "pnpm lingui compile", "lingui:extract": "pnpm lingui extract" @@ -20,6 +21,7 @@ "@lefun/ui": "^1.2.0", "@lingui/cli": "^4.11.1", "@lingui/conf": "^4.11.1", + "@lingui/core": "^4.11.1", "@lingui/macro": "^4.11.1", "@lingui/react": "^4.11.1", "@lingui/vite-plugin": "^4.11.1", @@ -30,17 +32,20 @@ "@types/react": "^18.3.3", "@types/react-dom": "^18.3.0", "@vitejs/plugin-react": "^4.3.1", + "autoprefixer": "^10.4.19", + "postcss": "^8.4.38", "react": "^18.3.1", "react-dom": "^18.3.1", "rollup": "^4.18.0", "rollup-plugin-copy": "^3.5.0", "rollup-plugin-postcss": "^4.0.2", + "tailwindcss": "^3.4.4", "typescript": "^5.5.2", "vite": "^5.3.1" }, "dependencies": { - "classnames": "^2.5.1", - "categorio-game": "workspace:*" + "categorio-game": "workspace:*", + "classnames": "^2.5.1" }, "peerDependencies": { "@lefun/core": "^1.2.0", diff --git a/ui/postcss.config.cjs b/ui/postcss.config.cjs new file mode 100644 index 0000000..12a703d --- /dev/null +++ b/ui/postcss.config.cjs @@ -0,0 +1,6 @@ +module.exports = { + plugins: { + tailwindcss: {}, + autoprefixer: {}, + }, +}; diff --git a/ui/src/Board.tsx b/ui/src/Board.tsx index 98d3756..7bd7baf 100644 --- a/ui/src/Board.tsx +++ b/ui/src/Board.tsx @@ -1,71 +1,131 @@ import "./index.css"; -import classNames from "classnames"; - -import type { UserId } from "@lefun/core"; import { - useUsername, makeUseSelector, - makeUseSelectorShallow, + // makeUseSelectorShallow, useDispatch, } from "@lefun/ui"; -import { Board as _Board, roll } from "roll-game"; +import classNames from "classnames"; + +import { useState } from "react"; + +import { B, PB, write, Phase } from "categorio-game"; -import { Trans } from "@lingui/macro"; +import { MessageDescriptor } from "@lingui/core"; +import { Trans, msg } from "@lingui/macro"; +import { useLingui } from "@lingui/react"; -type B = _Board; +import { useFonts } from "./useFonts"; -// Dice symbol characters -const DICE = ["", "\u2680", "\u2681", "\u2682", "\u2683", "\u2684", "\u2685"]; +const useSelector = makeUseSelector(); +// const useSelectorShallow = makeUseSelectorShallow(); -const useSelector = makeUseSelector(); -const useSelectorShallow = makeUseSelectorShallow(); +const phaseNames: Record = { + write: msg`Write`, + review: msg`Review`, +}; -function Player({ userId }: { userId: UserId }) { - const itsMe = useSelector((state) => state.userId === userId); - const username = useUsername(userId); +function Header() { + const round = useSelector((state) => state.board.round); + const phase = useSelector((state) => state.board.phase); + const letter = useSelector((state) => state.board.letter); + + const { _ } = useLingui(); return ( -
- {username} - +
+
+
+ Round {round + 1} + + {_(phaseNames[phase])} + +
+
+
+
+
{letter}
+
+
+
123
); } -function Die({ userId }: { userId: UserId }) { - const diceValue = useSelector( - (state) => state.board.players[userId].diceValue, - ); - const isRolling = useSelector( - (state) => state.board.players[userId].isRolling, +function AnswerInput({ index }: { index: number }) { + const category = useSelector((state) => state.board.categories[index]); + const answer = useSelector( + (state) => state.playerboard.answers[state.board.round][index], ); + const [newAnswer, setNewAnswer] = useState(answer); + + const empty = newAnswer === ""; + + const dispatch = useDispatch(); + + const [focused, setFocused] = useState(false); + return ( - - {isRolling || !diceValue ? "?" : DICE[diceValue]} - +
+ {(focused || !empty) && ( +
+
{category}
+
+ )} + { + const { value } = e.target; + setNewAnswer(value); + dispatch(write({ index, answer: value })); + }} + onFocus={() => setFocused(true)} + onBlur={() => setFocused(false)} + > +
); } function Board() { - const dispatch = useDispatch(); - const players = useSelectorShallow((state) => - Object.keys(state.board.players), - ); + useFonts(); + + const numCategories = useSelector((state) => state.board.categories.length); return ( -
-
- The template game - {players.map((userId) => ( - - ))} +
+
+
+
+ {Array(numCategories) + .fill(null) + .map((_, index) => ( + + ))} +
-
); } diff --git a/ui/src/index.css b/ui/src/index.css index fd7cd36..8c5306f 100644 --- a/ui/src/index.css +++ b/ui/src/index.css @@ -1,35 +1,21 @@ +@tailwind base; +@tailwind components; +@tailwind utilities; + html { - font-family: sans-serif; - font-size: 16px; + font-family: Inter, sans-serif; + font-size: 18px; + font-weight: 350; + /* This is approximately the color of the background on lefun.fun */ + background-color: #ecebe4; + @apply tracking-wide; } body, -html { +html, +#home { width: 100%; height: 100%; padding: 0; margin: 0; } - -button { - background-color: #4caf50; - color: white; - padding: 14px 20px; - border: none; - cursor: pointer; - width: 100%; - font-size: 1.5rem; -} - -.bold { - font-weight: bold; -} - -.dice { - margin: 0 0 0 10px; - font-size: 3rem; -} - -.player { - height: 100px; -} diff --git a/ui/src/locales/en/messages.po b/ui/src/locales/en/messages.po index f18baa4..3fb478b 100644 --- a/ui/src/locales/en/messages.po +++ b/ui/src/locales/en/messages.po @@ -39,9 +39,13 @@ msgid "lefun.description" msgstr "This game is merely a template game." #: src/Board.tsx -msgid "Roll" -msgstr "Roll" +msgid "Review" +msgstr "Review" #: src/Board.tsx -msgid "The template game" -msgstr "The template game" +msgid "Round {0}" +msgstr "Round {0}" + +#: src/Board.tsx +msgid "Write" +msgstr "Write" diff --git a/ui/src/locales/fr/messages.po b/ui/src/locales/fr/messages.po index 71841ee..f1a0610 100644 --- a/ui/src/locales/fr/messages.po +++ b/ui/src/locales/fr/messages.po @@ -39,9 +39,13 @@ msgid "lefun.description" msgstr "Ce jeu n'est qu'un template." #: src/Board.tsx -msgid "Roll" -msgstr "Lancer" +msgid "Review" +msgstr "Revue" #: src/Board.tsx -msgid "The template game" -msgstr "Le jeu template" +msgid "Round {0}" +msgstr "Ronde {0}" + +#: src/Board.tsx +msgid "Write" +msgstr "Écriture" diff --git a/ui/src/useFonts.ts b/ui/src/useFonts.ts new file mode 100644 index 0000000..b924670 --- /dev/null +++ b/ui/src/useFonts.ts @@ -0,0 +1,19 @@ +import { useEffect } from "react"; + +function useFonts() { + // Add the google font. This is a bit hacky but we have no other way to control the + // "outer" HTML. + useEffect(() => { + const parent = document.getElementsByTagName("head")[0]; + parent.insertAdjacentHTML( + "beforeend", + ` + + + + `, + ); + }, []); +} + +export { useFonts }; diff --git a/ui/tailwind.config.ts b/ui/tailwind.config.ts new file mode 100644 index 0000000..ac0825b --- /dev/null +++ b/ui/tailwind.config.ts @@ -0,0 +1,28 @@ +import type { Config } from "tailwindcss"; + +// Max height before we start capping on desktop. +// We optimise this to nicely fit our 10 questions. +const vmd = "740px"; + +export default { + content: ["./src/**/*.{ts,tsx}"], + theme: { + screens: { + // vsm: { raw: `(min-height: ${vsm})` }, + vmd: { raw: `(min-height: ${vmd})` }, + }, + extend: { + fontSize: { + xxs: "0.675rem", + }, + colors: { + primary: "#E00094", + }, + spacing: { + // vsm, + vmd, + }, + }, + }, + plugins: [], +} satisfies Config; From babba3e9a3086b39a7986ff71b3efeb74ae4b1dd Mon Sep 17 00:00:00 2001 From: Simon Lemieux <1105380+simlmx@users.noreply.github.com> Date: Sun, 23 Jun 2024 00:07:38 +0000 Subject: [PATCH 3/3] Add simple github workflow --- .github/workflows/ci.yaml | 26 ++++++++++++++++++++++++++ Makefile | 2 +- package.json | 3 ++- 3 files changed, 29 insertions(+), 2 deletions(-) create mode 100644 .github/workflows/ci.yaml diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml new file mode 100644 index 0000000..5feb7c5 --- /dev/null +++ b/.github/workflows/ci.yaml @@ -0,0 +1,26 @@ +# This workflow will do a clean installation of node dependencies, cache/restore them, build the source code and run tests across different versions of node +# For more information see: https://docs.github.com/en/actions/automating-builds-and-tests/building-and-testing-nodejs + +name: Build and Test + +on: + pull_request: + branches: [ "main" ] + +jobs: + build: + + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v4 + - uses: pnpm/action-setup@v4 + - name: Install Node.js + uses: actions/setup-node@v4 + with: + node-version: 20 + cache: 'pnpm' + - run: make install + - run: make build + - run: make check-format + - run: make test diff --git a/Makefile b/Makefile index 7a13d7d..5d17697 100644 --- a/Makefile +++ b/Makefile @@ -4,8 +4,8 @@ install: .PHONY: build build: + cd game && pnpm build cd ui && pnpm lingui:extract && pnpm lingui:compile - pnpm -r build .PHONY: test test: diff --git a/package.json b/package.json index e508162..a0e3ade 100644 --- a/package.json +++ b/package.json @@ -4,5 +4,6 @@ "devDependencies": { "prettier": "^3.3.2" }, - "private": true + "private": true, + "packageManager": "pnpm@9.4.0" }