From af1b3b02cd9911943b159d14107c4f6e7c391836 Mon Sep 17 00:00:00 2001 From: KeziahMoselle Date: Wed, 13 Mar 2024 10:32:22 +0100 Subject: [PATCH 1/9] refactor: migrate to static props --- .env.example | 5 - src/env.ts | 13 - src/libs/s3.ts | 42 - src/pages/admin/costumes-link.tsx | 432 --------- src/pages/database/stories/companions.tsx | 2 +- src/pages/database/stories/costumes.tsx | 2 +- src/pages/database/stories/memoirs.tsx | 2 +- src/pages/database/stories/weapons.tsx | 2 +- src/pages/loadout/[slug].tsx | 367 -------- src/pages/loadouts.tsx | 203 ----- .../[[...slug]].tsx => tierlists.tsx} | 2 +- src/pages/tools/loadout-builder.tsx | 761 ---------------- src/pages/tools/tierlist-builder/costumes.tsx | 845 ------------------ src/pages/tools/tierlist-builder/index.tsx | 58 -- src/pages/tools/tierlist-builder/weapons.tsx | 756 ---------------- 15 files changed, 5 insertions(+), 3487 deletions(-) delete mode 100644 src/libs/s3.ts delete mode 100644 src/pages/admin/costumes-link.tsx delete mode 100644 src/pages/loadout/[slug].tsx delete mode 100644 src/pages/loadouts.tsx rename src/pages/{tierlists/[[...slug]].tsx => tierlists.tsx} (99%) delete mode 100644 src/pages/tools/loadout-builder.tsx delete mode 100644 src/pages/tools/tierlist-builder/costumes.tsx delete mode 100644 src/pages/tools/tierlist-builder/index.tsx delete mode 100644 src/pages/tools/tierlist-builder/weapons.tsx diff --git a/.env.example b/.env.example index 22e22261..f727f77e 100644 --- a/.env.example +++ b/.env.example @@ -1,10 +1,5 @@ NODE_ENV=development|production -# S3 Bucket -S3_ACCESS_KEY=1S818EZOZ4BEX8UT06E1 -S3_SECRET_KEY=CRzsEo8XzmFu271DTzTbD33budBZ863T2sBEspkK -S3_ENDPOINT=s3.eu-central-1.wasabisys.com - # Dump database (costumes, weapons...) DATABASE_URL= diff --git a/src/env.ts b/src/env.ts index f246d037..1501f9a5 100644 --- a/src/env.ts +++ b/src/env.ts @@ -6,19 +6,6 @@ export const env = envsafe({ choices: ["development", "production"], }), - /** - * S3 Configuration - */ - S3_ACCESS_KEY: str({ - docs: "https://discord.com/channels/877257901146775603/877323861123809300/879707546372440104", - }), - S3_SECRET_KEY: str({ - docs: "https://discord.com/channels/877257901146775603/877323861123809300/879707546372440104", - }), - S3_ENDPOINT: str({ - default: "s3.eu-central-1.wasabisys.com", - }), - /** * API */ diff --git a/src/libs/s3.ts b/src/libs/s3.ts deleted file mode 100644 index 2dd92ebd..00000000 --- a/src/libs/s3.ts +++ /dev/null @@ -1,42 +0,0 @@ -import AWS from 'aws-sdk' -import axios from 'axios' -import { env } from '../env' - -AWS.config.update({ - accessKeyId: env.S3_ACCESS_KEY, - secretAccessKey: env.S3_SECRET_KEY, -}) - -const s3 = new AWS.S3({ - endpoint: env.S3_ENDPOINT -}) - -async function listModelsTypes() { - const { CommonPrefixes } = await listFolders() - - const types = CommonPrefixes.map(prefix => prefix.Prefix) - - return types -} - -function listFolders(prefix = null, delimiter = '/'): Promise { - return new Promise((resolve, reject) => { - s3.listObjectsV2({ - Bucket: 'models', - Delimiter: delimiter, - Prefix: prefix - }, (error, data) => { - if (error) { - return reject(error) - } - - resolve(data) - }) - }) -} - -export { - s3, - listModelsTypes, - listFolders, -} diff --git a/src/pages/admin/costumes-link.tsx b/src/pages/admin/costumes-link.tsx deleted file mode 100644 index bff531b0..00000000 --- a/src/pages/admin/costumes-link.tsx +++ /dev/null @@ -1,432 +0,0 @@ -import Layout from "@components/Layout"; -import Meta from "@components/Meta"; -import WeaponThumbnail from "@components/WeaponThumbnail"; -import CostumeThumbnail from "@components/CostumeThumbnail"; -import prisma from "@libs/prisma"; -import toast from "react-hot-toast"; -import { - character, - costume, - costume_ability, - costume_ability_link, - costume_skill, - costume_skill_link, - costume_stat, - debris, - emblem, - Prisma, - weapon, - weapon_ability, - weapon_ability_link, - weapon_skill, - weapon_skill_link, - weapon_stat, -} from "@prisma/client"; -import { costumes_link } from "@prisma/client-nrg"; -import { getAllCostumes } from "@models/costume"; -import { CDN_URL } from "@config/constants"; -import RARITY from "@utils/rarity"; -import WeaponSelect from "@components/weapons/WeaponSelect"; -import { useState } from "react"; -import axios from "axios"; -import produce from "immer"; -import getBaseRarity from "@utils/getBaseRarity"; -import { getAllEvents } from "@models/event"; -import { - Autocomplete, - FormControl, - InputBase, - InputLabel, - TextField, -} from "@mui/material"; -import { Event } from "@models/types"; -import MaterialTable from "@material-table/core"; -import { getAllWeapons } from "@models/weapon"; -import { Box } from "@mui/system"; -import Checkbox from "@components/form/Checkbox"; - -interface LoadoutBuilderProps { - costumes: (costume & { - costume_ability_link: (costume_ability_link & { - costume_ability: costume_ability; - })[]; - costume_skill_link: (costume_skill_link & { - costume_skill: costume_skill; - })[]; - costume_stat: costume_stat[]; - character: character; - emblem: emblem; - })[]; - weapons: (weapon & { - weapon_ability_link: (weapon_ability_link & { - weapon_ability: weapon_ability; - })[]; - weapon_skill_link: (weapon_skill_link & { - weapon_skill: weapon_skill; - })[]; - weapon_stat: weapon_stat[]; - })[]; - links: costumes_link[]; - events: Event[]; -} - -export default function AdminCostumesLink({ - costumes, - weapons, - links, - events, -}: LoadoutBuilderProps): JSX.Element { - const [newLinks, setNewLinks] = useState(links); - const [loading, setLoading] = useState(false); - - async function save() { - if (loading) return; - - try { - setLoading(true); - - await axios({ - url: "/api/costumes-link", - method: "POST", - data: { - costumes: newLinks, - }, - }); - - toast.success("Saved!"); - } catch (error) { - toast.error(error.message); - } finally { - setLoading(false); - } - } - - function updateField( - costume: costume & { - costume_ability_link: (costume_ability_link & { - costume_ability: costume_ability; - })[]; - costume_skill_link: (costume_skill_link & { - costume_skill: costume_skill; - })[]; - costume_stat: costume_stat[]; - character: character; - emblem: emblem; - }, - property: string, - value: any - ) { - setNewLinks( - produce(newLinks, (draft) => { - const linkedCostume = draft.find( - (link) => link?.costume_id === costume.costume_id - ); - - if (!linkedCostume) { - draft.push({ - // Set default values - costume_id: costume?.costume_id, - weapon_id: weapon?.weapon_id, - events: linkedCostume.events ?? [], - is_limited: costume?.is_limited ?? false, - is_collab: costume?.is_collab ?? false, - is_story: costume?.is_story ?? false, - is_ex: costume?.is_ex ?? false, - chapter: costume?.chapter ?? null, - // Override the new value - [property]: value, - }); - - return; - } - - linkedCostume[property] = value; - - console.log({ linkedCostume }); - }) - ); - - console.log({ newLinks }); - } - - return ( - - - -
- ( -
-
- - - {costume.is_ex_costume && ( - EX - )} - {costume.title} - -
-
- ), - customFilterAndSearch: (term, costume) => { - if (term.length === 0) return true; - return `${costume.character.name.toLowerCase()} ${costume.title.toLowerCase()}`.includes( - term.toLowerCase() - ); - }, - }, - { - field: "weapon", - title: "Associated Weapon", - type: "string", - render: (costume) => { - const link = newLinks.find( - (link) => link?.costume_id === costume.costume_id - ); - - const weaponLinked = weapons.find( - (weapon) => weapon.weapon_id === link?.weapon_id - ); - - return ( - - ); - }, - }, - { - field: "events", - title: "Costume sources", - type: "string", - render: (costume) => { - const link = newLinks.find( - (link) => link?.costume_id === costume.costume_id - ); - - const linkedEvents = (link?.events as Prisma.JsonArray) || []; - - const costumeEvents = events.filter((event) => - linkedEvents.includes(event.id) - ); - - return ( -
- {costumeEvents.map((event) => ( -
-

{event.attributes.title}

- event -
- ))} -
- ); - }, - }, - ]} - detailPanel={({ rowData: costume }) => { - const link = newLinks.find( - (link) => link?.costume_id === costume.costume_id - ); - - const weaponLinked = weapons.find( - (weapon) => weapon.weapon_id === link?.weapon_id - ); - - const linkedEvents = (link?.events as Prisma.JsonArray) || []; - - const costumeEvents = events.filter((event) => - linkedEvents.includes(event.id) - ); - - return ( -
-
- { - if (!value) return; - updateField(costume, "weapon_id", value.weapon_id); - }} - label="Add a weapon..." - /> - - - updateField( - costume, - "events", - selectedEvents.map( - (ev) => typeof ev === "object" && ev.id - ) - ) - } - options={events} - autoHighlight - getOptionLabel={(option) => - typeof option === "object" && - `${option?.attributes?.title}` - } - renderOption={(props, option) => ( - img": { mr: 2, flexShrink: 0 } }} - {...props} - > - - {option.attributes.title} - - )} - renderInput={(params) => ( - - )} - /> - -
- - updateField(costume, "is_limited", e.target.checked) - } - label="Is limited?" - /> -
- -
- - updateField(costume, "is_collab", e.target.checked) - } - label="Is collab?" - /> -
- -
- - updateField(costume, "is_story", e.target.checked) - } - label="Is story?" - /> -
- -
- - Chapter - - updateField( - costume, - "chapter", - Number(e.target.value) - ) - } - type="number" - /> - -
-
-
- ); - }} - options={{ - search: false, - actionsColumnIndex: -1, - searchFieldAlignment: "right", - filtering: true, - pageSize: 25, - draggable: false, - pageSizeOptions: [25, 50, 100, 200, 500], - }} - /> -
- -
- -
-
- ); -} - -export async function getServerSideProps() { - const [costumesData, weaponsData, links] = await Promise.all([ - getAllCostumes({ - orderBy: { - release_time: "desc", - }, - }), - getAllWeapons(), - prisma.nrg.costumes_link?.findMany({}), - ]); - - const selectWeapons = [...weaponsData.weapons].sort( - (a, b) => -b.weapon_type.localeCompare(a.weapon_type) - ); - - const events = await getAllEvents({ - includesDraft: true, - }); - - return { - props: JSON.parse( - JSON.stringify({ - costumes: costumesData.costumes, - weapons: selectWeapons, - links, - events, - }) - ), - }; -} diff --git a/src/pages/database/stories/companions.tsx b/src/pages/database/stories/companions.tsx index 7733f0d1..a26b2966 100644 --- a/src/pages/database/stories/companions.tsx +++ b/src/pages/database/stories/companions.tsx @@ -129,7 +129,7 @@ export default function DatabaseStoriesCompanions({ ); } -export async function getServerSideProps(context: NextPageContext) { +export async function getStaticProps(context: NextPageContext) { /** * Filters */ diff --git a/src/pages/database/stories/costumes.tsx b/src/pages/database/stories/costumes.tsx index 8e36be58..0d66bba3 100644 --- a/src/pages/database/stories/costumes.tsx +++ b/src/pages/database/stories/costumes.tsx @@ -218,7 +218,7 @@ export default function DatabaseStoriesCostumes({ ); } -export async function getServerSideProps(context: NextPageContext) { +export async function getStaticProps(context: NextPageContext) { const where = {}; if (Object.keys(context.query).length === 0) { diff --git a/src/pages/database/stories/memoirs.tsx b/src/pages/database/stories/memoirs.tsx index 4c85bcb3..41ee316c 100644 --- a/src/pages/database/stories/memoirs.tsx +++ b/src/pages/database/stories/memoirs.tsx @@ -121,7 +121,7 @@ export default function DatabaseStoriesMemoirs({ ); } -export async function getServerSideProps(context: NextPageContext) { +export async function getStaticProps(context: NextPageContext) { /** * Filters */ diff --git a/src/pages/database/stories/weapons.tsx b/src/pages/database/stories/weapons.tsx index ee0c6a5a..7e16c6ce 100644 --- a/src/pages/database/stories/weapons.tsx +++ b/src/pages/database/stories/weapons.tsx @@ -199,7 +199,7 @@ export default function DatabaseStoriesWeapons({ ); } -export async function getServerSideProps(context: NextPageContext) { +export async function getStaticProps(context: NextPageContext) { const where = { evolution_order: 1, }; diff --git a/src/pages/loadout/[slug].tsx b/src/pages/loadout/[slug].tsx deleted file mode 100644 index 8a480f9b..00000000 --- a/src/pages/loadout/[slug].tsx +++ /dev/null @@ -1,367 +0,0 @@ -import Layout from "@components/Layout"; -import Meta from "@components/Meta"; -import WeaponThumbnail from "@components/WeaponThumbnail"; -import CostumeThumbnail from "@components/CostumeThumbnail"; -import CompanionThumbnail from "@components/CompanionThumbnail"; -import DebrisThumbnail from "@components/DebrisThumbnail"; -import prisma from "@libs/prisma"; -import { CDN_URL } from "@config/constants"; -import RARITY from "@utils/rarity"; -import MemoirThumbnail from "@components/MemoirThumbnail"; -import Radio from "@components/form/Radio"; -import { NextPageContext } from "next"; -import { formatDistanceToNow } from "date-fns"; -import { useEffect, useState } from "react"; -import { LOADOUT_TYPES } from "@store/loadout"; -import Element from "@components/Element"; -import { - character, - companion, - costume, - debris, - memoir, - weapon, -} from "@prisma/client"; -import { loadouts, loadout_slots } from "@prisma/client-nrg"; -import Link from "next/link"; -import SVG from "react-inlinesvg"; -import { Chip, Tooltip } from "@mui/material"; -import { FiThumbsUp } from "react-icons/fi"; -import { useRouter } from "next/router"; -import { useLoadoutsVotes } from "@store/votes"; -import axios from "axios"; - -interface Slot { - costume: costume & { - character: character; - }; - weapons: [weapon, weapon, weapon]; - companion: companion; - debris: debris; - memoirs: [memoir, memoir, memoir]; -} - -interface LoadoutProps { - loadout: loadouts & { - loadout_slots: loadout_slots[]; - }; - slots: Slot[]; -} - -export default function Loadout({ loadout, slots }: LoadoutProps): JSX.Element { - return ( - - - - - -
- - -
- {slots.map((slot, index) => ( - - ))} -
-
-
- ); -} - -interface LoadoutInfoProps { - loadout: loadouts & { - loadout_slots: loadout_slots[]; - }; -} - -function LoadoutInfo({ loadout }: LoadoutInfoProps) { - const [createdAt, setCreatedAt] = useState(""); - const router = useRouter(); - const localVotes = useLoadoutsVotes((state) => state.votes); - const addVote = useLoadoutsVotes((state) => state.addVote); - - const hasVoted = localVotes.includes(loadout.loadout_id); - - async function vote() { - if (hasVoted) { - return; - } - - await axios.post("/api/loadouts/vote", { - loadout_id: loadout.loadout_id, - }); - - addVote(loadout.loadout_id); - - router.replace(router.asPath, undefined, { - scroll: false, - }); - } - - useEffect(() => { - setCreatedAt( - formatDistanceToNow(new Date(loadout.created_at), { - addSuffix: true, - }) - ); - }, [loadout]); - - return ( -
-
-
-

{loadout.title}

-

Created {createdAt}

- - } - /> - -
-
- {(loadout.attribute === "all" && ( -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- )) || } - - -
-
- -
-

- {loadout.description} -

-
-
- ); -} - -function CostumeSlot({ - costume, - weapons, - companion, - debris, - memoirs, -}: Slot): JSX.Element { - return ( -
-
- Details -
- {/* CHARACTER */} -
-

Character

-
- -
- -
- {/* WEAPONS */} -
-

Weapons

-
-
- {weapons.map((weapon: weapon, weaponIndex) => ( - - ))} -
- {/* COMPANION & DEBRIS */} -
-

Companion

-

Debris

-
-
- -
- -
-
- {/* MEMOIRS */} -
-

Memoirs

-
-
- {memoirs.map((memoir, memoirIndex) => ( - - ))} -
-
- ); -} - -export async function getServerSideProps(context: NextPageContext) { - context.res.setHeader("Cache-Control", "public, maxage=86400"); - - const loadout = await prisma.nrg.loadouts.findFirst({ - where: { - slug: context.query.slug as string, - }, - include: { - loadout_slots: { - orderBy: { - slot_position: "asc", - }, - }, - }, - }); - - /** - * Populate slots - */ - const slotFetches = loadout.loadout_slots.map((slot) => getSlotData(slot)); - const slots = await Promise.all(slotFetches); - - return { - props: JSON.parse( - JSON.stringify({ - loadout, - slots, - }) - ), - }; -} - -async function getSlotData(slot: loadout_slots) { - const [costume, companion, debris] = await Promise.all([ - /** - * Get costume - */ - slot.costume_id - ? prisma.dump.costume.findFirst({ - where: { - costume_id: slot.costume_id, - }, - include: { - character: true, - }, - }) - : null, - - /** - * Get companion - */ - slot.companion_id - ? prisma.dump.companion.findFirst({ - where: { - companion_id: slot.companion_id, - }, - }) - : null, - - /** - * Get debris - */ - slot.debris_id - ? prisma.dump.debris.findFirst({ - where: { - debris_id: slot.debris_id, - }, - }) - : null, - ]); - - /** - * Get weapons - */ - const weaponsIds = [ - slot.weapon_1_id, - slot.weapon_2_id, - slot.weapon_3_id, - ].filter(Boolean); - - const weapons = await Promise.all( - weaponsIds.map((id) => - prisma.dump.weapon.findFirst({ - where: { - weapon_id: id, - }, - }) - ) - ); - - /** - * Get memoirs - */ - const memoirsIds = [ - slot.memoir_1_id, - slot.memoir_2_id, - slot.memoir_3_id, - ].filter(Boolean); - - const memoirs = await Promise.all( - memoirsIds.map((id) => - prisma.dump.memoir.findFirst({ - where: { - memoir_id: id, - }, - }) - ) - ); - - const fillWeapons = new Array(3 - weapons.length).fill(null); - const formattedWeapons = [...weapons, ...fillWeapons]; - - const fillMemoirs = new Array(3 - memoirs.length).fill(null); - const formattedMemoirs = [...memoirs, ...fillMemoirs]; - - return { - costume, - weapons: formattedWeapons, - companion, - debris, - memoirs: formattedMemoirs, - }; -} diff --git a/src/pages/loadouts.tsx b/src/pages/loadouts.tsx deleted file mode 100644 index 8d303bd8..00000000 --- a/src/pages/loadouts.tsx +++ /dev/null @@ -1,203 +0,0 @@ -import Layout from "@components/Layout"; -import Meta from "@components/Meta"; -import prisma from "@libs/prisma"; -import { NextPageContext } from "next"; -import { loadouts } from "@prisma/client-nrg"; -import LoadoutListingItem from "@components/LoadoutListingItem"; -import { FormControl, InputLabel, MenuItem, Select } from "@mui/material"; -import ATTRIBUTES from "@utils/attributes"; -import { useEffect, useRef, useState } from "react"; -import TextField from "@mui/material/TextField"; -import { useRouter } from "next/router"; -import { AdapterDateFns } from "@mui/x-date-pickers/AdapterDateFns"; -import { LocalizationProvider } from "@mui/x-date-pickers/LocalizationProvider"; -import { MobileDatePicker } from "@mui/x-date-pickers/MobileDatePicker"; -import { sub } from "date-fns"; -import Link from "next/link"; - -interface LoadoutProps { - loadouts: loadouts[]; -} - -export default function ListingLoadout({ - loadouts, -}: LoadoutProps): JSX.Element { - const router = useRouter(); - const firstUpdate = useRef(true); - - const defaultFromDate = sub(new Date(), { - months: 1, - }); - - const [sortBy, setSortBy] = useState("created_at"); - const [fromDate, setFromDate] = useState(defaultFromDate); - const [attribute, setAttribute] = useState("all"); - const [type, setType] = useState("all"); - - useEffect(() => { - if (firstUpdate.current) return; - - router.push( - `/loadouts?attribute=${attribute}&type=${type}&from=${fromDate.toISOString()}&sortBy=${sortBy}` - ); - }, [attribute, type, fromDate, sortBy]); - - useEffect(() => { - if (firstUpdate.current) { - firstUpdate.current = false; - return; - } - }, []); - - return ( - - - -
-

Community loadouts

- - - - Create a loadout - - - -
- - Sort by - - - - setFromDate(newValue)} - renderInput={(params) => } - /> - - - Type - - - - Attribute - - -
- - {loadouts.length > 0 && ( -
- {loadouts.map((loadout) => ( - - ))} -
- )} - - {loadouts.length === 0 && ( -
- Fio confused -

Sorry, no loadouts found.

-
- - Create one! - -
-
- )} -
-
- ); -} - -export async function getServerSideProps(context: NextPageContext) { - const where = {}; - let orderBy = {}; - - /** - * Filters - */ - if (context.query.attribute) { - if (context.query.attribute !== "all") { - where["attribute"] = context.query.attribute; - } - } - - if (context.query.type !== "all") { - where["type"] = context.query.type; - } - - if (context.query.from) { - where["created_at"] = {}; - where["created_at"]["gte"] = context.query.from; - } - - /** - * Order by - */ - - if (context.query.sortBy) { - orderBy = { - [context.query.sortBy as string]: "desc", - }; - } else { - orderBy = { - created_at: "desc", - }; - } - - const loadouts = await prisma.nrg.loadouts.findMany({ - where, - orderBy, - }); - - return { - props: JSON.parse( - JSON.stringify({ - loadouts, - }) - ), - }; -} diff --git a/src/pages/tierlists/[[...slug]].tsx b/src/pages/tierlists.tsx similarity index 99% rename from src/pages/tierlists/[[...slug]].tsx rename to src/pages/tierlists.tsx index 404b7e2c..fbe7e81a 100644 --- a/src/pages/tierlists/[[...slug]].tsx +++ b/src/pages/tierlists.tsx @@ -186,7 +186,7 @@ export default function TierlistsPageProps({ ); } -export async function getServerSideProps(context: NextPageContext) { +export async function getStaticProps() { const { pve, pvp } = await getTiers(); const characters = await prisma.dump.character.findMany({}); diff --git a/src/pages/tools/loadout-builder.tsx b/src/pages/tools/loadout-builder.tsx deleted file mode 100644 index ccb83684..00000000 --- a/src/pages/tools/loadout-builder.tsx +++ /dev/null @@ -1,761 +0,0 @@ -import Layout from "@components/Layout"; -import Meta from "@components/Meta"; -import Radio from "@components/form/Radio"; -import { LOADOUT_TYPES, useLoadoutStore } from "@store/loadout"; -import WeaponThumbnail from "@components/WeaponThumbnail"; -import CostumeThumbnail from "@components/CostumeThumbnail"; -import CompanionThumbnail from "@components/CompanionThumbnail"; -import DebrisThumbnail from "@components/DebrisThumbnail"; -import { memo, useEffect, useState } from "react"; -import prisma from "@libs/prisma"; -import Modal from "@mui/material/Modal"; -import MaterialTable from "@material-table/core"; -import { CDN_URL } from "@config/constants"; -import RARITY from "@utils/rarity"; -import SVG from "react-inlinesvg"; -import { CostumesTable } from "@components/pages/costumes"; -import Star from "@components/decorations/Star"; -import Element from "@components/Element"; -import { attributesLookup, WeaponsTable } from "@components/pages/weapons"; -import { - DEBRIS_RARITY, - rarityLookup as debrisRarityLookup, -} from "pages/database/debris"; -import MemoirThumbnail from "@components/MemoirThumbnail"; -import { BtnSecondary } from "@components/btn"; -import toast from "react-hot-toast"; -import axios from "axios"; -import { useRouter } from "next/router"; -import { FormControl, InputLabel, MenuItem, Select } from "@mui/material"; -import ATTRIBUTES from "@utils/attributes"; -import { - character, - companion, - costume, - costume_ability, - costume_ability_link, - costume_skill, - costume_skill_link, - costume_stat, - debris, - emblem, - memoir, - weapon, - weapon_ability, - weapon_ability_link, - weapon_skill, - weapon_skill_link, - weapon_stat, -} from "@prisma/client"; -import Link from "next/link"; -import { getAllCostumes } from "@models/costume"; -import { useSettingsStore } from "../../store/settings"; -import { getAllWeapons } from "@models/weapon"; -import { useInventoryStore } from "@store/inventory"; -import Checkbox from "@components/form/Checkbox"; - -interface LoadoutBuilderProps { - costumes: (costume & { - costume_ability_link: (costume_ability_link & { - costume_ability: costume_ability; - })[]; - costume_skill_link: (costume_skill_link & { - costume_skill: costume_skill; - })[]; - costume_stat: costume_stat[]; - character: character; - emblem: emblem; - })[]; - weapons: (weapon & { - weapon_ability_link: (weapon_ability_link & { - weapon_ability: weapon_ability; - })[]; - weapon_skill_link: (weapon_skill_link & { - weapon_skill: weapon_skill; - })[]; - weapon_stat: weapon_stat[]; - })[]; - companions: companion[]; - debris: debris[]; - memoirs: (memoir & { - memoir_series: { - name: string; - large_set_description: string; - }; - })[]; - memoirsSetLookup; - abilitiesLookup; - charactersLookup; - weaponsAbilitiesLookup; -} - -export default function LoadoutBuilder({ - costumes, - weapons, - companions, - debris, - memoirs, - memoirsSetLookup, - abilitiesLookup, - charactersLookup, - weaponsAbilitiesLookup, -}: LoadoutBuilderProps): JSX.Element { - const showUnreleasedContent = useSettingsStore( - (state) => state.showUnreleasedContent - ); - - /** - * Loadout slots - */ - const slots = useLoadoutStore((state) => state.slots); - - /** - * Select a costume - */ - const setCostume = useLoadoutStore((state) => state.setCostume); - const costumeModal = useLoadoutStore((state) => state.costumeModal); - const setCostumeModal = useLoadoutStore((state) => state.setCostumeModal); - - /** - * Select up to 3 weapons - */ - const weaponsModal = useLoadoutStore((state) => state.weaponsModal); - const setWeaponsModal = useLoadoutStore((state) => state.setWeaponsModal); - const setWeapon = useLoadoutStore((state) => state.setWeapon); - - /** - * Companion - */ - const companionModal = useLoadoutStore((state) => state.companionModal); - const setCompanionModal = useLoadoutStore((state) => state.setCompanionModal); - const setCompanion = useLoadoutStore((state) => state.setCompanion); - - /** - * Debris - */ - const debrisModal = useLoadoutStore((state) => state.debrisModal); - const setDebrisModal = useLoadoutStore((state) => state.setDebrisModal); - const setDebris = useLoadoutStore((state) => state.setDebris); - - /** - * Memoirs - */ - const memoirsModal = useLoadoutStore((state) => state.memoirsModal); - const setMemoirsModal = useLoadoutStore((state) => state.setMemoirsModal); - const setMemoir = useLoadoutStore((state) => state.setMemoir); - - /** - * Inventory - */ - const [showOnlyInventory, setShowOnlyInventory] = useState(false); - const ownedCostumes = useInventoryStore((state) => state.costumes); - const ownedWeapons = useInventoryStore((state) => state.weapons); - - return ( - - - - - -
- - -
- {slots.map((slot, index) => ( - - ))} -
- - -
- - {/* Modals for selection */} - {/* MODAL COSTUMES */} - setCostumeModal(0, false)} - aria-labelledby="modal-modal-title" - aria-describedby="modal-modal-description" - keepMounted - > - { - if (!showOnlyInventory) return true; - return ownedCostumes.includes(cost.costume_id); - })} - abilitiesLookup={abilitiesLookup} - charactersLookup={charactersLookup} - showUnreleasedContent={showUnreleasedContent} - onRowClick={(event, costume) => setCostume(costume)} - /> - - - {/* MODAL WEAPONS */} - setWeaponsModal(0, false)} - aria-labelledby="modal-modal-title" - aria-describedby="modal-modal-description" - keepMounted - > - { - if (!showOnlyInventory) return true; - return ownedWeapons.includes(weap.weapon_id); - })} - onRowClick={(event, weapon) => setWeapon(weapon)} - abilitiesLookup={weaponsAbilitiesLookup} - /> - - - {/* MODAL COMPANIONS */} - setCompanionModal(0, false)} - aria-labelledby="modal-modal-title" - aria-describedby="modal-modal-description" - keepMounted - > - ( -
- - {companion.name} -
- ), - }, - { - field: "attribute", - title: "Attribute", - cellStyle: { - textAlign: "center", - }, - lookup: attributesLookup, - customFilterAndSearch: (term, weapon) => { - if (term.length === 0) return true; - return term.includes(weapon.attribute); - }, - render: (weapon) => , - }, - ]} - options={{ - grouping: true, - searchFieldAlignment: "right", - filtering: true, - pageSize: 25, - pageSizeOptions: [25, 50, 100, 200, 500], - }} - onRowClick={(event, companion) => setCompanion(companion)} - /> -
- - {/* MODAL DEBRIS */} - setDebrisModal(0, false)} - aria-labelledby="modal-modal-title" - aria-describedby="modal-modal-description" - keepMounted - > - ( -
- - {debris.name.split("Debris:")[1]} -
- ), - }, - { - field: "ability", - title: "Ability", - lookup: { 0: "WIP" }, - render: () => WIP, - }, - { - field: "rarity", - title: "Rarity", - lookup: debrisRarityLookup, - customFilterAndSearch: (term, debris) => { - if (term.length === 0) return true; - return term.includes(debris.rarity.toString()); - }, - render: (debris) => ( -
- -
- ), - }, - { - field: "release_time", - title: "Released date", - type: "datetime", - customFilterAndSearch: (term, debris) => { - return term < new Date(debris.release_time); - }, - }, - ]} - options={{ - grouping: true, - searchFieldAlignment: "right", - filtering: true, - pageSize: 25, - pageSizeOptions: [25, 50, 100, 200, 500], - }} - onRowClick={(event, debris) => setDebris(debris)} - /> -
- - {/* MODAL MEMOIRS */} - setMemoirsModal(0, 0, false)} - aria-labelledby="modal-modal-title" - aria-describedby="modal-modal-description" - keepMounted - > - { - if (term.length === 0) return true; - return term.includes(memoir.memoir_series.name); - }, - }, - { - field: "name", - render: (memoir) => ( -
- - {memoir.name} -
- ), - }, - { - field: "memoir_series.large_set_description", - title: "Description", - }, - ]} - options={{ - grouping: true, - searchFieldAlignment: "right", - filtering: true, - pageSize: 25, - pageSizeOptions: [25, 50, 100, 200, 500], - }} - onRowClick={(event, memoir) => setMemoir(memoir)} - /> -
-
- ); -} - -function LoadoutSettings({ - showOnlyInventory, - setShowOnlyInventory, -}: { - showOnlyInventory: boolean; - setShowOnlyInventory: (bool: boolean) => void; -}) { - const setSlotSize = useLoadoutStore((state) => state.setSlotSize); - - const title = useLoadoutStore((state) => state.title); - const setTitle = useLoadoutStore((state) => state.setTitle); - - const type = useLoadoutStore((state) => state.type); - const setType = useLoadoutStore((state) => state.setType); - - const description = useLoadoutStore((state) => state.description); - const setDescription = useLoadoutStore((state) => state.setDescription); - - const attribute = useLoadoutStore((state) => state.attribute); - const setAttribute = useLoadoutStore((state) => state.setAttribute); - - useEffect(() => { - setSlotSize(LOADOUT_TYPES[type].slotSize); - }, [type, setSlotSize]); - - return ( -
-
-
- setTitle(e.target.value)} - /> -
-
-
- setShowOnlyInventory(e.target.checked)} - /> -
- - Attribute - - -
- {Object.entries(LOADOUT_TYPES).map(([key, currentType]) => ( -
- -
- ))} -
-
-
- -
- -
-
- ); -} - -function LoadoutSave() { - const router = useRouter(); - const [loading, setLoading] = useState(false); - const loadout = useLoadoutStore((state) => ({ - title: state.title, - description: state.description, - type: state.type, - attribute: state.attribute, - slots: state.slots, - })); - - async function saveLoadout() { - if (loading) return; - - try { - setLoading(true); - - const response = await axios.post("/api/loadouts", { - loadout, - }); - - toast.success("Loadout saved! Redirecting..."); - - router.push(`/loadout/${response.data.loadout.slug}`); - } catch (error) { - toast.error(error.message); - } finally { - setLoading(false); - } - } - - return ( -
- {loading &&
} - {(loading && Loading...) || ( - Save - )} -
- ); -} - -interface CostumeSlotProps { - index: number; -} - -interface SlotType { - costume: costume & { - costume_ability_link: (costume_ability_link & { - costume_ability: costume_ability; - })[]; - costume_skill_link: (costume_skill_link & { - costume_skill: costume_skill; - })[]; - costume_stat: costume_stat[]; - character: character; - emblem: emblem; - }; - weapons: (weapon & { - weapon_ability_link: (weapon_ability_link & { - weapon_ability: weapon_ability; - })[]; - weapon_skill_link: (weapon_skill_link & { - weapon_skill: weapon_skill; - })[]; - weapon_stat: weapon_stat[]; - })[]; - companions: companion; - debris: debris; - memoirs: (memoir & { - memoir_series: { - name: string; - large_set_description: string; - }; - })[]; -} - -const CostumeSlot = memo(function CostumeSlot({ index }: CostumeSlotProps) { - /** - * Current slot in the loadout. - */ - const slot: SlotType = useLoadoutStore((state) => state.slots[index]); - - /** - * Init stats with costume stats - */ - // const costumeStat = slot?.costume?.costume_stat[0]; - /* const stats = { - agi: costumeStat?.agi ?? 0, - atk: costumeStat?.atk ?? 0, - crit_atk: costumeStat?.crit_atk ?? 0, - crit_rate: costumeStat?.crit_rate ?? 0, - eva_rate: costumeStat?.eva_rate ?? 0, - hp: costumeStat?.hp ?? 0, - vit: costumeStat?.vit ?? 0, - }; - - const weaponsStats = { - atk: 0, - hp: 0, - vit: 0, - }; - - if (slot.weapons.some((wep) => wep)) { - const atkStats = slot.weapons.reduce((acc, weapon, index) => { - const MULTIPLIER = index === 0 ? 1 : 0.5; - - acc = (acc + weapon.weapon_stat[0].atk) * MULTIPLIER; - - return acc; - }, 0); - - weaponsStats.atk = atkStats; - } - - console.table(stats); - console.table(weaponsStats); */ - /** - * Methods to open the selection modal for this item. - */ - const setCostumeModal = useLoadoutStore((state) => state.setCostumeModal); - const setWeaponsModal = useLoadoutStore((state) => state.setWeaponsModal); - const setCompanionModal = useLoadoutStore((state) => state.setCompanionModal); - const setDebrisModal = useLoadoutStore((state) => state.setDebrisModal); - const setMemoirsModal = useLoadoutStore((state) => state.setMemoirsModal); - - return ( -
-
- Details -
- {/* CHARACTER */} -
-

Character

-
- -
- setCostumeModal(index, true)} - src={ - slot.costume - ? `${CDN_URL}${slot.costume?.image_path_base}battle.png` - : undefined - } - alt={slot.costume ? `${slot.costume?.title} thumbnail` : undefined} - rarity={RARITY[slot.costume?.rarity]} - /> -
- {/* WEAPONS */} -
-

Weapons

-
-
- {slot.weapons.map((weapon: weapon, weaponIndex) => ( - setWeaponsModal(index, weaponIndex, true)} - element={weapon?.attribute} - rarity={weapon?.rarity} - type={weapon?.weapon_type} - isDark={weapon?.is_ex_weapon} - alt={weapon?.name} - image_path={weapon?.image_path} - /> - ))} -
- {/* COMPANION & DEBRIS */} -
-

