diff --git a/CHANGELOG.md b/CHANGELOG.md index 058c05d..1bf5bf1 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,7 +5,18 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). -## [2.11.5] - Current +## [2.12.0] - Current + +### Added + +- Login via Auth0 (currently useless, but this enables future features) +- App title in header + +### Fixed + +- Fixed display of Custom Sort instructions on mobile devices + +## [2.11.5] - 2025-04-03 ### Added diff --git a/README.md b/README.md index d35ad79..ddee4e2 100644 --- a/README.md +++ b/README.md @@ -50,3 +50,7 @@ Data and images from Elden Ring which are used in this project are the property Based on [erdtree](https://github.com/vodofrede/erdtree) by [@vodofrede](https://github.com/vodofrede) Weapon attack rating calculations feature some cannibalization of [Elden Ring Weapon Calculator](https://github.com/ThomasJClark/elden-ring-weapon-calculator) by [Thomas J Clark](https://github.com/ThomasJClark). + +Authentication provided by [Auth0](https://auth0.com). + +Mantinia Regular font provided by [fontsgeek.com](https://fontsgeek.com). diff --git a/__tests__/src/app/util/components/NavLinks.test.tsx b/__tests__/src/app/util/components/NavLinks.test.tsx index 8c13f0d..1270701 100644 --- a/__tests__/src/app/util/components/NavLinks.test.tsx +++ b/__tests__/src/app/util/components/NavLinks.test.tsx @@ -1,14 +1,31 @@ import "core-js/actual/structured-clone"; import { NavLinks } from "@/app/util/components/NavLinks"; +import { useUser } from "@auth0/nextjs-auth0/client"; import { render, screen } from "@testing-library/react"; import { usePathname } from "next/navigation"; +// mock the next/navigation usePathname hook jest.mock("next/navigation", () => ({ usePathname: jest.fn(), })); +// mock the auth0 useUser hook +jest.mock("@auth0/nextjs-auth0/client", () => ({ + useUser: jest.fn(), +})); describe("NavLinks", () => { + beforeEach(() => { + // mock the next/navigation usePathname hook + (usePathname as jest.Mock).mockReturnValue("/"); + // mock the auth0 useUser hook + (useUser as jest.Mock).mockReturnValue({ + user: null, + isLoading: false, + error: null, + }); + }); + test("Renders", () => { render(); @@ -58,4 +75,20 @@ describe("NavLinks", () => { expect(screen.getByText("About")).toHaveClass("current"); }); + + test("logged in", () => { + // mock the auth0 useUser hook + (useUser as jest.Mock).mockReturnValue({ + user: { + name: "test", + picture: "/favicon.ico", + email: "test@email.com", + }, + error: null, + isLoading: false, + }); + render(); + + expect(screen.getByText("Logout")).toBeInTheDocument(); + }); }); diff --git a/package-lock.json b/package-lock.json index d3eb61e..d01c63e 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,13 +1,14 @@ { "name": "haligtree", - "version": "2.11.2", + "version": "2.12.0", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "haligtree", - "version": "2.11.2", + "version": "2.12.0", "dependencies": { + "@auth0/nextjs-auth0": "^3.7.0", "@tailwindcss/postcss": "^4.1.0", "@vercel/analytics": "^1", "@vercel/speed-insights": "^1", @@ -71,6 +72,35 @@ "node": ">=6.0.0" } }, + "node_modules/@auth0/nextjs-auth0": { + "version": "3.7.0", + "resolved": "https://registry.npmjs.org/@auth0/nextjs-auth0/-/nextjs-auth0-3.7.0.tgz", + "integrity": "sha512-MxJl2rf3j09bwugggVBmrzOhO8H4yv7lZbXe7xPuQSYTuk1jJjjofHEQrZiOJnYV9dZbjYvNhEunFRFJM1PyVw==", + "license": "MIT", + "dependencies": { + "@panva/hkdf": "^1.0.2", + "cookie": "^0.7.1", + "debug": "^4.3.4", + "joi": "^17.6.0", + "jose": "^4.9.2", + "oauth4webapi": "^2.3.0", + "openid-client": "^5.2.1", + "tslib": "^2.4.0", + "url-join": "^4.0.1" + }, + "engines": { + "node": ">=16" + }, + "peerDependencies": { + "next": "^10.0.0 || ^11.0.0 || ^12.3.5 || ^13.5.9 || ^14.2.25 || ^15.2.3" + } + }, + "node_modules/@auth0/nextjs-auth0/node_modules/tslib": { + "version": "2.8.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", + "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==", + "license": "0BSD" + }, "node_modules/@babel/code-frame": { "version": "7.26.2", "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.26.2.tgz", @@ -922,14 +952,12 @@ "version": "9.3.0", "resolved": "https://registry.npmjs.org/@hapi/hoek/-/hoek-9.3.0.tgz", "integrity": "sha512-/c6rf4UJlmHlC9b5BaNvzAcFv7HZ2QHaV0D4/HNlBdvFnvQq8RI4kYdhyPCl7Xj+oWvTWQ8ujhqS53LIgAe6KQ==", - "dev": true, "license": "BSD-3-Clause" }, "node_modules/@hapi/topo": { "version": "5.1.0", "resolved": "https://registry.npmjs.org/@hapi/topo/-/topo-5.1.0.tgz", "integrity": "sha512-foQZKJig7Ob0BMAYBfcJk8d77QtOe7Wo4ox7ff1lQYoNNAb6jwcY1ncdoy2e9wQZzvNy7ODZCYJkK8kzmcAnAg==", - "dev": true, "license": "BSD-3-Clause", "dependencies": { "@hapi/hoek": "^9.0.0" @@ -2136,6 +2164,15 @@ "node": ">=12.4.0" } }, + "node_modules/@panva/hkdf": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/@panva/hkdf/-/hkdf-1.2.1.tgz", + "integrity": "sha512-6oclG6Y3PiDFcoyk8srjLfVKyMfVCKJ27JwNPViuXziFpmdz+MZnZN/aKY0JGXgYuO/VghU0jcOAZgWXZ1Dmrw==", + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/panva" + } + }, "node_modules/@paulirish/trace_engine": { "version": "0.0.23", "resolved": "https://registry.npmjs.org/@paulirish/trace_engine/-/trace_engine-0.0.23.tgz", @@ -2402,7 +2439,6 @@ "version": "4.1.5", "resolved": "https://registry.npmjs.org/@sideway/address/-/address-4.1.5.tgz", "integrity": "sha512-IqO/DUQHUkPeixNQ8n0JA6102hT9CmaljNTPmQ1u8MEhBo/R4Q8eKLN/vGZxuebwOroDB4cbpjheD4+/sKFK4Q==", - "dev": true, "license": "BSD-3-Clause", "dependencies": { "@hapi/hoek": "^9.0.0" @@ -2412,14 +2448,12 @@ "version": "3.0.1", "resolved": "https://registry.npmjs.org/@sideway/formula/-/formula-3.0.1.tgz", "integrity": "sha512-/poHZJJVjx3L+zVD6g9KgHfYnb443oi7wLu/XKojDviHy6HOEOA6z1Trk5aR1dGcmPenJEgb2sK2I80LeS3MIg==", - "dev": true, "license": "BSD-3-Clause" }, "node_modules/@sideway/pinpoint": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/@sideway/pinpoint/-/pinpoint-2.0.0.tgz", "integrity": "sha512-RNiOoTPkptFtSVzQevY/yWtZwf/RxyVnPy/OcA9HBM3MlGDnBEYL5B41H0MTn0Uec8Hi+2qUtTfG2WWZBmMejQ==", - "dev": true, "license": "BSD-3-Clause" }, "node_modules/@sinclair/typebox": { @@ -5053,7 +5087,6 @@ "version": "0.7.1", "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.7.1.tgz", "integrity": "sha512-6DnInpx7SJ2AK3+CTUE/ZM0vWTUboZCegxhC2xiIydHR9jNuTAASBrfEpHhiGOZw/nX51bHt6YQl8jsGo4y/0w==", - "dev": true, "license": "MIT", "engines": { "node": ">= 0.6" @@ -9391,7 +9424,6 @@ "version": "17.13.3", "resolved": "https://registry.npmjs.org/joi/-/joi-17.13.3.tgz", "integrity": "sha512-otDA4ldcIx+ZXsKHWmp0YizCweVRZG96J10b0FevjfuncLO1oX59THoAmHkNubYJ+9gWsYsp5k8v4ib6oDv1fA==", - "dev": true, "license": "BSD-3-Clause", "dependencies": { "@hapi/hoek": "^9.3.0", @@ -9401,6 +9433,15 @@ "@sideway/pinpoint": "^2.0.0" } }, + "node_modules/jose": { + "version": "4.15.9", + "resolved": "https://registry.npmjs.org/jose/-/jose-4.15.9.tgz", + "integrity": "sha512-1vUQX+IdDMVPj4k8kOxgUqlcK518yluMuGZwqlr44FS1ppZB/5GWh4rZG89erpOBOJjU/OBsnCVFfapsRz6nEA==", + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/panva" + } + }, "node_modules/jpeg-js": { "version": "0.4.4", "resolved": "https://registry.npmjs.org/jpeg-js/-/jpeg-js-0.4.4.tgz", @@ -11255,6 +11296,15 @@ "dev": true, "license": "MIT" }, + "node_modules/oauth4webapi": { + "version": "2.17.0", + "resolved": "https://registry.npmjs.org/oauth4webapi/-/oauth4webapi-2.17.0.tgz", + "integrity": "sha512-lbC0Z7uzAFNFyzEYRIC+pkSVvDHJTbEW+dYlSBAlCYDe6RxUkJ26bClhk8ocBZip1wfI9uKTe0fm4Ib4RHn6uQ==", + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/panva" + } + }, "node_modules/object-assign": { "version": "4.1.1", "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", @@ -11265,6 +11315,15 @@ "node": ">=0.10.0" } }, + "node_modules/object-hash": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/object-hash/-/object-hash-2.2.0.tgz", + "integrity": "sha512-gScRMn0bS5fH+IuwyIFgnh9zBdo4DV+6GhygmWM9HyNJSgS0hScp1f5vjtm7oIIOiT9trXrShAkLFSc2IqKNgw==", + "license": "MIT", + "engines": { + "node": ">= 6" + } + }, "node_modules/object-inspect": { "version": "1.13.4", "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.4.tgz", @@ -11378,6 +11437,15 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/oidc-token-hash": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/oidc-token-hash/-/oidc-token-hash-5.1.0.tgz", + "integrity": "sha512-y0W+X7Ppo7oZX6eovsRkuzcSM40Bicg2JEJkDJ4irIt1wsYAP5MLSNv+QAogO8xivMffw/9OvV3um1pxXgt1uA==", + "license": "MIT", + "engines": { + "node": "^10.13.0 || >=12.0.0" + } + }, "node_modules/on-finished": { "version": "2.4.1", "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.4.1.tgz", @@ -11444,6 +11512,39 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/openid-client": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/openid-client/-/openid-client-5.7.1.tgz", + "integrity": "sha512-jDBPgSVfTnkIh71Hg9pRvtJc6wTwqjRkN88+gCFtYWrlP4Yx2Dsrow8uPi3qLr/aeymPF3o2+dS+wOpglK04ew==", + "license": "MIT", + "dependencies": { + "jose": "^4.15.9", + "lru-cache": "^6.0.0", + "object-hash": "^2.2.0", + "oidc-token-hash": "^5.0.3" + }, + "funding": { + "url": "https://github.com/sponsors/panva" + } + }, + "node_modules/openid-client/node_modules/lru-cache": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "license": "ISC", + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/openid-client/node_modules/yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "license": "ISC" + }, "node_modules/optionator": { "version": "0.9.4", "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.4.tgz", @@ -14215,6 +14316,12 @@ "punycode": "^2.1.0" } }, + "node_modules/url-join": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/url-join/-/url-join-4.0.1.tgz", + "integrity": "sha512-jk1+QP6ZJqyOiuEI9AEWQfju/nB2Pw466kbA0LEZljHwKeMgd9WrAEgEGxjPDD2+TNbbb37rTyhEfrCXfuKXnA==", + "license": "MIT" + }, "node_modules/url-parse": { "version": "1.5.10", "resolved": "https://registry.npmjs.org/url-parse/-/url-parse-1.5.10.tgz", diff --git a/package.json b/package.json index 31e459a..620cb40 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "haligtree", - "version": "2.11.4", + "version": "2.12.0", "private": true, "scripts": { "dev": "next dev", @@ -13,6 +13,7 @@ "lighthouse": "next build && next start -p 3000 & npx wait-on http://localhost:3000 && npx lhci autorun" }, "dependencies": { + "@auth0/nextjs-auth0": "^3.7.0", "@tailwindcss/postcss": "^4.1.0", "@vercel/analytics": "^1", "@vercel/speed-insights": "^1", diff --git a/public/fonts/Mantinia Regular.otf b/public/fonts/Mantinia Regular.otf new file mode 100644 index 0000000..e68802d Binary files /dev/null and b/public/fonts/Mantinia Regular.otf differ diff --git a/src/app/armor/components/customSortBy/CustomizeSortBy.tsx b/src/app/armor/components/customSortBy/CustomizeSortBy.tsx index c16fc9b..5b8687e 100644 --- a/src/app/armor/components/customSortBy/CustomizeSortBy.tsx +++ b/src/app/armor/components/customSortBy/CustomizeSortBy.tsx @@ -1,4 +1,5 @@ import { useState } from "react"; +import { JSX } from "react/jsx-runtime"; import FormulaField from "./FormulaField"; import { SortByArmor, unmarshallSortBy } from "./sorting"; @@ -6,7 +7,7 @@ export function CustomizeSortBy(props: { closePopUp: () => void; setCustomSortBy: (newSortBy: SortByArmor) => void; sortBy: SortByArmor; -}) { +}): JSX.Element { const [descriptionIsExpanded, setDescriptionIsExpanded] = useState(true); @@ -83,7 +84,12 @@ export function CustomizeSortBy(props: {
  • ( X )
      -
    • +
    • The parentheses will group things into one value. This is useful for separating values when trying to ensure an order of @@ -94,7 +100,12 @@ export function CustomizeSortBy(props: {
    • AVG( X X ... )
        -
      • +
      • This will average all space-separated values inside the parentheses. Note that more than one value is required. @@ -104,7 +115,12 @@ export function CustomizeSortBy(props: {
      • SUM( X X ... )
          -
        • +
        • This will sum all space-separated values inside the parentheses. Note that more than one value is required. @@ -114,7 +130,12 @@ export function CustomizeSortBy(props: {
        • MULT( X X ... )
            -
          • +
          • This will multiply all space-separated values inside the parentheses. Note that more than one value is required. @@ -124,7 +145,12 @@ export function CustomizeSortBy(props: {
          • PHYSICAL
              -
            • +
            • This will use the value of an armor piece's Physical Absorption.
            • @@ -133,7 +159,12 @@ export function CustomizeSortBy(props: {
            • STRIKE
                -
              • +
              • This will use the value of an armor piece's Strike Absorption.
              • @@ -142,7 +173,12 @@ export function CustomizeSortBy(props: {
              • SLASH
                  -
                • +
                • This will use the value of an armor piece's Slash Absorption.
                • @@ -151,7 +187,12 @@ export function CustomizeSortBy(props: {
                • PIERCE
                    -
                  • +
                  • This will use the value of an armor piece's Pierce Absorption.
                  • @@ -160,7 +201,12 @@ export function CustomizeSortBy(props: {
                  • MAGIC
                      -
                    • +
                    • This will use the value of an armor piece's Magic Absorption.
                    • @@ -169,7 +215,12 @@ export function CustomizeSortBy(props: {
                    • FIRE
                        -
                      • +
                      • This will use the value of an armor piece's Fire Absorption.
                      • @@ -178,7 +229,12 @@ export function CustomizeSortBy(props: {
                      • LIGHTNING
                          -
                        • +
                        • This will use the value of an armor piece's Lightning Absorption.
                        • @@ -187,7 +243,12 @@ export function CustomizeSortBy(props: {
                        • HOLY
                            -
                          • +
                          • This will use the value of an armor piece's Holy Absorption.
                          • @@ -196,7 +257,12 @@ export function CustomizeSortBy(props: {
                          • POISON
                              -
                            • +
                            • This will use the value of the armor piece's Poison Resistance.
                            • @@ -205,7 +271,12 @@ export function CustomizeSortBy(props: {
                            • SCARLETROT
                                -
                              • +
                              • This will use the value of the armor piece's Scarlet Rot Resistance.
                              • @@ -214,7 +285,12 @@ export function CustomizeSortBy(props: {
                              • HEMORRHAGE
                                  -
                                • +
                                • This will use the value of the armor piece's Hemorrhage Resistance.
                                • @@ -223,7 +299,12 @@ export function CustomizeSortBy(props: {
                                • FROSTBITE
                                    -
                                  • +
                                  • This will use the value of the armor piece's Frostbite Resistance.
                                  • @@ -232,7 +313,12 @@ export function CustomizeSortBy(props: {
                                  • SLEEP
                                      -
                                    • +
                                    • This will use the value of the armor piece's Sleep Resistance.
                                    • @@ -241,7 +327,12 @@ export function CustomizeSortBy(props: {
                                    • MADNESS
                                        -
                                      • +
                                      • This will use the value of the armor piece's Madness Resistance.
                                      • @@ -250,7 +341,12 @@ export function CustomizeSortBy(props: {
                                      • DEATHBLIGHT
                                          -
                                        • +
                                        • This will use the value of the armor piece's Death Blight Resistance.
                                        • @@ -259,7 +355,12 @@ export function CustomizeSortBy(props: {
                                        • POISE
                                            -
                                          • +
                                          • This will use the value of the armor piece's Poise.
                                          • diff --git a/src/app/globals.css b/src/app/globals.css index b10b19e..e2c47cd 100644 --- a/src/app/globals.css +++ b/src/app/globals.css @@ -34,6 +34,13 @@ html { } } +@font-face { + font-family: "Mantinia"; + src: url("/fonts/Mantinia Regular.otf") format("truetype"); + font-weight: normal; + font-style: normal; +} + /* fix sizing and remove margins and padding */ html { box-sizing: border-box; diff --git a/src/app/layout.tsx b/src/app/layout.tsx index 2466777..ef51886 100644 --- a/src/app/layout.tsx +++ b/src/app/layout.tsx @@ -1,3 +1,4 @@ +import { UserProvider } from "@auth0/nextjs-auth0/client"; import { Analytics } from "@vercel/analytics/react"; import { SpeedInsights } from "@vercel/speed-insights/next"; import type { Metadata, Viewport } from "next"; @@ -19,7 +20,7 @@ export const viewport: Viewport = { initialScale: 1, }; -export default function RootLayout({ +export default async function RootLayout({ children, }: { children: React.ReactNode; @@ -31,51 +32,69 @@ export default function RootLayout({ }) || ""; return ( - - - {children} - - - -