aboutsummaryrefslogtreecommitdiffhomepage
path: root/frontend
diff options
context:
space:
mode:
Diffstat (limited to 'frontend')
-rw-r--r--frontend/app/api/schema.d.ts2
-rw-r--r--frontend/app/components/Gaming/CodePopover.tsx43
-rw-r--r--frontend/app/components/Gaming/RankingTable.tsx5
-rw-r--r--frontend/app/routes/dashboard.tsx19
-rw-r--r--frontend/package-lock.json385
-rw-r--r--frontend/package.json1
6 files changed, 425 insertions, 30 deletions
diff --git a/frontend/app/api/schema.d.ts b/frontend/app/api/schema.d.ts
index 6f69292..af454e8 100644
--- a/frontend/app/api/schema.d.ts
+++ b/frontend/app/api/schema.d.ts
@@ -211,6 +211,8 @@ export interface components {
score: number;
/** @example 946684800 */
submitted_at: number;
+ /** @example echo 'hello world'; */
+ code: string | null;
};
};
responses: {
diff --git a/frontend/app/components/Gaming/CodePopover.tsx b/frontend/app/components/Gaming/CodePopover.tsx
new file mode 100644
index 0000000..a574a77
--- /dev/null
+++ b/frontend/app/components/Gaming/CodePopover.tsx
@@ -0,0 +1,43 @@
+import { Popover } from "@base-ui-components/react/popover";
+import { faCode, faXmark } from "@fortawesome/free-solid-svg-icons";
+import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
+import { calcCodeSize } from "../../states/play";
+import BorderedContainer from "../BorderedContainer";
+import CodeBlock from "../Gaming/CodeBlock";
+
+type Props = {
+ code: string;
+};
+
+export default function CodePopover({ code }: Props) {
+ const codeSize = calcCodeSize(code);
+
+ return (
+ <Popover.Root>
+ <Popover.Trigger>
+ <FontAwesomeIcon icon={faCode} fixedWidth />
+ </Popover.Trigger>
+ <Popover.Portal>
+ <Popover.Positioner>
+ <Popover.Popup>
+ <BorderedContainer className="grow flex flex-col gap-4">
+ <div className="flex flex-row gap-2 items-center">
+ <div className="grow font-semibold text-lg">
+ コードサイズ: {codeSize}
+ </div>
+ <Popover.Close className="p-1 bg-gray-50 border-1 border-gray-300 rounded-sm">
+ <FontAwesomeIcon
+ icon={faXmark}
+ fixedWidth
+ className="text-gray-500"
+ />
+ </Popover.Close>
+ </div>
+ <CodeBlock code={code} language="php" />
+ </BorderedContainer>
+ </Popover.Popup>
+ </Popover.Positioner>
+ </Popover.Portal>
+ </Popover.Root>
+ );
+}
diff --git a/frontend/app/components/Gaming/RankingTable.tsx b/frontend/app/components/Gaming/RankingTable.tsx
index a1e41f5..38d5200 100644
--- a/frontend/app/components/Gaming/RankingTable.tsx
+++ b/frontend/app/components/Gaming/RankingTable.tsx
@@ -1,6 +1,7 @@
import { useAtomValue } from "jotai";
import React from "react";
import { rankingAtom } from "../../states/watch";
+import CodePopover from "./CodePopover";
function TableHeaderCell({ children }: { children: React.ReactNode }) {
return (
@@ -40,6 +41,7 @@ export default function RankingTable() {
<TableHeaderCell>プレイヤー</TableHeaderCell>
<TableHeaderCell>スコア</TableHeaderCell>
<TableHeaderCell>提出時刻</TableHeaderCell>
+ <TableHeaderCell>コード</TableHeaderCell>
</tr>
</thead>
<tbody className="bg-white divide-y divide-gray-300">
@@ -54,6 +56,9 @@ export default function RankingTable() {
<TableBodyCell>
{formatUnixTimestamp(entry.submitted_at)}
</TableBodyCell>
+ <TableBodyCell>
+ {entry.code && <CodePopover code={entry.code} />}
+ </TableBodyCell>
</tr>
))}
</tbody>
diff --git a/frontend/app/routes/dashboard.tsx b/frontend/app/routes/dashboard.tsx
index d0fea47..b7bfb01 100644
--- a/frontend/app/routes/dashboard.tsx
+++ b/frontend/app/routes/dashboard.tsx
@@ -24,8 +24,6 @@ export async function loader({ request }: LoaderFunctionArgs) {
export default function Dashboard() {
const { user, games } = useLoaderData<typeof loader>()!;
- const isOnlineQualifyingOpen = new Date() < new Date(2025, 2, 21, 16, 30);
-
return (
<div className="p-6 bg-gray-100 min-h-screen flex flex-col items-center gap-4">
{user.icon_path && (
@@ -36,23 +34,6 @@ export default function Dashboard() {
/>
)}
<h1 className="text-3xl font-bold text-gray-800">{user.display_name}</h1>
- {isOnlineQualifyingOpen && (
- <BorderedContainerWithCaption caption="オンライン予選開催中 (3/21 決勝当日まで)">
- <p className="text-gray-900 max-w-prose">
- 現在オンライン予選を開催中です。
- 予選問題2問を両方解いたプレイヤーのうち合計スコアが最も小さい2名が、3/21
- (金) の PHPerKaigi day0 に実施される決勝戦への進出枠を獲得します。
- 当日は、会場の Track A まで是非お越しください!
- </p>
- <p className="text-gray-600 max-w-prose">
- ※ 当日会場 Track A
- にいらっしゃらない場合、次点のスコアを獲得されている方が自動的に決勝進出となります。
- </p>
- <p className="text-gray-600 max-w-prose">
- ※ 決勝に参加する予定のない方でも、プレイしていただくことは可能です。
- </p>
- </BorderedContainerWithCaption>
- )}
<BorderedContainerWithCaption caption="試合一覧">
<div className="px-4">
{games.length === 0 ? (
diff --git a/frontend/package-lock.json b/frontend/package-lock.json
index a4ae09f..9bcfa0a 100644
--- a/frontend/package-lock.json
+++ b/frontend/package-lock.json
@@ -6,6 +6,7 @@
"": {
"name": "phperkaigi-2025-albatross-frontend",
"dependencies": {
+ "@base-ui-components/react": "^1.0.0-alpha.7",
"@fortawesome/fontawesome-svg-core": "^6.7.2",
"@fortawesome/free-solid-svg-icons": "^6.7.2",
"@fortawesome/react-fontawesome": "^0.2.2",
@@ -474,10 +475,9 @@
}
},
"node_modules/@babel/runtime": {
- "version": "7.26.9",
- "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.26.9.tgz",
- "integrity": "sha512-aA63XwOkcl4xxQa3HjPMqOP6LiK0ZDv3mUPYEFXkpHbaFjtGggE1A61FjFzJnB+p7/oy2gA8E+rcBNl/zC1tMg==",
- "devOptional": true,
+ "version": "7.27.0",
+ "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.27.0.tgz",
+ "integrity": "sha512-VtPOkrdPHZsKc/clNqyi9WUA8TINkZ4cGk63UUE3u4pmB2k+ZMQRDuIOagv8UVd6j7k0T3+RRIb7beKTebNbcw==",
"license": "MIT",
"dependencies": {
"regenerator-runtime": "^0.14.0"
@@ -540,6 +540,37 @@
"node": ">=6.9.0"
}
},
+ "node_modules/@base-ui-components/react": {
+ "version": "1.0.0-alpha.7",
+ "resolved": "https://registry.npmjs.org/@base-ui-components/react/-/react-1.0.0-alpha.7.tgz",
+ "integrity": "sha512-M4MxUvwAfERYSMqrUmTSf4J5yHXXGHqXw5wE7WLz8eCIhFmVWog4j5hYRU6QZ0VhqlyVPhs9KqSnts+FFyPmew==",
+ "license": "MIT",
+ "dependencies": {
+ "@babel/runtime": "^7.26.10",
+ "@floating-ui/react": "^0.27.5",
+ "@floating-ui/utils": "^0.2.9",
+ "@react-aria/overlays": "^3.26.1",
+ "prop-types": "^15.8.1",
+ "use-sync-external-store": "^1.4.0"
+ },
+ "engines": {
+ "node": ">=14.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/mui-org"
+ },
+ "peerDependencies": {
+ "@types/react": "^17 || ^18 || ^19",
+ "react": "^17 || ^18 || ^19",
+ "react-dom": "^17 || ^18 || ^19"
+ },
+ "peerDependenciesMeta": {
+ "@types/react": {
+ "optional": true
+ }
+ }
+ },
"node_modules/@biomejs/biome": {
"version": "1.9.4",
"resolved": "https://registry.npmjs.org/@biomejs/biome/-/biome-1.9.4.tgz",
@@ -1482,7 +1513,6 @@
"version": "1.6.9",
"resolved": "https://registry.npmjs.org/@floating-ui/core/-/core-1.6.9.tgz",
"integrity": "sha512-uMXCuQ3BItDUbAMhIXw7UPXRfAlOAvZzdK9BWpE60MCn+Svt3aLn9jsPTi/WNGlRUu2uI0v5S7JiIUsbsvh3fw==",
- "dev": true,
"license": "MIT",
"dependencies": {
"@floating-ui/utils": "^0.2.9"
@@ -1492,18 +1522,31 @@
"version": "1.6.13",
"resolved": "https://registry.npmjs.org/@floating-ui/dom/-/dom-1.6.13.tgz",
"integrity": "sha512-umqzocjDgNRGTuO7Q8CU32dkHkECqI8ZdMZ5Swb6QAM0t5rnlrN3lGo1hdpscRd3WS8T6DKYK4ephgIH9iRh3w==",
- "dev": true,
"license": "MIT",
"dependencies": {
"@floating-ui/core": "^1.6.0",
"@floating-ui/utils": "^0.2.9"
}
},
+ "node_modules/@floating-ui/react": {
+ "version": "0.27.5",
+ "resolved": "https://registry.npmjs.org/@floating-ui/react/-/react-0.27.5.tgz",
+ "integrity": "sha512-BX3jKxo39Ba05pflcQmqPPwc0qdNsdNi/eweAFtoIdrJWNen2sVEWMEac3i6jU55Qfx+lOcdMNKYn2CtWmlnOQ==",
+ "license": "MIT",
+ "dependencies": {
+ "@floating-ui/react-dom": "^2.1.2",
+ "@floating-ui/utils": "^0.2.9",
+ "tabbable": "^6.0.0"
+ },
+ "peerDependencies": {
+ "react": ">=17.0.0",
+ "react-dom": ">=17.0.0"
+ }
+ },
"node_modules/@floating-ui/react-dom": {
"version": "2.1.2",
"resolved": "https://registry.npmjs.org/@floating-ui/react-dom/-/react-dom-2.1.2.tgz",
"integrity": "sha512-06okr5cgPzMNBy+Ycse2A6udMi4bqwW/zgBF/rwjcNqWkyr82Mcg8b0vjX8OJpZFy/FKjJmw6wV7t44kK6kW7A==",
- "dev": true,
"license": "MIT",
"dependencies": {
"@floating-ui/dom": "^1.0.0"
@@ -1517,9 +1560,59 @@
"version": "0.2.9",
"resolved": "https://registry.npmjs.org/@floating-ui/utils/-/utils-0.2.9.tgz",
"integrity": "sha512-MDWhGtE+eHw5JW7lq4qhc5yRLS11ERl1c7Z6Xd0a58DozHES6EnNNwUWbMiG4J9Cgj053Bhk8zvlhFYKVhULwg==",
- "dev": true,
"license": "MIT"
},
+ "node_modules/@formatjs/ecma402-abstract": {
+ "version": "2.3.4",
+ "resolved": "https://registry.npmjs.org/@formatjs/ecma402-abstract/-/ecma402-abstract-2.3.4.tgz",
+ "integrity": "sha512-qrycXDeaORzIqNhBOx0btnhpD1c+/qFIHAN9znofuMJX6QBwtbrmlpWfD4oiUUD2vJUOIYFA/gYtg2KAMGG7sA==",
+ "license": "MIT",
+ "dependencies": {
+ "@formatjs/fast-memoize": "2.2.7",
+ "@formatjs/intl-localematcher": "0.6.1",
+ "decimal.js": "^10.4.3",
+ "tslib": "^2.8.0"
+ }
+ },
+ "node_modules/@formatjs/fast-memoize": {
+ "version": "2.2.7",
+ "resolved": "https://registry.npmjs.org/@formatjs/fast-memoize/-/fast-memoize-2.2.7.tgz",
+ "integrity": "sha512-Yabmi9nSvyOMrlSeGGWDiH7rf3a7sIwplbvo/dlz9WCIjzIQAfy1RMf4S0X3yG724n5Ghu2GmEl5NJIV6O9sZQ==",
+ "license": "MIT",
+ "dependencies": {
+ "tslib": "^2.8.0"
+ }
+ },
+ "node_modules/@formatjs/icu-messageformat-parser": {
+ "version": "2.11.2",
+ "resolved": "https://registry.npmjs.org/@formatjs/icu-messageformat-parser/-/icu-messageformat-parser-2.11.2.tgz",
+ "integrity": "sha512-AfiMi5NOSo2TQImsYAg8UYddsNJ/vUEv/HaNqiFjnI3ZFfWihUtD5QtuX6kHl8+H+d3qvnE/3HZrfzgdWpsLNA==",
+ "license": "MIT",
+ "dependencies": {
+ "@formatjs/ecma402-abstract": "2.3.4",
+ "@formatjs/icu-skeleton-parser": "1.8.14",
+ "tslib": "^2.8.0"
+ }
+ },
+ "node_modules/@formatjs/icu-skeleton-parser": {
+ "version": "1.8.14",
+ "resolved": "https://registry.npmjs.org/@formatjs/icu-skeleton-parser/-/icu-skeleton-parser-1.8.14.tgz",
+ "integrity": "sha512-i4q4V4qslThK4Ig8SxyD76cp3+QJ3sAqr7f6q9VVfeGtxG9OhiAk3y9XF6Q41OymsKzsGQ6OQQoJNY4/lI8TcQ==",
+ "license": "MIT",
+ "dependencies": {
+ "@formatjs/ecma402-abstract": "2.3.4",
+ "tslib": "^2.8.0"
+ }
+ },
+ "node_modules/@formatjs/intl-localematcher": {
+ "version": "0.6.1",
+ "resolved": "https://registry.npmjs.org/@formatjs/intl-localematcher/-/intl-localematcher-0.6.1.tgz",
+ "integrity": "sha512-ePEgLgVCqi2BBFnTMWPfIghu6FkbZnnBVhO2sSxvLfrdFw7wCHAHiDoM2h4NRgjbaY7+B7HgOLZGkK187pZTZg==",
+ "license": "MIT",
+ "dependencies": {
+ "tslib": "^2.8.0"
+ }
+ },
"node_modules/@fortawesome/fontawesome-common-types": {
"version": "6.7.2",
"resolved": "https://registry.npmjs.org/@fortawesome/fontawesome-common-types/-/fontawesome-common-types-6.7.2.tgz",
@@ -1632,6 +1725,43 @@
"url": "https://github.com/sponsors/nzakas"
}
},
+ "node_modules/@internationalized/date": {
+ "version": "3.7.0",
+ "resolved": "https://registry.npmjs.org/@internationalized/date/-/date-3.7.0.tgz",
+ "integrity": "sha512-VJ5WS3fcVx0bejE/YHfbDKR/yawZgKqn/if+oEeLqNwBtPzVB06olkfcnojTmEMX+gTpH+FlQ69SHNitJ8/erQ==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@swc/helpers": "^0.5.0"
+ }
+ },
+ "node_modules/@internationalized/message": {
+ "version": "3.1.6",
+ "resolved": "https://registry.npmjs.org/@internationalized/message/-/message-3.1.6.tgz",
+ "integrity": "sha512-JxbK3iAcTIeNr1p0WIFg/wQJjIzJt9l/2KNY/48vXV7GRGZSv3zMxJsce008fZclk2cDC8y0Ig3odceHO7EfNQ==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@swc/helpers": "^0.5.0",
+ "intl-messageformat": "^10.1.0"
+ }
+ },
+ "node_modules/@internationalized/number": {
+ "version": "3.6.0",
+ "resolved": "https://registry.npmjs.org/@internationalized/number/-/number-3.6.0.tgz",
+ "integrity": "sha512-PtrRcJVy7nw++wn4W2OuePQQfTqDzfusSuY1QTtui4wa7r+rGVtR75pO8CyKvHvzyQYi3Q1uO5sY0AsB4e65Bw==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@swc/helpers": "^0.5.0"
+ }
+ },
+ "node_modules/@internationalized/string": {
+ "version": "3.2.5",
+ "resolved": "https://registry.npmjs.org/@internationalized/string/-/string-3.2.5.tgz",
+ "integrity": "sha512-rKs71Zvl2OKOHM+mzAFMIyqR5hI1d1O6BBkMK2/lkfg3fkmVh9Eeg0awcA8W2WqYqDOv6a86DIOlFpggwLtbuw==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@swc/helpers": "^0.5.0"
+ }
+ },
"node_modules/@isaacs/cliui": {
"version": "8.0.2",
"resolved": "https://registry.npmjs.org/@isaacs/cliui/-/cliui-8.0.2.tgz",
@@ -2433,6 +2563,132 @@
"dev": true,
"license": "MIT"
},
+ "node_modules/@react-aria/focus": {
+ "version": "3.20.1",
+ "resolved": "https://registry.npmjs.org/@react-aria/focus/-/focus-3.20.1.tgz",
+ "integrity": "sha512-lgYs+sQ1TtBrAXnAdRBQrBo0/7o5H6IrfDxec1j+VRpcXL0xyk0xPq+m3lZp8typzIghqDgpnKkJ5Jf4OrzPIw==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@react-aria/interactions": "^3.24.1",
+ "@react-aria/utils": "^3.28.1",
+ "@react-types/shared": "^3.28.0",
+ "@swc/helpers": "^0.5.0",
+ "clsx": "^2.0.0"
+ },
+ "peerDependencies": {
+ "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1",
+ "react-dom": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1"
+ }
+ },
+ "node_modules/@react-aria/i18n": {
+ "version": "3.12.7",
+ "resolved": "https://registry.npmjs.org/@react-aria/i18n/-/i18n-3.12.7.tgz",
+ "integrity": "sha512-eLbYO2xrpeOKIEmLv2KD5LFcB0wltFqS+pUjsOzkKZg6H3b6AFDmJPxr/a0x2KGHtpGJvuHwCSbpPi9PzSSQLg==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@internationalized/date": "^3.7.0",
+ "@internationalized/message": "^3.1.6",
+ "@internationalized/number": "^3.6.0",
+ "@internationalized/string": "^3.2.5",
+ "@react-aria/ssr": "^3.9.7",
+ "@react-aria/utils": "^3.28.1",
+ "@react-types/shared": "^3.28.0",
+ "@swc/helpers": "^0.5.0"
+ },
+ "peerDependencies": {
+ "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1",
+ "react-dom": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1"
+ }
+ },
+ "node_modules/@react-aria/interactions": {
+ "version": "3.24.1",
+ "resolved": "https://registry.npmjs.org/@react-aria/interactions/-/interactions-3.24.1.tgz",
+ "integrity": "sha512-OWEcIC6UQfWq4Td5Ptuh4PZQ4LHLJr/JL2jGYvuNL6EgL3bWvzPrRYIF/R64YbfVxIC7FeZpPSkS07sZ93/NoA==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@react-aria/ssr": "^3.9.7",
+ "@react-aria/utils": "^3.28.1",
+ "@react-stately/flags": "^3.1.0",
+ "@react-types/shared": "^3.28.0",
+ "@swc/helpers": "^0.5.0"
+ },
+ "peerDependencies": {
+ "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1",
+ "react-dom": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1"
+ }
+ },
+ "node_modules/@react-aria/overlays": {
+ "version": "3.26.1",
+ "resolved": "https://registry.npmjs.org/@react-aria/overlays/-/overlays-3.26.1.tgz",
+ "integrity": "sha512-AtQ0mp+H0alFFkojKBADEUIc1AKFsSobH4QNoxQa3V4bZKQoXxga7cRhD5RRYanu3XCQOkIxZJ3vdVK/LVVBXA==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@react-aria/focus": "^3.20.1",
+ "@react-aria/i18n": "^3.12.7",
+ "@react-aria/interactions": "^3.24.1",
+ "@react-aria/ssr": "^3.9.7",
+ "@react-aria/utils": "^3.28.1",
+ "@react-aria/visually-hidden": "^3.8.21",
+ "@react-stately/overlays": "^3.6.14",
+ "@react-types/button": "^3.11.0",
+ "@react-types/overlays": "^3.8.13",
+ "@react-types/shared": "^3.28.0",
+ "@swc/helpers": "^0.5.0"
+ },
+ "peerDependencies": {
+ "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1",
+ "react-dom": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1"
+ }
+ },
+ "node_modules/@react-aria/ssr": {
+ "version": "3.9.7",
+ "resolved": "https://registry.npmjs.org/@react-aria/ssr/-/ssr-3.9.7.tgz",
+ "integrity": "sha512-GQygZaGlmYjmYM+tiNBA5C6acmiDWF52Nqd40bBp0Znk4M4hP+LTmI0lpI1BuKMw45T8RIhrAsICIfKwZvi2Gg==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@swc/helpers": "^0.5.0"
+ },
+ "engines": {
+ "node": ">= 12"
+ },
+ "peerDependencies": {
+ "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1"
+ }
+ },
+ "node_modules/@react-aria/utils": {
+ "version": "3.28.1",
+ "resolved": "https://registry.npmjs.org/@react-aria/utils/-/utils-3.28.1.tgz",
+ "integrity": "sha512-mnHFF4YOVu9BRFQ1SZSKfPhg3z+lBRYoW5mLcYTQihbKhz48+I1sqRkP7ahMITr8ANH3nb34YaMME4XWmK2Mgg==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@react-aria/ssr": "^3.9.7",
+ "@react-stately/flags": "^3.1.0",
+ "@react-stately/utils": "^3.10.5",
+ "@react-types/shared": "^3.28.0",
+ "@swc/helpers": "^0.5.0",
+ "clsx": "^2.0.0"
+ },
+ "peerDependencies": {
+ "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1",
+ "react-dom": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1"
+ }
+ },
+ "node_modules/@react-aria/visually-hidden": {
+ "version": "3.8.21",
+ "resolved": "https://registry.npmjs.org/@react-aria/visually-hidden/-/visually-hidden-3.8.21.tgz",
+ "integrity": "sha512-iii5qO+cVHrHiOeiBYCnTRUQG2eOgEPFmiMG4dAuby8+pJJ8U4BvffX2sDTYWL6ztLLBYyrsUHPSw1Ld03JhmA==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@react-aria/interactions": "^3.24.1",
+ "@react-aria/utils": "^3.28.1",
+ "@react-types/shared": "^3.28.0",
+ "@swc/helpers": "^0.5.0"
+ },
+ "peerDependencies": {
+ "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1",
+ "react-dom": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1"
+ }
+ },
"node_modules/@react-router/dev": {
"version": "7.3.0",
"resolved": "https://registry.npmjs.org/@react-router/dev/-/dev-7.3.0.tgz",
@@ -2583,6 +2839,74 @@
"react-router": "7.3.0"
}
},
+ "node_modules/@react-stately/flags": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/@react-stately/flags/-/flags-3.1.0.tgz",
+ "integrity": "sha512-KSHOCxTFpBtxhIRcKwsD1YDTaNxFtCYuAUb0KEihc16QwqZViq4hasgPBs2gYm7fHRbw7WYzWKf6ZSo/+YsFlg==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@swc/helpers": "^0.5.0"
+ }
+ },
+ "node_modules/@react-stately/overlays": {
+ "version": "3.6.14",
+ "resolved": "https://registry.npmjs.org/@react-stately/overlays/-/overlays-3.6.14.tgz",
+ "integrity": "sha512-RRalTuHdwrKO1BmXKaqBtE1GGUXU4VUAWwgh4lsP2EFSixDHmOVLxHFDWYvOPChBhpi8KXfLEgm6DEgPBvLBZQ==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@react-stately/utils": "^3.10.5",
+ "@react-types/overlays": "^3.8.13",
+ "@swc/helpers": "^0.5.0"
+ },
+ "peerDependencies": {
+ "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1"
+ }
+ },
+ "node_modules/@react-stately/utils": {
+ "version": "3.10.5",
+ "resolved": "https://registry.npmjs.org/@react-stately/utils/-/utils-3.10.5.tgz",
+ "integrity": "sha512-iMQSGcpaecghDIh3mZEpZfoFH3ExBwTtuBEcvZ2XnGzCgQjeYXcMdIUwAfVQLXFTdHUHGF6Gu6/dFrYsCzySBQ==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@swc/helpers": "^0.5.0"
+ },
+ "peerDependencies": {
+ "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1"
+ }
+ },
+ "node_modules/@react-types/button": {
+ "version": "3.11.0",
+ "resolved": "https://registry.npmjs.org/@react-types/button/-/button-3.11.0.tgz",
+ "integrity": "sha512-gJh5i0JiBiZGZGDo+tXMp6xbixPM7IKZ0sDuxTYBG49qNzzWJq0uNYltO3emwSVXFSsBgRV/Wu8kQGhfuN7wIw==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@react-types/shared": "^3.28.0"
+ },
+ "peerDependencies": {
+ "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1"
+ }
+ },
+ "node_modules/@react-types/overlays": {
+ "version": "3.8.13",
+ "resolved": "https://registry.npmjs.org/@react-types/overlays/-/overlays-3.8.13.tgz",
+ "integrity": "sha512-xgT843KIh1otvYPQ6kCGTVUICiMF5UQ7SZUQZd4Zk3VtiFIunFVUvTvL03cpt0026UmY7tbv7vFrPKcT6xjsjw==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@react-types/shared": "^3.28.0"
+ },
+ "peerDependencies": {
+ "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1"
+ }
+ },
+ "node_modules/@react-types/shared": {
+ "version": "3.28.0",
+ "resolved": "https://registry.npmjs.org/@react-types/shared/-/shared-3.28.0.tgz",
+ "integrity": "sha512-9oMEYIDc3sk0G5rysnYvdNrkSg7B04yTKl50HHSZVbokeHpnU0yRmsDaWb9B/5RprcKj8XszEk5guBO8Sa/Q+Q==",
+ "license": "Apache-2.0",
+ "peerDependencies": {
+ "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1"
+ }
+ },
"node_modules/@redocly/ajv": {
"version": "8.11.2",
"resolved": "https://registry.npmjs.org/@redocly/ajv/-/ajv-8.11.2.tgz",
@@ -2963,6 +3287,15 @@
"integrity": "sha512-83yeghZ2xxin3Nj8z1NMd/NCuca+gsYXswywDy5bHvwlWL8tpTQmzGeUuHd9FC3E/SBEMvzJRwWEOz5gGes9Qg==",
"license": "MIT"
},
+ "node_modules/@swc/helpers": {
+ "version": "0.5.15",
+ "resolved": "https://registry.npmjs.org/@swc/helpers/-/helpers-0.5.15.tgz",
+ "integrity": "sha512-JQ5TuMi45Owi4/BIMAJBoSQoOJu12oOk/gADqlcUL9JEdHB8vyjUSsxqeNXnmXHjYKMi2WcYtezGEEhqUI/E2g==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "tslib": "^2.8.0"
+ }
+ },
"node_modules/@tailwindcss/node": {
"version": "4.0.12",
"resolved": "https://registry.npmjs.org/@tailwindcss/node/-/node-4.0.12.tgz",
@@ -4262,7 +4595,6 @@
"version": "2.1.1",
"resolved": "https://registry.npmjs.org/clsx/-/clsx-2.1.1.tgz",
"integrity": "sha512-eYm0QWBtUrBWZWG0d386OGAw16Z995PiOVo2B7bjWSbHedGl5e0ZWaq65kOGgUSNesEIDkB9ISbTg/JK9dhCZA==",
- "dev": true,
"license": "MIT",
"engines": {
"node": ">=6"
@@ -4769,6 +5101,12 @@
}
}
},
+ "node_modules/decimal.js": {
+ "version": "10.5.0",
+ "resolved": "https://registry.npmjs.org/decimal.js/-/decimal.js-10.5.0.tgz",
+ "integrity": "sha512-8vDa8Qxvr/+d94hSh5P3IJwI5t8/c0KsMp+g8bNw9cY2icONa5aPfvKeieW1WlG0WQYwwhJ7mjui2xtiePQSXw==",
+ "license": "MIT"
+ },
"node_modules/decode-named-character-reference": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/decode-named-character-reference/-/decode-named-character-reference-1.1.0.tgz",
@@ -6552,6 +6890,18 @@
"node": ">= 0.4"
}
},
+ "node_modules/intl-messageformat": {
+ "version": "10.7.16",
+ "resolved": "https://registry.npmjs.org/intl-messageformat/-/intl-messageformat-10.7.16.tgz",
+ "integrity": "sha512-UmdmHUmp5CIKKjSoE10la5yfU+AYJAaiYLsodbjL4lji83JNvgOQUjGaGhGrpFCb0Uh7sl7qfP1IyILa8Z40ug==",
+ "license": "BSD-3-Clause",
+ "dependencies": {
+ "@formatjs/ecma402-abstract": "2.3.4",
+ "@formatjs/fast-memoize": "2.2.7",
+ "@formatjs/icu-messageformat-parser": "2.11.2",
+ "tslib": "^2.8.0"
+ }
+ },
"node_modules/ipaddr.js": {
"version": "1.9.1",
"resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz",
@@ -9480,7 +9830,6 @@
"version": "0.14.1",
"resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.14.1.tgz",
"integrity": "sha512-dYnhHh0nJoMfnkZs6GmmhFknAGRrLznOu5nc9ML+EJxGvrx6H7teuevqVqCuPcPK//3eDrrjQhehXVx9cnkGdw==",
- "devOptional": true,
"license": "MIT"
},
"node_modules/regex": {
@@ -10436,6 +10785,12 @@
"url": "https://github.com/sponsors/ljharb"
}
},
+ "node_modules/tabbable": {
+ "version": "6.2.0",
+ "resolved": "https://registry.npmjs.org/tabbable/-/tabbable-6.2.0.tgz",
+ "integrity": "sha512-Cat63mxsVJlzYvN51JmVXIgNoUokrIaT2zLclCXjRd8boZ0004U4KCs/sToJ75C6sdlByWxpYnb5Boif1VSFew==",
+ "license": "MIT"
+ },
"node_modules/tailwindcss": {
"version": "4.0.12",
"resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-4.0.12.tgz",
@@ -10523,7 +10878,6 @@
"version": "2.8.1",
"resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz",
"integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==",
- "dev": true,
"license": "0BSD"
},
"node_modules/turbo-stream": {
@@ -10918,6 +11272,15 @@
}
}
},
+ "node_modules/use-sync-external-store": {
+ "version": "1.4.0",
+ "resolved": "https://registry.npmjs.org/use-sync-external-store/-/use-sync-external-store-1.4.0.tgz",
+ "integrity": "sha512-9WXSPC5fMv61vaupRkCKCxsPxBocVnwakBEkMIHHpkTTg6icbJtg6jzgtLDm4bl3cSHAca52rYWih0k4K3PfHw==",
+ "license": "MIT",
+ "peerDependencies": {
+ "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0"
+ }
+ },
"node_modules/util-deprecate": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz",
diff --git a/frontend/package.json b/frontend/package.json
index 5fcb574..d692339 100644
--- a/frontend/package.json
+++ b/frontend/package.json
@@ -15,6 +15,7 @@
"start": "react-router-serve ./build/server/index.js"
},
"dependencies": {
+ "@base-ui-components/react": "^1.0.0-alpha.7",
"@fortawesome/fontawesome-svg-core": "^6.7.2",
"@fortawesome/free-solid-svg-icons": "^6.7.2",
"@fortawesome/react-fontawesome": "^0.2.2",