Companion

-

Debris

-
-
- setCompanionModal(index, true)} - companion={slot.companion} - small - /> -
- setDebrisModal(index, true)} - {...slot.debris} - /> -
-
- {/* MEMOIRS */} -
-

Memoirs

-
-
- {slot.memoirs.map((memoir, memoirIndex) => ( - setMemoirsModal(index, memoirIndex, true)} - key={`${index}-${memoirIndex}`} - {...memoir} - /> - ))} -
- - {/* STATS */} - {/*
- {Object.entries(stats).map(([key, value]) => ( -

- {key}{" "} - {key} {value} -

- ))} -
*/} -
- ); -}); - -export async function getStaticProps() { - const [ - costumesData, - weaponsData, - companions, - debris, - memoirs, - memoirsLookupData, - ] = await Promise.all([ - getAllCostumes({ - orderBy: { - release_time: "desc", - }, - }), - getAllWeapons(), - prisma.dump.companion.findMany({ - orderBy: { - release_time: "asc", - }, - }), - prisma.dump.debris.findMany({ - orderBy: { - release_time: "asc", - }, - }), - prisma.dump.memoir.findMany({ - orderBy: { - series_id: "asc", - }, - where: { - lottery_id: 5, - rarity: "SS_RARE", - }, - include: { - memoir_series: { - select: { - large_set_description: true, - name: true, - }, - }, - }, - }), - prisma.dump.memoir_series.findMany({ - orderBy: { - memoir_series_id: "asc", - }, - select: { - name: true, - }, - }), - ]); - - const memoirsSetLookup = memoirsLookupData.reduce((acc, current) => { - acc[current.name] = current.name; - return acc; - }, {}); - - return { - props: JSON.parse( - JSON.stringify({ - costumes: costumesData.costumes, - weapons: weaponsData.weapons, - companions, - debris, - memoirs, - memoirsSetLookup, - abilitiesLookup: costumesData.abilitiesLookup, - charactersLookup: costumesData.charactersLookup, - weaponsAbilitiesLookup: weaponsData.abilitiesLookup, - }) - ), - }; -} diff --git a/src/pages/tools/tierlist-builder/costumes.tsx b/src/pages/tools/tierlist-builder/costumes.tsx deleted file mode 100644 index d74a6686..00000000 --- a/src/pages/tools/tierlist-builder/costumes.tsx +++ /dev/null @@ -1,845 +0,0 @@ -import Layout from "components/Layout"; -import Meta from "@components/Meta"; -import SVG from "react-inlinesvg"; -import produce from "immer"; -import { - character, - costume, - costume_ability, - costume_ability_link, - costume_skill, - costume_skill_link, - costume_stat, - emblem, -} from "@prisma/client"; -import Link from "next/link"; -import { getAllCostumes } from "@models/costume"; -import { useSettingsStore } from "../../../store/settings"; -import { useCreatedTierlists } from "../../../store/created-tierlists"; -import { DragDropContext, Droppable, Draggable } from "react-beautiful-dnd"; -import { useEffect, useState } from "react"; -import { - FiArrowDownCircle, - FiArrowUpCircle, - FiEdit, - FiMessageCircle, - FiXCircle, -} from "react-icons/fi"; -import CostumeThumbnail from "@components/CostumeThumbnail"; -import { CDN_URL } from "@config/constants"; -import RARITY from "@utils/rarity"; -import classNames from "classnames"; -import Image from "next/legacy/image"; -import { - Autocomplete, - FormControl, - InputLabel, - MenuItem, - Modal, - TextField, - Tooltip, - Select, -} from "@mui/material"; -import { BtnSecondary } from "@components/btn"; -import axios from "axios"; -import Wysiwyg from "@components/Wysiwyg"; -import toast from "react-hot-toast"; -import { useRouter } from "next/router"; -import CostumeSelect from "@components/characters/CostumeSelect"; -import Checkbox from "@components/form/Checkbox"; -import { RANK_THUMBNAILS } from "@utils/rankThumbnails"; -import ATTRIBUTES from "@utils/attributes"; -import Element from "@components/Element"; - -const DEFAULT_DESCRIPTION = "

My awesome (and objective) tierlist.

"; - -const reorder = (list, startIndex, endIndex) => { - const result = Array.from(list); - const [removed] = result.splice(startIndex, 1); - result.splice(endIndex, 0, removed); - - return result; -}; - -/** - * Moves an item from one list to another list. - */ -const move = (source, destination, droppableSource, droppableDestination) => { - const sourceClone = Array.from(source); - const destClone = Array.from(destination); - const [removed] = sourceClone.splice(droppableSource.index, 1); - - destClone.splice(droppableDestination.index, 0, removed); - - const result = {}; - result[droppableSource.droppableId] = sourceClone; - result[droppableDestination.droppableId] = destClone; - - return result; -}; - -const getItemStyle = (isDragging, draggableStyle) => ({ - userSelect: "none", - background: "transparent", - ...draggableStyle, -}); -const getListStyle = (isDraggingOver) => ({ - background: isDraggingOver ? "#bda699" : "#0C0C0C", -}); - -interface TierlistBuilderProps { - costumes: (costume & { - costume_ability_link: (costume_ability_link & { - costume_ability: costume_ability; - })[]; - costume_skill_link: (costume_skill_link & { - costume_skill: costume_skill; - })[]; - costume_stat: costume_stat[]; - character: character; - emblem: emblem; - })[]; -} - -export default function TierlistBuilder({ - costumes, -}: TierlistBuilderProps): JSX.Element { - const router = useRouter(); - - const showUnreleasedContent = useSettingsStore( - (state) => state.showUnreleasedContent - ); - - const addTierlist = useCreatedTierlists((state) => state.addTierlist); - - /** - * Inventory - */ - const [show4StarsOnly, setShow4StarsOnly] = useState(true); - - /** - * Costumes - */ - const [state, setState] = useState([ - { - tier: "SSS", - description: "", - items: [], - }, - { - tier: "SS", - description: "", - items: [], - }, - { - tier: "S", - description: "", - items: [], - }, - { - tier: "A", - description: "", - items: [], - }, - { - tier: "B", - description: "", - items: [], - }, - { - tier: "ALL", - description: "", - items: [], - }, - ]); - const [yup, setYup] = useState(false); - const [titleModal, setTitleModal] = useState(false); - const [tooltipModal, setTooltipModal] = useState(false); - const [currentIndex, setCurrentIndex] = useState(0); - const [currentItemIndex, setCurrentItemIndex] = useState(0); - const [title, setTitle] = useState("My tierlist"); - const [description, setDescription] = useState(DEFAULT_DESCRIPTION); - const [currentTooltip, setCurrentTooltip] = useState(""); - const [tierDescription, setTierDescription] = useState(""); - const [loading, setLoading] = useState(false); - - /** - * Fetch existing tierlist if edit_key is found. - */ - useEffect(() => { - if (router.query.edit_key) { - getExistingTierlist(); - } - }, [router]); - - /** - * Client side only - */ - useEffect(() => { - setYup(true); - }, []); - - /** - * Filter costumes - */ - useEffect(() => { - const filteredSelection = getCostumesSelection(); - setState( - produce(state, (draft) => { - draft[draft.length - 1].items = filteredSelection; - }) - ); - }, [costumes]); - - function onDragEnd(result) { - const { source, destination } = result; - - // dropped outside the list - if (!destination) { - return; - } - const sInd = +source.droppableId; - const dInd = +destination.droppableId; - - if (sInd === dInd) { - const items = reorder(state[sInd].items, source.index, destination.index); - const newState = [...state]; - newState[sInd].items = items; - setState(newState); - } else { - const result = move( - state[sInd].items, - state[dInd].items, - source, - destination - ); - const newState = [...state]; - newState[sInd] = { - ...newState[sInd], - items: result[sInd], - }; - - newState[dInd] = { - ...newState[dInd], - items: result[dInd], - }; - - setState(newState); - } - } - - function moveTierUp(index) { - setState( - produce(state, (draft) => { - if (index > 0) { - const item = state[index]; - draft.splice(index, 1); - draft.splice(index - 1, 0, item); - } - }) - ); - } - - function moveTierDown(index) { - if (index + 1 === state.length - 1) { - return; - } - - setState( - produce(state, (draft) => { - const item = state[index]; - draft.splice(index, 1); - draft.splice(index + 1, 0, item); - }) - ); - } - - function removeTier(index) { - if (window.confirm("Are you sure you want to delete this tier?")) { - setState( - produce(state, (draft) => { - draft.splice(index, 1); - }) - ); - } - } - - function editTitle(index) { - setCurrentIndex(index); - setTitleModal(true); - } - - function handleTitleModalClose(event) { - event.preventDefault(); - const value = event.target.elements[0].value || state[currentIndex].tier; - - const newState = produce(state, (draft) => { - draft[currentIndex].tier = value; - draft[currentIndex].description = tierDescription; - }); - setState(newState); - setTitleModal(false); - setCurrentIndex(0); - setTierDescription(""); - } - - function handleTooltipModalClose() { - const newState = produce(state, (draft) => { - if (!currentTooltip) { - return; - } - // Update content - if (currentTooltip === "

") { - draft[currentIndex].items[currentItemIndex].tooltip = ""; - return; - } - draft[currentIndex].items[currentItemIndex].tooltip = currentTooltip; - }); - - setState(newState); - setTooltipModal(false); - setCurrentIndex(0); - setCurrentItemIndex(0); - setCurrentTooltip(""); - } - - function getCostumesSelection() { - const filtered = costumes - .filter((costume) => { - if (showUnreleasedContent) return true; - return new Date() > new Date(costume.release_time); - }) - .sort((a, b) => -b.character.name.localeCompare(a.character.name)) - .map((costume, index) => ({ - ...costume, - id: `${costume.character.character_id}-${costume.costume_id}-${index}`, - tooltip: "", - tooltip_is_important: false, - awakening_step: 0, - preferred_attribute: "", - })); - - return filtered; - } - - async function getExistingTierlist() { - try { - setLoading(true); - const { data } = await axios.get( - `/api/tierlists?edit_key=${router.query.edit_key}` - ); - const { tierlist, tiers } = data; - const filteredSelection = getCostumesSelection(); - const alreadySelectedItems = tiers.map((tier) => tier.items).flat(); - const newSelection = filteredSelection.filter((item) => { - const isSelected = alreadySelectedItems.findIndex( - (it) => it.item_id === item.costume_id - ); - - if (isSelected >= 0) { - return false; - } - return true; - }); - setTitle(tierlist.title); - setDescription(tierlist.description); - setState([ - ...tiers, - { tier: "ALL", description: "", items: newSelection }, - ]); - } catch (error) { - console.error(error); - } finally { - setLoading(false); - } - } - - async function save() { - if (loading) return; - - try { - setLoading(true); - - const formattedTiers = state.slice(0, state.length - 1).map((tiers) => { - const newItems = tiers.items.map((item) => ({ - costume_id: item.costume_id, - tooltip: item.tooltip, - tooltip_is_important: item.tooltip_is_important, - awakening_step: item.awakening_step, - attribute: item.preferred_attribute, - })); - - return { - ...tiers, - items: newItems, - }; - }); - - const response = await axios({ - url: "/api/tierlists", - method: router.query.edit_key ? "PUT" : "POST", - data: { - title, - description, - type: "costumes", - attribute: "all", - tiers: formattedTiers, - edit_key: router.query.edit_key, - }, - }); - - toast.success("Tier list saved! Redirecting..."); - - addTierlist(response.data.tierlist); - - router.push(`/tierlist/${response.data.tierlist.slug}`); - } catch (error) { - toast.error(error.message); - } finally { - setLoading(false); - } - } - - return ( - - - - - -
-
-
-
- setTitle(e.target.value)} - /> -
-
- -
- setDescription(html)} - content={description} - /> -
-
-
- {loading && ( -
- )} - {(loading && Loading...) || ( - Save - )} -
- {yup && ( -
- - {state.map((el, ind) => ( - <> - {ind === state.length - 1 && ( -
- -
- )} - - {(provided, snapshot) => ( -
- {ind !== state.length - 1 && ( -
- - - -
- )} - - {ind !== state.length - 1 && ( - - )} - {ind === state.length - 1 && ( -
-

Drag & Drop costumes into the tiers.

- - setShow4StarsOnly(e.target.checked) - } - /> -
- )} - -
- {ind !== state.length - 1 && ( -
- {ind !== state.length - 1 && ( -
- {(RANK_THUMBNAILS[el.tier] && ( - {el.tier} - )) ||

{el.tier}

} -
- )} -
- )} - -
- {el.items?.map((item, index) => { - return ( - - {(provided, snapshot) => ( -
-
- {item.tooltip && ( -
- -
- )} - - {item.awakening_step > 0 && ( - - - - {item.awakening_step} - - - )} - {item.preferred_attribute && ( - - - - )} - {ind === state.length - 1 && ( -
-

- {item.is_ex_costume && ( - - EX{" "} - - )} - {item.character.name} -

- - {item.title} - -
- )} - {ind !== state.length - 1 && ( - - - - )} -
-
- )} -
- ); - })} -
-
- - {el.description && ( -
- )} - - {ind === state.length - 1 && ( -
- - -b.character.name.localeCompare( - a.character.name - ) - )} - onSelect={(e, costume) => { - if (!costume) { - return; - } - - setState( - produce(state, (draft) => { - draft[draft.length - 1].items.push({ - ...costume, - id: `${ - costume.character.character_id - }-${Date.now()}`, - tooltip: "", - tooltip_is_important: false, - awakening_step: 0, - preferred_attribute: "", - }); - }) - ); - }} - /> -
- )} - - {provided.placeholder} -
- )} -
- - ))} -
-
- )} -
- - setTitleModal(false)} - className="flex items-center justify-center" - aria-labelledby="modal-modal-title" - aria-describedby="modal-modal-description" - > -
- key)} - renderInput={(params) => ( - - )} - /> - setTierDescription(content)} - content={state[currentIndex]?.description ?? ""} - /> - - -
- - setTooltipModal(false)} - className="flex items-center justify-center" - aria-labelledby="modal-modal-title" - aria-describedby="modal-modal-description" - > -
- setCurrentTooltip(content)} - content={ - state[currentIndex]?.items[currentItemIndex]?.tooltip ?? - "Add new tooltip..." - } - /> -
- { - const newState = produce(state, (draft) => { - draft[currentIndex].items[ - currentItemIndex - ].tooltip_is_important = - !state[currentIndex]?.items[currentItemIndex] - ?.tooltip_is_important; - }); - - setState(newState); - }} - /> -
-
- - - Preferred Awakening Level - - - - - - Preferred Attribute - - - -
-
- -
-
-
-
- ); -} - -export async function getStaticProps() { - const { costumes } = await getAllCostumes({ - orderBy: { costume_id: "desc" }, - }); - - return { - props: JSON.parse( - JSON.stringify({ - costumes, - }) - ), - }; -} diff --git a/src/pages/tools/tierlist-builder/index.tsx b/src/pages/tools/tierlist-builder/index.tsx deleted file mode 100644 index a07ce3eb..00000000 --- a/src/pages/tools/tierlist-builder/index.tsx +++ /dev/null @@ -1,58 +0,0 @@ -import Meta from "@components/Meta"; -import Image from "next/legacy/image"; -import Link from "next/link"; -import Layout from "@components/Layout"; -import classNames from "classnames"; - -export default function TierlistBuilderChoices(): JSX.Element { - return ( - - - -

- What kind of tierlist do you want to create? -

-
- - -
-
- ); -} - -function ListingItem({ href, src, label }) { - return ( - ( - - {label} -

- {label} -

- - ) - ); -} diff --git a/src/pages/tools/tierlist-builder/weapons.tsx b/src/pages/tools/tierlist-builder/weapons.tsx deleted file mode 100644 index 69fda99f..00000000 --- a/src/pages/tools/tierlist-builder/weapons.tsx +++ /dev/null @@ -1,756 +0,0 @@ -import Layout from "@components/Layout"; -import Meta from "@components/Meta"; -import SVG from "react-inlinesvg"; -import produce from "immer"; -import { - weapon, - weapon_ability, - weapon_ability_link, - weapon_skill, - weapon_skill_link, - weapon_stat, -} from "@prisma/client"; -import Link from "next/link"; -import { useSettingsStore } from "../../../store/settings"; -import { useInventoryStore } from "@store/inventory"; -import { DragDropContext, Droppable, Draggable } from "react-beautiful-dnd"; -import { useEffect, useState } from "react"; -import { - FiArrowDownCircle, - FiArrowUpCircle, - FiEdit, - FiMessageCircle, - FiXCircle, -} from "react-icons/fi"; -import classNames from "classnames"; -import Image from "next/legacy/image"; -import { - Autocomplete, - FormControl, - InputLabel, - MenuItem, - Modal, - Select, - TextField, - Tooltip, -} from "@mui/material"; -import { BtnSecondary } from "@components/btn"; -import axios from "axios"; -import Wysiwyg from "@components/Wysiwyg"; -import toast from "react-hot-toast"; -import { useRouter } from "next/router"; -import Checkbox from "@components/form/Checkbox"; -import { getAllWeapons } from "@models/weapon"; -import WeaponSelect from "@components/weapons/WeaponSelect"; -import WeaponThumbnail from "@components/WeaponThumbnail"; -import ATTRIBUTES from "@utils/attributes"; -import { RANK_THUMBNAILS } from "@utils/rankThumbnails"; -import { useCreatedTierlists } from "@store/created-tierlists"; -import getBaseRarity from "@utils/getBaseRarity"; -import { useFilteredWeapons } from "@hooks/useFilteredWeapons"; - -const DEFAULT_DESCRIPTION = "

My awesome (and objective) tierlist.

"; - -const reorder = (list, startIndex, endIndex) => { - const result = Array.from(list); - const [removed] = result.splice(startIndex, 1); - result.splice(endIndex, 0, removed); - - return result; -}; - -/** - * Moves an item from one list to another list. - */ -const move = (source, destination, droppableSource, droppableDestination) => { - const sourceClone = Array.from(source); - const destClone = Array.from(destination); - const [removed] = sourceClone.splice(droppableSource.index, 1); - - destClone.splice(droppableDestination.index, 0, removed); - - const result = {}; - result[droppableSource.droppableId] = sourceClone; - result[droppableDestination.droppableId] = destClone; - - return result; -}; - -const getItemStyle = (isDragging, draggableStyle) => ({ - userSelect: "none", - background: "transparent", - ...draggableStyle, -}); -const getListStyle = (isDraggingOver) => ({ - background: isDraggingOver ? "#bda699" : "#0C0C0C", -}); - -interface TierlistBuilderProps { - weapons: (weapon & { - weapon_ability_link: (weapon_ability_link & { - weapon_ability: weapon_ability; - })[]; - weapon_skill_link: (weapon_skill_link & { - weapon_skill: weapon_skill; - })[]; - weapon_stat: weapon_stat[]; - })[]; -} - -export default function TierlistBuilder({ - weapons, -}: TierlistBuilderProps): JSX.Element { - const router = useRouter(); - const { filteredWeapons } = useFilteredWeapons({ weapons }); - - const showUnreleasedContent = useSettingsStore( - (state) => state.showUnreleasedContent - ); - - const addTierlist = useCreatedTierlists((state) => state.addTierlist); - - /** - * Inventory - */ - const [showOnlyInventory, setShowOnlyInventory] = useState(false); - const ownedWeapons = useInventoryStore((state) => state.weapons); - - /** - * Weapons - */ - const [state, setState] = useState([ - { - tier: "SSS", - description: "", - items: [], - }, - { - tier: "SS", - description: "", - items: [], - }, - { - tier: "S", - description: "", - items: [], - }, - { - tier: "A", - description: "", - items: [], - }, - { - tier: "B", - description: "", - items: [], - }, - { - tier: "ALL", - description: "", - items: [], - }, - ]); - const [yup, setYup] = useState(false); - const [titleModal, setTitleModal] = useState(false); - const [tooltipModal, setTooltipModal] = useState(false); - const [currentIndex, setCurrentIndex] = useState(0); - const [currentItemIndex, setCurrentItemIndex] = useState(0); - const [title, setTitle] = useState("My tierlist"); - const [description, setDescription] = useState(DEFAULT_DESCRIPTION); - const [attribute, setAttribute] = useState("all"); - const [currentTooltip, setCurrentTooltip] = useState(""); - const [tierDescription, setTierDescription] = useState(""); - const [loading, setLoading] = useState(false); - - /** - * Fetch existing tierlist if edit_key is found. - */ - useEffect(() => { - if (router.query.edit_key) { - getExistingTierlist(); - } - }, [router]); - - useEffect(() => { - setYup(true); - }, []); - - useEffect(() => { - const filteredSelection = getWeaponsSelection(); - - setState( - produce(state, (draft) => { - draft[draft.length - 1].items = filteredSelection; - }) - ); - }, [filteredWeapons]); - - function onDragEnd(result) { - const { source, destination } = result; - - // dropped outside the list - if (!destination) { - return; - } - const sInd = +source.droppableId; - const dInd = +destination.droppableId; - - if (sInd === dInd) { - const items = reorder(state[sInd].items, source.index, destination.index); - const newState = [...state]; - newState[sInd].items = items; - setState(newState); - } else { - const result = move( - state[sInd].items, - state[dInd].items, - source, - destination - ); - const newState = [...state]; - newState[sInd] = { - ...newState[sInd], - items: result[sInd], - }; - - newState[dInd] = { - ...newState[dInd], - items: result[dInd], - }; - - setState(newState); - } - } - - function moveTierUp(index) { - setState( - produce(state, (draft) => { - if (index > 0) { - const item = state[index]; - draft.splice(index, 1); - draft.splice(index - 1, 0, item); - } - }) - ); - } - - function moveTierDown(index) { - if (index + 1 === state.length - 1) { - return; - } - - setState( - produce(state, (draft) => { - const item = state[index]; - draft.splice(index, 1); - draft.splice(index + 1, 0, item); - }) - ); - } - - function removeTier(index) { - if (window.confirm("Are you sure you want to delete this tier?")) { - setState( - produce(state, (draft) => { - draft.splice(index, 1); - }) - ); - } - } - - function editTitle(index) { - setCurrentIndex(index); - setTitleModal(true); - } - - function handleTitleModalClose(event) { - event.preventDefault(); - const value = event.target.elements[0].value || state[currentIndex].tier; - - const newState = produce(state, (draft) => { - draft[currentIndex].tier = value; - draft[currentIndex].description = tierDescription; - }); - setState(newState); - setTitleModal(false); - setCurrentIndex(0); - setTierDescription(""); - } - - function handleTooltipModalClose() { - const newState = produce(state, (draft) => { - if (!currentTooltip) { - return; - } - // Update content - if (currentTooltip === "

") { - draft[currentIndex].items[currentItemIndex].tooltip = ""; - return; - } - - draft[currentIndex].items[currentItemIndex].tooltip = currentTooltip; - }); - setState(newState); - setTooltipModal(false); - setCurrentIndex(0); - setCurrentItemIndex(0); - setCurrentTooltip(""); - } - - function getWeaponsSelection() { - const filtered = filteredWeapons - .filter((costume) => { - if (showUnreleasedContent) return true; - return new Date() > new Date(costume.release_time); - }) - .filter((weap) => { - if (!showOnlyInventory) return true; - return ownedWeapons.includes(weap.weapon_id); - }) - .map((weap) => ({ - ...weap, - id: `${weap.weapon_id}-${new Date().toISOString()}`, - tooltip: "", - tooltip_is_important: false, - })); - - return filtered; - } - - async function getExistingTierlist() { - try { - setLoading(true); - const { data } = await axios.get( - `/api/tierlists?edit_key=${router.query.edit_key}` - ); - const { tierlist, tiers } = data; - const filteredSelection = getWeaponsSelection(); - const alreadySelectedItems = tiers.map((tier) => tier.items).flat(); - const newSelection = filteredSelection.filter((item) => { - const isSelected = alreadySelectedItems.findIndex( - (it) => it.item_id === item.weapon_id - ); - - if (isSelected >= 0) { - return false; - } - return true; - }); - setTitle(tierlist.title); - setDescription(tierlist.description); - setAttribute(tierlist.attribute); - setState([ - ...tiers, - { tier: "ALL", description: "", items: newSelection }, - ]); - } catch (error) { - console.error(error); - } finally { - setLoading(false); - } - } - - async function save() { - if (loading) return; - - try { - setLoading(true); - - const response = await axios({ - url: "/api/tierlists", - method: router.query.edit_key ? "PUT" : "POST", - data: { - title, - description, - type: "weapons", - attribute, - tiers: state.slice(0, state.length - 1), - edit_key: router.query.edit_key, - }, - }); - - toast.success("Tier list saved! Redirecting..."); - - addTierlist(response.data.tierlist); - - router.push(`/tierlist/${response.data.tierlist.slug}`); - } catch (error) { - toast.error(error.message); - } finally { - setLoading(false); - } - } - - return ( - - - - - -
-
-
-
- setTitle(e.target.value)} - /> -
-
- - Attribute - - -
-
- -
- setDescription(html)} - content={description} - /> -
-
-
- {loading &&
} - {(loading && Loading...) || ( - Save - )} -
- {yup && ( -
- - {state.map((el, ind) => ( - <> - {ind === state.length - 1 && ( -
- -
- )} - - {(provided, snapshot) => ( -
- {ind !== state.length - 1 && ( -
- - - -
- )} - - {ind !== state.length - 1 && ( - - )} - - {ind === state.length - 1 && ( -
-

Drag & Drop weapons into the tiers.

- - setShowOnlyInventory(e.target.checked) - } - /> -
- )} - -
- {ind !== state.length - 1 && ( -
- {ind !== state.length - 1 && ( -
- {(RANK_THUMBNAILS[el.tier] && ( - {el.tier} - )) ||

{el.tier}

} -
- )} -
- )} -
- {el.items?.map((item, index) => { - return ( - - {(provided, snapshot) => ( -
-
- {item.tooltip && ( -
- -
- )} - - {ind === state.length - 1 && ( -
- - {item.is_ex_weapon && ( - - EX{" "} - - )} - {item.name} - -
- )} - {ind !== state.length - 1 && ( - - - - )} -
-
- )} -
- ); - })} -
-
- - {el.description && ( -
- )} - - {ind === state.length - 1 && ( -
- - -b.weapon_type.localeCompare(a.weapon_type) - )} - onSelect={(e, weapon) => { - if (!weapon) { - return; - } - - setState( - produce(state, (draft) => { - draft[draft.length - 1].items.push({ - ...weapon, - id: new Date().toISOString(), - tooltip: "", - tooltip_is_important: false, - }); - }) - ); - }} - /> -
- )} - - {provided.placeholder} -
- )} -
- - ))} -
-
- )} -
- - setTitleModal(false)} - className="flex items-center justify-center" - aria-labelledby="modal-modal-title" - aria-describedby="modal-modal-description" - > -
- key)} - renderInput={(params) => ( - - )} - /> - setTierDescription(content)} - content={state[currentIndex]?.description ?? ""} - /> - - -
- - setTooltipModal(false)} - className="flex items-center justify-center" - aria-labelledby="modal-modal-title" - aria-describedby="modal-modal-description" - > -
- setCurrentTooltip(content)} - content={ - state[currentIndex]?.items[currentItemIndex]?.tooltip ?? - "Add new tooltip..." - } - /> -
- { - const newState = produce(state, (draft) => { - draft[currentIndex].items[ - currentItemIndex - ].tooltip_is_important = - !state[currentIndex]?.items[currentItemIndex] - ?.tooltip_is_important; - }); - - setState(newState); - }} - /> -
-
- -
-
-
-
- ); -} - -export async function getStaticProps() { - const { weapons } = await getAllWeapons(); - - return { - props: JSON.parse( - JSON.stringify({ - weapons, - }) - ), - }; -} From bed700490fe0769840d8731e9388b6a00718f40d Mon Sep 17 00:00:00 2001 From: KeziahMoselle Date: Wed, 13 Mar 2024 13:13:22 +0100 Subject: [PATCH 2/9] remove unecessary env --- src/env.ts | 21 --------------------- 1 file changed, 21 deletions(-) diff --git a/src/env.ts b/src/env.ts index 1501f9a5..e18749b5 100644 --- a/src/env.ts +++ b/src/env.ts @@ -6,21 +6,6 @@ export const env = envsafe({ choices: ["development", "production"], }), - /** - * API - */ - NEXT_PUBLIC_API_ENDPOINT: url({ - default: "https://strapi.nierrein.guide/", - }), - NEXT_PUBLIC_STRAPI_REST_API_ENDPOINT: url({}), - - /** - * Search - */ - NEXT_PUBLIC_SEARCH_ENDPOINT: url({ - default: "https://search.nierrein.guide", - }), - /** * Databases */ @@ -30,10 +15,4 @@ export const env = envsafe({ NIERREINGUIDE_DATABASE_URL: str({ desc: "Main database (loadouts...)", }), - - /** - * Post new events on Discord - */ - DISCORD_EVENTS_WEBHOOK_URL: url({}), - DISCORD_TIERLISTS_UPDATE_CHANNEL_WEBHOOK: url({}), }); From bc15e8d070d015be1526ba2c6891012353729bb2 Mon Sep 17 00:00:00 2001 From: KeziahMoselle Date: Fri, 22 Mar 2024 10:34:48 +0100 Subject: [PATCH 3/9] refactor: getstaticprops --- .nvmrc | 2 +- next.config.js | 4 +- package.json | 1 - src/components/CommunityTierlists.tsx | 111 +--------------------- src/components/LoadoutListingItem.tsx | 17 ---- src/components/TierlistListingItem.tsx | 20 ---- src/env.ts | 5 + src/libs/search.ts | 12 --- src/pages/database/assets/[folder].tsx | 93 ------------------ src/pages/database/assets/index.tsx | 87 ----------------- src/pages/database/stories/companions.tsx | 101 +------------------- src/pages/database/stories/costumes.tsx | 89 +++-------------- src/pages/database/stories/memoirs.tsx | 40 ++------ src/pages/database/stories/weapons.tsx | 72 +------------- src/pages/database/story/[slug].tsx | 84 ---------------- src/pages/event/[slug].tsx | 6 +- src/pages/guide/[slug].tsx | 6 +- src/pages/notice/[id].tsx | 6 +- src/pages/tierlist/[slug].tsx | 43 ++++----- src/pages/tierlists.tsx | 111 +--------------------- tailwind.config.js | 1 - 21 files changed, 66 insertions(+), 845 deletions(-) delete mode 100644 src/libs/search.ts delete mode 100644 src/pages/database/assets/[folder].tsx delete mode 100644 src/pages/database/assets/index.tsx delete mode 100644 src/pages/database/story/[slug].tsx diff --git a/.nvmrc b/.nvmrc index 975215f4..25bf17fc 100644 --- a/.nvmrc +++ b/.nvmrc @@ -1 +1 @@ -16.17.0 \ No newline at end of file +18 \ No newline at end of file diff --git a/next.config.js b/next.config.js index 99d83459..1eb3dc40 100644 --- a/next.config.js +++ b/next.config.js @@ -3,13 +3,11 @@ const withPWA = require('next-pwa')({ }) module.exports = withPWA({ + output: 'export', reactStrictMode: false, experimental: { largePageDataBytes: 1028 * 1000, }, - api: { - responseLimit: "16mb", - }, images: { domains: [ "reinguide-assets.s3.eu-central-1.wasabisys.com", diff --git a/package.json b/package.json index a9bbc45c..e9fd30b9 100644 --- a/package.json +++ b/package.json @@ -85,7 +85,6 @@ "zustand": "^4.3.7" }, "devDependencies": { - "@tailwindcss/line-clamp": "^0.4.4", "@types/marked": "^4.0.8", "@types/node": "^18.15.11", "@types/react": "^18.0.32", diff --git a/src/components/CommunityTierlists.tsx b/src/components/CommunityTierlists.tsx index 644b85f6..78b84569 100644 --- a/src/components/CommunityTierlists.tsx +++ b/src/components/CommunityTierlists.tsx @@ -1,15 +1,6 @@ import { tierlists } from "@prisma/client-nrg"; import TierlistListingItem from "@components/TierlistListingItem"; -import { FormControl, InputLabel, MenuItem, Select } from "@mui/material"; -import ATTRIBUTES from "@utils/attributes"; -import { useEffect, useRef, useState } from "react"; -import TextField from "@mui/material/TextField"; -import { useRouter } from "next/router"; -import { AdapterDateFns } from "@mui/x-date-pickers/AdapterDateFns"; -import { LocalizationProvider } from "@mui/x-date-pickers/LocalizationProvider"; -import { MobileDatePicker } from "@mui/x-date-pickers/MobileDatePicker"; import { sub } from "date-fns"; -import Link from "next/link"; interface LoadoutProps { tierlists: tierlists[]; @@ -22,114 +13,14 @@ export const defaultFromDate = sub(new Date(), { export default function ListingLoadout({ tierlists = [], }: LoadoutProps): JSX.Element { - const router = useRouter(); - const isFirstMount = useRef(true); - - const [sortBy, setSortBy] = useState("votes"); - const [fromDate, setFromDate] = useState(defaultFromDate); - const [attribute, setAttribute] = useState("all"); - const [type, setType] = useState("all"); - - useEffect(() => { - if (isFirstMount.current) { - return; - } - - router.push( - `/tierlists/community?attribute=${attribute}&type=${type}&from=${fromDate.toISOString()}&sortBy=${sortBy}` - ); - }, [attribute, type, fromDate, sortBy]); - - useEffect(() => { - if (type === "costumes") { - setAttribute("all"); - } - }, [type]); - - useEffect(() => { - isFirstMount.current = false; - }, []); return <> -
- - Sort by - - - - setFromDate(newValue)} - renderInput={(params) => } - /> - - - Type - - - {type === "weapons" && ( - - Attribute - - - )} -
- {tierlists.length > 0 && ( -
+
{tierlists.map((tierlist) => ( ))}
)} - - {tierlists.length === 0 && ( -
- Fio confused -

Sorry, no tierlist found.

-
- - Create one! - -
-
- )} ; } diff --git a/src/components/LoadoutListingItem.tsx b/src/components/LoadoutListingItem.tsx index 3266b22f..e4399547 100644 --- a/src/components/LoadoutListingItem.tsx +++ b/src/components/LoadoutListingItem.tsx @@ -24,22 +24,6 @@ export default function LoadoutListinItem({ const hasVoted = localVotes.includes(loadout_id); - async function vote() { - if (hasVoted) { - return; - } - - await axios.post("/api/loadouts/vote", { - loadout_id, - }); - - addVote(loadout_id); - - router.replace(router.asPath, undefined, { - scroll: false, - }); - } - return (
state.votes); - const addVote = useTierlistsVotes((state) => state.addVote); - const hasVoted = localVotes.includes(tierlist_id); - async function vote() { - if (hasVoted) { - return; - } - - await axios.post("/api/tierlists/vote", { - tierlist_id, - }); - - addVote(tierlist_id); - - router.replace(router.asPath, undefined, { - scroll: false, - }); - } - return (
- - - - -
-

Assets {folder}

- -
- {files.map((file) => ( -
- {`${file}`} -
- ))} -
-
- - ); -} - -export async function getStaticProps(context) { - const uiFolder = resolve( - process.cwd(), - "public", - "ui", - context.params.folder - ); - - const files = await readdir(uiFolder); - - const filteredFiles = files.filter( - (file) => file.endsWith(".png") || file.endsWith(".jpg") - ); - - return { - props: { - files: filteredFiles, - folder: context.params.folder, - }, - }; -} - -export async function getStaticPaths() { - const uiFolder = resolve(process.cwd(), "public", "ui"); - - const folders = await readdir(uiFolder); - - const paths = folders.map((folder) => ({ - params: { - folder, - }, - })); - - return { - paths, - fallback: false, - }; -} diff --git a/src/pages/database/assets/index.tsx b/src/pages/database/assets/index.tsx deleted file mode 100644 index b6206c17..00000000 --- a/src/pages/database/assets/index.tsx +++ /dev/null @@ -1,87 +0,0 @@ -import { readdir } from "fs/promises"; -import { resolve } from "path"; -import Layout from "@components/Layout"; -import Meta from "@components/Meta"; -import Link from "next/link"; -import SVG from "react-inlinesvg"; -import Image from "next/legacy/image"; - -interface DatabaseStoriesProps { - uiFolders: string[]; - uiFiles: string[]; -} - -export default function DatabaseStories({ - uiFolders, - uiFiles, -}: DatabaseStoriesProps): JSX.Element { - return ( - - - - - -
-

Assets

- -
- {uiFolders.map((folder, index) => ( - ( - - {`${folder} -

- {`${folder.charAt(0).toUpperCase()}${folder.slice( - 1 - )}`.replaceAll("_", " ")} -

- - ) - ))} -
-
-
- ); -} - -export async function getStaticProps() { - const uiFolder = resolve(process.cwd(), "public", "ui"); - - const uiFolders = await readdir(uiFolder); - - const uiFilesFetches = uiFolders.map((folder) => - readdir(resolve(uiFolder, folder)) - ); - const uiFiles = await Promise.all(uiFilesFetches); - - const filteredFiles = uiFiles.map((folder) => - folder.filter((file) => file.endsWith(".png") || file.endsWith(".jpg")) - ); - - return { - props: { - uiFolders, - uiFiles: filteredFiles, - }, - }; -} diff --git a/src/pages/database/stories/companions.tsx b/src/pages/database/stories/companions.tsx index a26b2966..d18c0114 100644 --- a/src/pages/database/stories/companions.tsx +++ b/src/pages/database/stories/companions.tsx @@ -1,54 +1,17 @@ import Layout from "@components/Layout"; import Meta from "@components/Meta"; -import { useEffect, useRef, useState } from "react"; import prisma from "@libs/prisma"; import { companion } from "@prisma/client"; -import { Autocomplete } from "@mui/material"; -import TextField from "@mui/material/TextField"; -import { useRouter } from "next/router"; -import { NextPageContext } from "next"; -import { Box } from "@mui/system"; -import { StoriesNavbar } from "./index"; -import { useSettingsStore } from "@store/settings"; import CompanionThumbnail from "@components/CompanionThumbnail"; import StoriesLayout from "@components/Layout/StoriesLayout"; interface DatabaseStoriesCompanionsProps { - companions: companion[]; allCompanions: companion[]; } export default function DatabaseStoriesCompanions({ - companions, allCompanions, }: DatabaseStoriesCompanionsProps): JSX.Element { - const router = useRouter(); - const firstUpdate = useRef(true); - - const showUnreleasedContent = useSettingsStore( - (state) => state.showUnreleasedContent - ); - - const [companionId, setCompanionId] = useState("all"); - - useEffect(() => { - if (firstUpdate.current) return; - const params = new URLSearchParams(); - - if (companionId !== "all") { - params.append("companion_id", companionId.toString()); - } - - router.push(`/database/stories/companions?${params.toString()}`); - }, [companionId]); - - useEffect(() => { - if (firstUpdate.current) { - firstUpdate.current = false; - return; - } - }, []); - return ( -
- { - if (!companion) { - setCompanionId("all"); - return; - } - setCompanionId(companion.companion_id); - }} - className="w-full md:w-72" - options={allCompanions} - getOptionLabel={(option) => - typeof option === "object" && `${option.name}` - } - autoHighlight - renderOption={(props, option) => ( - img": { mr: 2, flexShrink: 0 } }} - {...props} - > - -

{option.name}

-
- )} - renderInput={(params) => ( - - )} - /> -
-
- {companions - .filter((companion) => { - if (showUnreleasedContent) return true; - return new Date() > new Date(companion.release_time); - }) + {allCompanions .map((companion) => (
state.showUnreleasedContent - ); - - const [fromDate, setFromDate] = useState(DEFAULT_FROM_DATE); const [costumeSlug, setCostumeSlug] = useState("all"); const [characterSlug, setCharacterSlug] = useState("all"); - useEffect(() => { - if (firstUpdate.current) return; - const params = new URLSearchParams(); - - if (characterSlug !== "all" && costumeSlug === "all") { - params.append("character", characterSlug); - } - if (costumeSlug !== "all") { - params.append("costume", costumeSlug); - } - if (costumeSlug !== "all" && characterSlug !== "all") { - setCharacterSlug("all"); - return; - } - if (costumeSlug === "all") { - params.append("from", fromDate.toISOString()); - } - - router.push(`/database/stories/costumes?${params.toString()}`); - }, [characterSlug, costumeSlug, fromDate]); - - useEffect(() => { - if (firstUpdate.current) { - firstUpdate.current = false; - return; - } - }, []); - function resetFilters() { - setFromDate(DEFAULT_FROM_DATE); setCostumeSlug("all"); setCharacterSlug("all"); } @@ -142,7 +105,10 @@ export default function DatabaseStoriesCostumes({ />

or

{ + if (characterSlug === 'all') return true; + return costume.character.slug === characterSlug; + })} onSelect={(e, costume) => { if (!costume) { setCostumeSlug("all"); @@ -151,22 +117,16 @@ export default function DatabaseStoriesCostumes({ setCostumeSlug(costume.slug); }} /> - - setFromDate(newValue)} - renderInput={(params) => } - /> -
{costumes .filter((costume) => { - if (showUnreleasedContent) return true; - return new Date() > new Date(costume.release_time); + if (costumeSlug === 'all') return true; + return costume.slug === costumeSlug; + }) + .filter((costume) => { + if (characterSlug === 'all') return true; + return costume.character.slug === characterSlug; }) .map((costume) => (
("all"); - useEffect(() => { - if (firstUpdate.current) return; - const params = new URLSearchParams(); - - if (serieId !== "all") { - params.append("memoir_series_id", serieId.toString()); - } - - router.push(`/database/stories/memoirs?${params.toString()}`); - }, [serieId]); - - useEffect(() => { - if (firstUpdate.current) { - firstUpdate.current = false; - return; - } - }, []); - return (
- {memoirs.map((memoir) => ( + {memoirs + .filter((memoir) => { + if (serieId === 'all') return true; + return memoir.series_id === serieId; + }) + .map((memoir) => (
state.showUnreleasedContent - ); - - const [fromDate, setFromDate] = useState(DEFAULT_FROM_DATE); const [weaponSlug, setWeaponSlug] = useState("all"); - useEffect(() => { - if (firstUpdate.current) return; - const params = new URLSearchParams(); - - if (weaponSlug !== "all") { - params.append("weapon", weaponSlug); - } else { - params.append("from", fromDate.toISOString()); - } - - router.push(`/database/stories/weapons?${params.toString()}`); - }, [weaponSlug, fromDate]); - - useEffect(() => { - if (firstUpdate.current) { - firstUpdate.current = false; - return; - } - }, []); - function resetFilters() { - setFromDate(DEFAULT_FROM_DATE); setWeaponSlug("all"); } @@ -124,23 +89,13 @@ export default function DatabaseStoriesWeapons({ /> )} /> - - setFromDate(newValue)} - renderInput={(params) => } - /> -
{weapons - .filter((costume) => { - if (showUnreleasedContent) return true; - return new Date() > new Date(costume.release_time); + .filter((weapon) => { + if (weaponSlug === 'all') return true; + return weapon.slug === weaponSlug; }) .map((weapon) => (
- {!router.isFallback && ( - - )} - - - - {(router.isFallback &&

Loading...

) || ( - <> -
-

- {story.attributes.title} -

-
- -
- - -
-
- - )} - - ); -} - -export async function getStaticProps(context) { - const story = await getStory(context.params.slug); - - return { - props: { - story, - }, - }; -} - -export async function getStaticPaths() { - const stories = await getAllStories(); - - const paths = stories.map((story) => ({ - params: { slug: story.attributes.slug }, - })); - - return { - paths, - fallback: true, - }; -} diff --git a/src/pages/event/[slug].tsx b/src/pages/event/[slug].tsx index 978b766d..cd404702 100644 --- a/src/pages/event/[slug].tsx +++ b/src/pages/event/[slug].tsx @@ -211,8 +211,8 @@ export default function SingleEvent({ ); } -export async function getStaticProps(context) { - const event = await getEventBySlug(context.params.slug); +export async function getStaticProps({ params }) { + const event = await getEventBySlug(params.slug); const linked = await prisma.nrg.costumes_link.findMany({ where: { @@ -252,6 +252,6 @@ export async function getStaticPaths() { return { paths, - fallback: "blocking", + fallback: false, }; } diff --git a/src/pages/guide/[slug].tsx b/src/pages/guide/[slug].tsx index c5713be4..66675dd5 100644 --- a/src/pages/guide/[slug].tsx +++ b/src/pages/guide/[slug].tsx @@ -92,8 +92,8 @@ export default function SingleGuide({ guide }: GuideProps): JSX.Element { ); } -export async function getStaticProps(context) { - const guide = await getGuideBySlug(context.params.slug); +export async function getStaticProps({ params }) { + const guide = await getGuideBySlug(params.slug); return { props: { @@ -111,6 +111,6 @@ export async function getStaticPaths() { return { paths, - fallback: "blocking", + fallback: false, }; } diff --git a/src/pages/notice/[id].tsx b/src/pages/notice/[id].tsx index 50cd3ee4..2e86c6b3 100644 --- a/src/pages/notice/[id].tsx +++ b/src/pages/notice/[id].tsx @@ -76,10 +76,10 @@ export default function SingleNotice({ ); } -export async function getStaticProps(context) { +export async function getStaticProps({ params }) { const notification = await prisma.nrg.notification.findFirst({ where: { - notification_id: Number(context.params.id), + notification_id: Number(params.id), }, }); @@ -105,6 +105,6 @@ export async function getStaticPaths() { return { paths, - fallback: "blocking", + fallback: false, }; } diff --git a/src/pages/tierlist/[slug].tsx b/src/pages/tierlist/[slug].tsx index aa1de6ea..f935d259 100644 --- a/src/pages/tierlist/[slug].tsx +++ b/src/pages/tierlist/[slug].tsx @@ -1,7 +1,6 @@ import Image from "next/legacy/image"; import { formatDistanceToNow, differenceInDays } from "date-fns"; import { tiers, tiers_items, tierlists } from "@prisma/client-nrg"; -import { NextPageContext } from "next"; import { character, costume } from "@prisma/client"; import CostumeThumbnail from "@components/CostumeThumbnail"; import { CDN_URL, FEATURED_TIERLISTS } from "@config/constants"; @@ -11,7 +10,6 @@ import Layout from "@components/Layout"; import WeaponThumbnail from "@components/WeaponThumbnail"; import { RANK_THUMBNAILS } from "@utils/rankThumbnails"; import { useTierlistsVotes } from "@store/tierlist-votes"; -import axios from "axios"; import { useRouter } from "next/router"; import { Button, @@ -150,22 +148,6 @@ export function TierlistContent({ const hasVoted = localVotes.includes(tierlist.tierlist_id); - async function vote() { - if (hasVoted) { - return; - } - - await axios.post("/api/tierlists/vote", { - tierlist_id: tierlist.tierlist_id, - }); - - addVote(tierlist.tierlist_id); - - router.replace(router.asPath, undefined, { - scroll: false, - }); - } - function toggleContent() { wysiwyg.current.classList.toggle("max-h-36"); setIsContentExpanded(!isContentExpanded); @@ -294,7 +276,6 @@ export function TierlistContent({
@@ -924,7 +922,6 @@ function SingleStat({ name, value, type, icon }): JSX.Element {
{name} )) || ( {`${costume.title} diff --git a/src/components/CostumePanel.tsx b/src/components/CostumePanel.tsx index 2610c6a5..543e4d84 100644 --- a/src/components/CostumePanel.tsx +++ b/src/components/CostumePanel.tsx @@ -15,7 +15,7 @@ import { weapon, } from "@prisma/client"; import { Event } from "@models/types"; -import Image from "next/legacy/image"; + import weaponsIcons from "@utils/weaponsIcons"; import classNames from "classnames"; import { CDN_URL } from "@config/constants"; diff --git a/src/components/CostumeThumbnail.tsx b/src/components/CostumeThumbnail.tsx index 328325d2..7b9bcb7c 100644 --- a/src/components/CostumeThumbnail.tsx +++ b/src/components/CostumeThumbnail.tsx @@ -1,7 +1,7 @@ import weaponsIcons from "@utils/weaponsIcons"; import RARITY from "@utils/rarity"; import classNames from "classnames"; -import Image from "next/legacy/image"; + import SVG from "react-inlinesvg"; import Link from "next/link"; import WeaponThumbnail from "./WeaponThumbnail"; @@ -110,10 +110,7 @@ export default function CostumeThumbnail({ }} > {alt} @@ -129,7 +126,7 @@ export default function CostumeThumbnail({ "relative", sizeClasses, onClick || href - ? "cursor-pointer hover:scale-105 transition transform" + ? "cursor-pointer hover:scale-105 transition transform overflow-hidden" : "", className )} @@ -137,10 +134,15 @@ export default function CostumeThumbnail({ backgroundImage: `url(/decorations/background_rarity_${costumeRarity}.png)`, }} > + {alt} + {src && ( @@ -153,7 +155,7 @@ export default function CostumeThumbnail({ left: "1px", }} > - {alt} + {alt}
)} {attribute && ( @@ -168,14 +170,6 @@ export default function CostumeThumbnail({
)} - {alt} - {href && ( See costume diff --git a/src/components/Credits.tsx b/src/components/Credits.tsx index d30f898a..d7784340 100644 --- a/src/components/Credits.tsx +++ b/src/components/Credits.tsx @@ -1,10 +1,11 @@ import { CREDITS } from "config/constants"; import Lines from "@components/decorations/Lines"; -import Image from "next/legacy/image"; -import mamaImg from "../../public/mama.png"; + import slugify from "slugify"; import classNames from "classnames"; +const mamaImg = "/mama.png"; + export default function Credits(): JSX.Element { return (
diff --git a/src/components/CurrentEvents.tsx b/src/components/CurrentEvents.tsx index c21c79f5..53e7cd4f 100644 --- a/src/components/CurrentEvents.tsx +++ b/src/components/CurrentEvents.tsx @@ -1,4 +1,4 @@ -import Image from "next/legacy/image"; + import Link from "next/link"; import { Event } from "@models/types"; import { formatDistanceToNow } from "date-fns"; diff --git a/src/components/DailyQuests.tsx b/src/components/DailyQuests.tsx index 878f8191..ae04314e 100644 --- a/src/components/DailyQuests.tsx +++ b/src/components/DailyQuests.tsx @@ -1,7 +1,7 @@ import { GAME_TIMEZONE } from "@config/constants"; import { utcToZonedTime } from "date-fns-tz"; import React from "react"; -import Image from "next/legacy/image"; + import Disclosure from "@components/Disclosure"; // used for listing all daily types @@ -80,11 +80,11 @@ const dailyTypes = (dayOfWeek: number): DailyInfo => { } }; -import tanzaniteIcon from "../../public/ui/material/material321011_standard.png"; -import topazIcon from "../../public/ui/material/material321010_standard.png"; -import emeraldIcon from "../../public/ui/material/material321009_standard.png"; -import aquamarineIcon from "../../public/ui/material/material321008_standard.png"; -import rubyIcon from "../../public/ui/material/material321007_standard.png"; +const tanzaniteIcon = "/ui/material/material321011_standard.png"; +const topazIcon = "/ui/material/material321010_standard.png"; +const emeraldIcon = "/ui/material/material321009_standard.png"; +const aquamarineIcon = "/ui/material/material321008_standard.png"; +const rubyIcon = "/ui/material/material321007_standard.png"; const gemToIcon = (gem: string) => { switch (gem) { @@ -101,13 +101,13 @@ const gemToIcon = (gem: string) => { } }; -import swordIcon from "../../public/ui/material/material321001_standard.png"; -import greatswordIcon from "../../public/ui/material/material321002_standard.png"; -import spearIcon from "../../public/ui/material/material321003_standard.png"; -import fistIcon from "../../public/ui/material/material321004_standard.png"; -import staffIcon from "../../public/ui/material/material321005_standard.png"; -import gunIcon from "../../public/ui/material/material321006_standard.png"; -import { format } from "date-fns"; +const swordIcon = "/ui/material/material321001_standard.png"; +const greatswordIcon = "/ui/material/material321002_standard.png"; +const spearIcon = "/ui/material/material321003_standard.png"; +const fistIcon = "/ui/material/material321004_standard.png"; +const staffIcon = "/ui/material/material321005_standard.png"; +const gunIcon = "/ui/material/material321006_standard.png"; +const { format } from "date-fns"; const weaponToIcon = (weapon: string): StaticImageData => { switch (weapon) { diff --git a/src/components/DatabaseNavbar.tsx b/src/components/DatabaseNavbar.tsx index 9c9f953e..a154d686 100644 --- a/src/components/DatabaseNavbar.tsx +++ b/src/components/DatabaseNavbar.tsx @@ -3,21 +3,22 @@ import { useRouter } from "next/router"; import { MdFilterAlt, MdViewColumn, MdViewComfy } from "react-icons/md"; import * as Popover from "@radix-ui/react-popover"; -import loadoutsIcon from "../../public/icons/loadout.png"; -import charactersIcon from "../../public/icons/characters.png"; -import abilitiesIcon from "../../public/icons/abilities.png"; -import debrisIcon from "../../public/icons/debris.png"; -import companionsIcon from "../../public/icons/companions.png"; -import memoirsIcon from "../../public/icons/memoirs.png"; -import emblemsIcon from "../../public/icons/emblems.png"; -import storiesIcon from "../../public/icons/stories.png"; -import noticesIcon from "../../public/icons/notices.png"; -import eventsIcon from "../../public/icons/events.png"; import { Button, ToggleButton, ToggleButtonGroup } from "@mui/material"; import Checkbox from "./form/Checkbox"; import { FiFilter } from "react-icons/fi"; import { useCostumesFilters } from "@store/costumes-filters"; +const loadoutsIcon = "/icons/loadout.png"; +const charactersIcon = "/icons/characters.png"; +const abilitiesIcon = "/icons/abilities.png"; +const debrisIcon = "/icons/debris.png"; +const companionsIcon = "/icons/companions.png"; +const memoirsIcon = "/icons/memoirs.png"; +const emblemsIcon = "/icons/emblems.png"; +const storiesIcon = "/icons/stories.png"; +const noticesIcon = "/icons/notices.png"; +const eventsIcon = "/icons/events.png"; + const SUPPORTED_MULTIPLE_DISPLAY = ["/characters", "/weapons"]; export const ITEMS = [ diff --git a/src/components/DebrisThumbnail.tsx b/src/components/DebrisThumbnail.tsx index 23d3b09e..91bf104c 100644 --- a/src/components/DebrisThumbnail.tsx +++ b/src/components/DebrisThumbnail.tsx @@ -1,5 +1,5 @@ import classNames from "classnames"; -import Image from "next/legacy/image"; + import { CDN_URL } from "@config/constants"; import { debris } from "@prisma/client"; diff --git a/src/components/Element.tsx b/src/components/Element.tsx index 2397f2a5..b0dc34a5 100644 --- a/src/components/Element.tsx +++ b/src/components/Element.tsx @@ -1,4 +1,4 @@ -import Image from "next/legacy/image"; + import { ElementTypes } from "@models/types"; // import { ElementTypes } from "@models/types"; // import darkIcon from "../../public/elements/dark.png"; diff --git a/src/components/EventsSlider.tsx b/src/components/EventsSlider.tsx index dc1541bd..4b8be3f7 100644 --- a/src/components/EventsSlider.tsx +++ b/src/components/EventsSlider.tsx @@ -1,7 +1,7 @@ import { Swiper, SwiperSlide } from "swiper/react"; import { Pagination, Navigation, A11y } from "swiper"; import { Event } from "@models/types"; -import Image from "next/legacy/image"; + import formatDistanceToNow from "date-fns/formatDistanceToNow"; import SVG from "react-inlinesvg"; import { useState } from "react"; @@ -61,8 +61,7 @@ export default function EventsSlider({
diff --git a/src/components/Layout/Header.tsx b/src/components/Layout/Header.tsx index 7874203c..d8d7c7b5 100644 --- a/src/components/Layout/Header.tsx +++ b/src/components/Layout/Header.tsx @@ -1,7 +1,7 @@ import classNames from "classnames"; import { useRouter } from "next/router"; import Link from "next/link"; -import Image from "next/legacy/image"; + import { NAVIGATION } from "config/constants"; import Lottie from "react-lottie-player"; import logoData from "../../lottie/logo.json"; diff --git a/src/components/MemoirThumbnail.tsx b/src/components/MemoirThumbnail.tsx index 42da8750..f90e9819 100644 --- a/src/components/MemoirThumbnail.tsx +++ b/src/components/MemoirThumbnail.tsx @@ -1,6 +1,6 @@ import RARITY from "@utils/rarity"; import classNames from "classnames"; -import Image from "next/legacy/image"; + import { CDN_URL } from "@config/constants"; import { memoir } from "@prisma/client"; diff --git a/src/components/NewCostumes.tsx b/src/components/NewCostumes.tsx index e91b8a11..107bc30f 100644 --- a/src/components/NewCostumes.tsx +++ b/src/components/NewCostumes.tsx @@ -7,7 +7,7 @@ import slug from "slugg"; import classNames from "classnames"; import { useMedia } from "react-use"; import SVG from "react-inlinesvg"; -import Image from "next/legacy/image"; + import weaponsIcons from "@utils/weaponsIcons"; import { formatDistanceToNow } from "date-fns"; diff --git a/src/components/Poll.tsx b/src/components/Poll.tsx index 885c49a2..c94912a8 100644 --- a/src/components/Poll.tsx +++ b/src/components/Poll.tsx @@ -1,5 +1,5 @@ import { Event } from "@models/types"; -import Image from "next/legacy/image"; + interface PollProps { event: Event; diff --git a/src/components/Search.tsx b/src/components/Search.tsx index 922545e2..316bdc1f 100644 --- a/src/components/Search.tsx +++ b/src/components/Search.tsx @@ -1,14 +1,8 @@ import classNames from "classnames"; -import Image from "next/legacy/image"; -import CloseBtnIcon from "../../public/icons/close-btn.png"; + import { - InstantSearch, - InfiniteHits, - SearchBox, - Stats, Highlight, } from "react-instantsearch-dom"; -import { searchClient } from "@libs/search"; import { ICostume } from "./pages/costumes"; import { usePanelStore } from "@store/panels"; import { AiOutlinePushpin } from "react-icons/ai"; @@ -18,43 +12,7 @@ import AbilityThumbnail from "./AbilityThumbnail"; import SkillThumbnail from "./SkillThumbnail"; export function Search({ isOpen, setIsOpen }) { - function toggleSearchPanel() { - setIsOpen(!isOpen); - } - return null; - - return ( -
- -
- - -
-
- - -
-
-
- ); } function CostumeHit({ hit }: { hit: ICostume }) { diff --git a/src/components/Skill.tsx b/src/components/Skill.tsx index 3877a090..cb0a33a4 100644 --- a/src/components/Skill.tsx +++ b/src/components/Skill.tsx @@ -5,7 +5,7 @@ import skillGaugeColors, { skillGaugeBorderColors, } from "@utils/skillGaugeColors"; import classNames from "classnames"; -import Image from "next/legacy/image"; + import SVG from "react-inlinesvg"; import { Gauge } from "./Gauge"; @@ -58,11 +58,10 @@ export default function Skill({
diff --git a/src/components/StatDisplay.tsx b/src/components/StatDisplay.tsx index 5d33c871..eb03dc32 100644 --- a/src/components/StatDisplay.tsx +++ b/src/components/StatDisplay.tsx @@ -1,6 +1,6 @@ import classNames from "classnames"; import SVG from "react-inlinesvg"; -import Image from "next/legacy/image"; + import statsIcons from "@utils/statsIcons"; import Stat from "./Stat"; import { statsColors } from "@utils/statsColors"; diff --git a/src/components/StrapiImage.tsx b/src/components/StrapiImage.tsx index 6942f527..fd53f526 100644 --- a/src/components/StrapiImage.tsx +++ b/src/components/StrapiImage.tsx @@ -1,4 +1,4 @@ -import Image from "next/legacy/image"; + import { StrapiImage as StrapiImageType, StrapiImageFormats, diff --git a/src/components/TierlistListingItem.tsx b/src/components/TierlistListingItem.tsx index 1b37f804..4247aeec 100644 --- a/src/components/TierlistListingItem.tsx +++ b/src/components/TierlistListingItem.tsx @@ -8,7 +8,7 @@ import { FiThumbsUp } from "react-icons/fi"; import Tooltip from "@mui/material/Tooltip"; import { useTierlistsVotes } from "@store/tierlist-votes"; import { formatDistanceToNow } from "date-fns"; -import Image from "next/legacy/image"; + import { CDN_URL } from "@config/constants"; export default function TierlistListingItem({ diff --git a/src/components/WeaponInfo.tsx b/src/components/WeaponInfo.tsx index ab6262cd..eaa5151c 100644 --- a/src/components/WeaponInfo.tsx +++ b/src/components/WeaponInfo.tsx @@ -1,4 +1,4 @@ -import Image from "next/legacy/image"; + import weaponsIcons from "@utils/weaponsIcons"; import RARITY from "@utils/rarity"; import Star from "@components/decorations/Star"; diff --git a/src/components/WeaponThumbnail.tsx b/src/components/WeaponThumbnail.tsx index 46883ba1..60b18b4f 100644 --- a/src/components/WeaponThumbnail.tsx +++ b/src/components/WeaponThumbnail.tsx @@ -1,6 +1,6 @@ import RARITY from "@utils/rarity"; import classNames from "classnames"; -import Image from "next/legacy/image"; + import Element from "@components/Element"; import { ElementTypes, WeaponType } from "@models/types"; import weaponsIcons from "@utils/weaponsIcons"; @@ -107,9 +107,7 @@ export default function WeaponThumbnail({ }} > Mama icon used as star; diff --git a/src/components/decorations/Rank.tsx b/src/components/decorations/Rank.tsx index fa7c5ac2..a7231523 100644 --- a/src/components/decorations/Rank.tsx +++ b/src/components/decorations/Rank.tsx @@ -1,15 +1,15 @@ -import rankS from "../../../public/ui/search/search_rank_1.png"; -import rankA from "../../../public/ui/search/search_rank_2.png"; -import rankB from "../../../public/ui/search/search_rank_3.png"; -import rankC from "../../../public/ui/search/search_rank_4.png"; -import rankD from "../../../public/ui/search/search_rank_5.png"; -import rankE from "../../../public/ui/search/search_rank_6.png"; -import Image from "next/legacy/image"; +const rankS = "/ui/search/search_rank_1.png"; +const rankA = "/ui/search/search_rank_2.png"; +const rankB = "/ui/search/search_rank_3.png"; +const rankC = "/ui/search/search_rank_4.png"; +const rankD = "/ui/search/search_rank_5.png"; +const rankE = "/ui/search/search_rank_6.png"; + type ranks = "S" | "A" | "B" | "C" | "D" | "E"; export default function Rank({ rank }: { rank: ranks }): JSX.Element { - let img: StaticImageData; + let img: string; switch (rank) { case "S": img = rankS; diff --git a/src/components/decorations/Star.tsx b/src/components/decorations/Star.tsx index ecf50d10..d7c2c24d 100644 --- a/src/components/decorations/Star.tsx +++ b/src/components/decorations/Star.tsx @@ -3,7 +3,7 @@ import two from "../../../public/icons/stars/2_star_single.svg"; import three from "../../../public/icons/stars/3_star_single.svg"; import four from "../../../public/icons/stars/4_star_single.svg"; import five from "../../../public/icons/stars/5_star_single.svg"; -import Image from "next/legacy/image"; + const STAR_RARITY = { 1: one, diff --git a/src/components/pages/costumes.tsx b/src/components/pages/costumes.tsx index c20c6047..de71812c 100644 --- a/src/components/pages/costumes.tsx +++ b/src/components/pages/costumes.tsx @@ -15,7 +15,7 @@ import { costumes_link } from "@prisma/client-nrg"; import { CDN_URL, SKILLS_TYPES } from "@config/constants"; import CostumeThumbnail from "@components/CostumeThumbnail"; import RARITY from "@utils/rarity"; -import Image from "next/legacy/image"; + import SVG from "react-inlinesvg"; import MaterialTable from "@material-table/core"; import weaponsIcons from "@utils/weaponsIcons"; diff --git a/src/components/pages/tools.tsx b/src/components/pages/tools.tsx index dbf00521..ffa06c7c 100644 --- a/src/components/pages/tools.tsx +++ b/src/components/pages/tools.tsx @@ -1,6 +1,6 @@ import { TOOLS } from "@config/constants"; import classNames from "classnames"; -import Image from "next/legacy/image"; + import Link from "next/link"; function ListingTools() { @@ -31,9 +31,7 @@ function ListingItem({ href, src, label, classes }) { {label} diff --git a/src/components/pages/weapons.tsx b/src/components/pages/weapons.tsx index d8e7c41d..cae865ba 100644 --- a/src/components/pages/weapons.tsx +++ b/src/components/pages/weapons.tsx @@ -4,7 +4,7 @@ import React, { useEffect, useMemo, useState } from "react"; import MaterialTable from "@material-table/core"; import Element from "@components/Element"; import WeaponThumbnail from "@components/WeaponThumbnail"; -import Image from "next/legacy/image"; + import weaponsIcons from "@utils/weaponsIcons"; import SVG from "react-inlinesvg"; import Star from "@components/decorations/Star"; diff --git a/src/components/tierlist/TierList.tsx b/src/components/tierlist/TierList.tsx index 9364ef49..69039bde 100644 --- a/src/components/tierlist/TierList.tsx +++ b/src/components/tierlist/TierList.tsx @@ -1,4 +1,4 @@ -import Image from "next/legacy/image"; + import { formatDistanceToNow } from "date-fns"; import { RANK_THUMBNAILS } from "@utils/rankThumbnails"; diff --git a/src/components/tierlist/TierLogo.tsx b/src/components/tierlist/TierLogo.tsx index 17f53aa4..5d1e8d1a 100644 --- a/src/components/tierlist/TierLogo.tsx +++ b/src/components/tierlist/TierLogo.tsx @@ -1,5 +1,5 @@ import { RANK_THUMBNAILS } from "@utils/rankThumbnails"; -import Image from "next/legacy/image"; + export default function TierLogo({ tier }: { tier: string }) { if (RANK_THUMBNAILS[tier]) { diff --git a/src/config/constants.tsx b/src/config/constants.tsx index cdc347ed..3a39ee1f 100644 --- a/src/config/constants.tsx +++ b/src/config/constants.tsx @@ -1,12 +1,13 @@ -import homeIcon from "../../public/icons/home.png"; -import guidesIcon from "../../public/icons/guides.png"; -import loadoutsIcon from "../../public/icons/loadout.png"; -import tierlistIcon from "../../public/icons/tierlist.png"; -import databaseIcon from "../../public/icons/database.png"; import { RiRedditFill, RiGithubFill, RiTwitterFill } from "react-icons/ri"; import { FaDiscord } from "react-icons/fa"; import { FiGithub } from "react-icons/fi"; +const homeIcon = "/icons/home.png"; +const guidesIcon = "/icons/guides.png"; +const loadoutsIcon = "/icons/loadout.png"; +const tierlistIcon = "/icons/tierlist.png"; +const databaseIcon = "/icons/database.png"; + /** * NAVIGATION LINKS */ diff --git a/src/pages/ability/costume/[slug].tsx b/src/pages/ability/costume/[slug].tsx index a18712f6..bc765b8f 100644 --- a/src/pages/ability/costume/[slug].tsx +++ b/src/pages/ability/costume/[slug].tsx @@ -22,7 +22,7 @@ import slug from "slugg"; import CostumeThumbnail from "@components/CostumeThumbnail"; import RARITY from "@utils/rarity"; import SVG from "react-inlinesvg"; -import Image from "next/legacy/image"; + import statsIcons from "@utils/statsIcons"; import { Chip } from "@mui/material"; import dynamic from "next/dynamic"; diff --git a/src/pages/ability/weapon/[slug].tsx b/src/pages/ability/weapon/[slug].tsx index 81df61c4..fb91c219 100644 --- a/src/pages/ability/weapon/[slug].tsx +++ b/src/pages/ability/weapon/[slug].tsx @@ -20,7 +20,7 @@ import classNames from "classnames"; import AbilityThumbnail from "@components/AbilityThumbnail"; import slug from "slugg"; import SVG from "react-inlinesvg"; -import Image from "next/legacy/image"; + import statsIcons from "@utils/statsIcons"; import { Chip } from "@mui/material"; import dynamic from "next/dynamic"; diff --git a/src/pages/community-tierlists.tsx b/src/pages/community-tierlists.tsx new file mode 100644 index 00000000..58124bcd --- /dev/null +++ b/src/pages/community-tierlists.tsx @@ -0,0 +1,80 @@ +import prisma from "@libs/prisma"; +import Layout from "@components/Layout"; +import Meta from "@components/Meta"; +import CommunityTierlists from "@components/CommunityTierlists"; +import { FEATURED_TIERLISTS } from "@config/constants"; +import { character } from "@prisma/client"; + +interface TierlistsPageProps { + characters: character[]; + tierlists; +} + +export default function TierlistsPageProps({ + tierlists, + characters, +}: TierlistsPageProps): JSX.Element { + + return ( + + + +
+

Community Tierlists

+ + +
+
+ ); +} + +export async function getStaticProps() { + const characters = await prisma.dump.character.findMany({}); + + const props = { + characters, + tierlists: [], + }; + + /** + * Community tierlists filters + */ + const where = { + updated_at: { + gte: undefined, + }, + }; + let orderBy = {}; + + // Exclude pinned tierlists + where.tierlist_id = { + notIn: [...FEATURED_TIERLISTS.pve, ...FEATURED_TIERLISTS.pvp], + }; + + // Exclude unlisted tierlists + where.is_unlisted = false; + + /** + * Order by + */ + + orderBy = { + votes: "desc", + }; + + const tierlists = await prisma.nrg.tierlists.findMany({ + orderBy, + where, + }); + + props.tierlists = tierlists; + + return JSON.parse( + JSON.stringify({ + props, + }) + ); +} diff --git a/src/pages/database.tsx b/src/pages/database.tsx index 9f76dc59..75189919 100644 --- a/src/pages/database.tsx +++ b/src/pages/database.tsx @@ -1,17 +1,16 @@ import Layout from "@components/Layout"; import Meta from "@components/Meta"; -import Image from "next/legacy/image"; import Link from "next/link"; -import storiesImg from "../../public/database/stories.jpg"; -import assetsImg from "../../public/database/assets.jpg"; -import emblemsImg from "../../public/database/emblems.jpg"; -import memoirsImg from "../../public/database/memoirs.jpg"; -import companionsImg from "../../public/database/companions.jpg"; -import debrisImg from "../../public/database/debris.jpg"; -import noticesImg from "../../public/database/notices.jpg"; -import eventsImg from "../../public/database/events.jpg"; -import abilitiesImg from "../../public/database/abilities.jpg"; +const storiesImg = "/database/stories.jpg"; +const assetsImg = "/database/assets.jpg"; +const emblemsImg = "/database/emblems.jpg"; +const memoirsImg = "/database/memoirs.jpg"; +const companionsImg = "/database/companions.jpg"; +const debrisImg = "/database/debris.jpg"; +const noticesImg = "/database/notices.jpg"; +const eventsImg = "/database/events.jpg"; +const abilitiesImg = "/database/abilities.jpg"; export default function Database(): JSX.Element { return ( @@ -30,9 +29,7 @@ export default function Database(): JSX.Element { Abilties thumbnail @@ -49,9 +46,7 @@ export default function Database(): JSX.Element { Memoirs thumbnail @@ -68,9 +63,7 @@ export default function Database(): JSX.Element { Companions thumbnail @@ -87,9 +80,7 @@ export default function Database(): JSX.Element { Debris thumbnail @@ -106,9 +97,7 @@ export default function Database(): JSX.Element { Notices thumbnail @@ -125,9 +114,7 @@ export default function Database(): JSX.Element { Events thumbnail @@ -144,9 +131,7 @@ export default function Database(): JSX.Element { Stories thumbnail @@ -163,9 +148,7 @@ export default function Database(): JSX.Element { Assets thumbnail @@ -182,9 +165,7 @@ export default function Database(): JSX.Element { Emblems thumbnail diff --git a/src/pages/database/artworks.tsx b/src/pages/database/artworks.tsx index 84be6422..389db12c 100644 --- a/src/pages/database/artworks.tsx +++ b/src/pages/database/artworks.tsx @@ -2,7 +2,7 @@ import Layout from "@components/Layout"; import Meta from "@components/Meta"; import Link from "next/link"; import SVG from "react-inlinesvg"; -import Image from "next/legacy/image"; + export default function DatabaseStories(): JSX.Element { return ( diff --git a/src/pages/database/memoirs.tsx b/src/pages/database/memoirs.tsx index e21725f6..a91a5f73 100644 --- a/src/pages/database/memoirs.tsx +++ b/src/pages/database/memoirs.tsx @@ -1,6 +1,6 @@ import Layout from "@components/Layout"; import Meta from "@components/Meta"; -import Image from "next/legacy/image"; + import prisma from "@libs/prisma"; import { CDN_URL } from "@config/constants"; import * as Tabs from "@radix-ui/react-tabs"; diff --git a/src/pages/database/stories/content.tsx b/src/pages/database/stories/content.tsx index d1b6a8f5..ca189cf5 100644 --- a/src/pages/database/stories/content.tsx +++ b/src/pages/database/stories/content.tsx @@ -3,7 +3,7 @@ import Meta from "@components/Meta"; import { getAllStories } from "@models/stories"; import { Story } from "@models/types"; import Link from "next/link"; -import Image from "next/legacy/image"; + import coverStory from "../../../../public/cover-story.jpg"; import { StoriesNavbar } from "./index"; @@ -35,8 +35,7 @@ export default function DatabaseStories({ className="transform transition-transform ease-out-cubic hover:scale-105" > PvP - - Community - + + + Community + + {/* PvE */} @@ -118,10 +123,6 @@ export default function TierlistsPageProps({ ))} - - - - @@ -141,39 +142,6 @@ export async function getStaticProps() { tierlists: [], }; - /** - * Community tierlists filters - */ - const where = { - updated_at: { - gte: undefined, - }, - }; - let orderBy = {}; - - // Exclude pinned tierlists - where.tierlist_id = { - notIn: [...FEATURED_TIERLISTS.pve, ...FEATURED_TIERLISTS.pvp], - }; - - // Exclude unlisted tierlists - where.is_unlisted = false; - - /** - * Order by - */ - - orderBy = { - votes: "desc", - }; - - const tierlists = await prisma.nrg.tierlists.findMany({ - orderBy, - where, - }); - - props.tierlists = tierlists; - return JSON.parse( JSON.stringify({ props, diff --git a/src/pages/tools/materials.tsx b/src/pages/tools/materials.tsx index 1bb3968d..5ae0d01f 100644 --- a/src/pages/tools/materials.tsx +++ b/src/pages/tools/materials.tsx @@ -1,6 +1,6 @@ import Layout from "@components/Layout"; import Meta from "@components/Meta"; -import Image from "next/legacy/image"; + import { useState } from "react"; import Link from "next/link"; import SVG from "react-inlinesvg"; diff --git a/src/utils/rankThumbnails.ts b/src/utils/rankThumbnails.ts index 3c0d236a..5e7ace07 100644 --- a/src/utils/rankThumbnails.ts +++ b/src/utils/rankThumbnails.ts @@ -1,13 +1,13 @@ -import SearchRankX from "../../public/ui/search/search_rank_x.png"; -import SearchRankSSS from "../../public/ui/search/search_rank_sss.png"; -import SearchRankSS from "../../public/ui/search/search_rank_ss.png"; -import SearchRankS from "../../public/ui/search/search_rank_1.png"; -import SearchRankA from "../../public/ui/search/search_rank_2.png"; -import SearchRankB from "../../public/ui/search/search_rank_3.png"; -import SearchRankC from "../../public/ui/search/search_rank_4.png"; -import SearchRankD from "../../public/ui/search/search_rank_5.png"; -import SearchRankE from "../../public/ui/search/search_rank_6.png"; -import SearchRankF from "../../public/ui/search/search_rank_7.png"; +const SearchRankX = "/ui/search/search_rank_x.png"; +const SearchRankSSS = "/ui/search/search_rank_sss.png"; +const SearchRankSS = "/ui/search/search_rank_ss.png"; +const SearchRankS = "/ui/search/search_rank_1.png"; +const SearchRankA = "/ui/search/search_rank_2.png"; +const SearchRankB = "/ui/search/search_rank_3.png"; +const SearchRankC = "/ui/search/search_rank_4.png"; +const SearchRankD = "/ui/search/search_rank_5.png"; +const SearchRankE = "/ui/search/search_rank_6.png"; +const SearchRankF = "/ui/search/search_rank_7.png"; export const RANK_THUMBNAILS = { X: SearchRankX, diff --git a/src/utils/statsIcons.ts b/src/utils/statsIcons.ts index aa6a8b3f..e3472be5 100644 --- a/src/utils/statsIcons.ts +++ b/src/utils/statsIcons.ts @@ -1,17 +1,17 @@ -import atkIcon from "../../public/stats/atk.png"; -import agilityIcon from "../../public/stats/agility.png"; -import cdIcon from "../../public/stats/cd.png"; -import crIcon from "../../public/stats/cr.png"; -import defIcon from "../../public/stats/def.png"; -import hpIcon from "../../public/stats/hp.png"; -import evasionIcon from "../../public/stats/evasion.png"; +const atkIcon = "/stats/atk.png"; +const agilityIcon = "/stats/agility.png"; +const cdIcon = "/stats/cd.png"; +const crIcon = "/stats/cr.png"; +const defIcon = "/stats/def.png"; +const hpIcon = "/stats/hp.png"; +const evasionIcon = "/stats/evasion.png"; -import largeAtkIcon from "../../public/icons/stats/atk.png"; -import largeAgiIcon from "../../public/icons/stats/agi.png"; -import largeCdIcon from "../../public/icons/stats/cd.png"; -import largeCrIcon from "../../public/icons/stats/cr.png"; -import largeDefIcon from "../../public/icons/stats/def.png"; -import largeHpIcon from "../../public/icons/stats/hp.png"; +const largeAtkIcon = "/icons/stats/atk.png"; +const largeAgiIcon = "/icons/stats/agi.png"; +const largeCdIcon = "/icons/stats/cd.png"; +const largeCrIcon = "/icons/stats/cr.png"; +const largeDefIcon = "/icons/stats/def.png"; +const largeHpIcon = "/icons/stats/hp.png"; const statsIcons = { atk: atkIcon, diff --git a/src/utils/weaponsIcons.ts b/src/utils/weaponsIcons.ts index 7c6b5427..53a3e104 100644 --- a/src/utils/weaponsIcons.ts +++ b/src/utils/weaponsIcons.ts @@ -1,17 +1,10 @@ -import swordIcon from "../../public/weapons_types/1h-sword.png"; -import bigSwordIcon from "../../public/weapons_types/2h-sword.png"; -import fistIcon from "../../public/weapons_types/fist.png"; -import gunIcon from "../../public/weapons_types/gun.png"; -import spearIcon from "../../public/weapons_types/spear.png"; -import staffIcon from "../../public/weapons_types/staff.png"; - const weaponsIcons = { - SWORD: swordIcon, - BIG_SWORD: bigSwordIcon, - FIST: fistIcon, - GUN: gunIcon, - SPEAR: spearIcon, - STAFF: staffIcon, + SWORD: '/weapons_types/1h-sword.png', + BIG_SWORD: '/weapons_types/2h-sword.png', + FIST: '/weapons_types/fist.png', + GUN: '/weapons_types/gun.png', + SPEAR: '/weapons_types/spear.png', + STAFF: '/weapons_types/staff.png', }; export default weaponsIcons; \ No newline at end of file From e5bd9a1b88f28893e1bce96bd5b39b88ee46a7e2 Mon Sep 17 00:00:00 2001 From: Keziah Date: Mon, 1 Apr 2024 16:48:26 +0200 Subject: [PATCH 7/9] fix: build --- src/components/DailyQuests.tsx | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/components/DailyQuests.tsx b/src/components/DailyQuests.tsx index ae04314e..62d20dd7 100644 --- a/src/components/DailyQuests.tsx +++ b/src/components/DailyQuests.tsx @@ -1,7 +1,7 @@ import { GAME_TIMEZONE } from "@config/constants"; import { utcToZonedTime } from "date-fns-tz"; import React from "react"; - +import { format } from "date-fns"; import Disclosure from "@components/Disclosure"; // used for listing all daily types @@ -107,7 +107,6 @@ const spearIcon = "/ui/material/material321003_standard.png"; const fistIcon = "/ui/material/material321004_standard.png"; const staffIcon = "/ui/material/material321005_standard.png"; const gunIcon = "/ui/material/material321006_standard.png"; -const { format } from "date-fns"; const weaponToIcon = (weapon: string): StaticImageData => { switch (weapon) { From 7a5851fff9ec17fac4536ed62d19d9a976871ee3 Mon Sep 17 00:00:00 2001 From: KeziahMoselle Date: Mon, 22 Apr 2024 16:13:36 +0200 Subject: [PATCH 8/9] fix: umami & weapon thumbnail --- src/components/WeaponThumbnail.tsx | 2 +- src/pages/_document.tsx | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/components/WeaponThumbnail.tsx b/src/components/WeaponThumbnail.tsx index 60b18b4f..8c9506bb 100644 --- a/src/components/WeaponThumbnail.tsx +++ b/src/components/WeaponThumbnail.tsx @@ -183,7 +183,7 @@ export default function WeaponThumbnail({ )} )} {/* Comment system */} From 448690fa85f752c0a0d2ec8bc94247bbd2605b1c Mon Sep 17 00:00:00 2001 From: KeziahMoselle Date: Mon, 22 Apr 2024 16:25:18 +0200 Subject: [PATCH 9/9] fix: costume thumbnail --- src/components/CostumeThumbnail.tsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/components/CostumeThumbnail.tsx b/src/components/CostumeThumbnail.tsx index 7b9bcb7c..7b1a9458 100644 --- a/src/components/CostumeThumbnail.tsx +++ b/src/components/CostumeThumbnail.tsx @@ -135,14 +135,14 @@ export default function CostumeThumbnail({ }} > {alt} {src && (