Skip to content

Commit

Permalink
feat: ✨ add mme info
Browse files Browse the repository at this point in the history
  • Loading branch information
lucca180 committed Feb 2, 2025
1 parent 30cdfa1 commit 8aa8bef
Show file tree
Hide file tree
Showing 7 changed files with 173 additions and 4 deletions.
65 changes: 65 additions & 0 deletions components/Items/MMECard.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
import { Flex, Text } from '@chakra-ui/react';
import React from 'react';
import { ItemData, ItemMMEData } from '../../types';
import CardBase from '../Card/CardBase';
import ItemCard from './ItemCard';
import { useTranslations } from 'next-intl';

type Props = {
item: ItemData;
mmeData: ItemMMEData;
};

const MMECard = (props: Props) => {
const t = useTranslations();
const { item, mmeData } = props;
const color = item.color.rgb;

return (
<CardBase title={`${mmeData.name} Info`} color={color}>
<Flex gap={3} wrap="wrap" alignItems="center" flexFlow={'column'}>
<Text fontSize={'sm'} textAlign={'center'}>
{t.rich('ItemPage.mme-text', {
b: (children) => <b>{children}</b>,
name: mmeData.name,
isMini: mmeData.isMini,
})}
</Text>
<Flex wrap="wrap" gap={2} alignItems="center" justifyContent={'center'}>
{Object.keys(mmeData.trails).map((trail) => (
<Flex
key={trail}
direction="column"
gap={2}
bg="blackAlpha.500"
p={3}
borderRadius={'md'}
>
<Text>
<b>
{t('ItemPage.mme-trail', {
x: trail.toUpperCase(),
})}
</b>
</Text>
<Flex wrap="wrap" gap={2} justifyContent={'center'}>
<ItemCard item={mmeData.initial} small />
{mmeData.trails[trail].map((i) => (
<ItemCard key={i.internal_id} item={i} small />
))}
</Flex>
</Flex>
))}
</Flex>
<Text fontSize={'sm'} textAlign={'center'}>
{t.rich('ItemPage.mme-chance', {
b: (children) => <b>{children}</b>,
})}
</Text>
<ItemCard item={mmeData.bonus} small isLE />
</Flex>
</CardBase>
);
};

export default MMECard;
79 changes: 79 additions & 0 deletions pages/api/v1/items/[id_name]/mme.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
import { NextApiRequest, NextApiResponse } from 'next';
import { getItem } from '.';
import { doSearch } from '../../search';
import { ItemData, ItemMMEData } from '../../../../../types';

const mmeRegex = /^(mini)?(MME)(\d+)/i;

export default async function handle(req: NextApiRequest, res: NextApiResponse) {
if (req.method === 'GET') return GET(req, res);

if (req.method == 'OPTIONS') {
res.setHeader('Access-Control-Allow-Methods', 'GET');
return res.status(200).json({});
}

return res.status(405).json({ error: 'Method not allowed' });
}

async function GET(req: NextApiRequest, res: NextApiResponse) {
const result = await getMMEData(req.query.id_name as string);

return res.status(200).json(result);
}

export const getMMEData = async (id_name: string | number): Promise<ItemMMEData | null> => {
const internal_id = Number(id_name);
const name = isNaN(internal_id) ? (id_name as string) : undefined;

const item = await getItem(name ?? internal_id);
if (!item) return null;

if (!isMME(item.name)) return null;
const mmeName = item.name.match(mmeRegex)![0];
console.log('MME Name:', mmeName);

const search = await doSearch(mmeName);

if (!search) return null;
const mmeItems = search.content.filter((i) => i.name.match(mmeRegex)?.[0] === mmeName);
const firstOne = mmeItems.find((i) => i.name.toLowerCase().includes('s1'));
const bonus = mmeItems.find((i) => i.name.toLowerCase().includes(mmeName.toLowerCase() + '-b'));

if (!firstOne || !bonus) return null;

const trails: { [name: string]: ItemData[] } = {};
const allTrails: ItemData[] = [];
for (const mmeItem of mmeItems) {
if (mmeItem.name === firstOne.name || mmeItem.name === bonus.name) continue;

const trailName = mmeItem.name.match(/(?<=S\d)[a-z]/gim)?.[0];
if (!trailName) {
allTrails.push(mmeItem);
console.error('No trail name found for', mmeItem.name);
continue;
}

if (!trails[trailName]) trails[trailName] = [];
trails[trailName].push(mmeItem);
}

Object.keys(trails).forEach((key) => {
trails[key].push(...allTrails);
trails[key] = trails[key].sort((a, b) => a.name.localeCompare(b.name));
});

if (Object.keys(trails).length === 0) {
trails['A'] = allTrails;
}

return {
name: mmeName,
isMini: mmeName.toLowerCase().includes('mini'),
initial: firstOne,
bonus,
trails,
};
};

export const isMME = (name: string) => !!name.match(mmeRegex);
4 changes: 2 additions & 2 deletions pages/api/v1/search/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -579,13 +579,13 @@ export async function doSearch(
? { value: null, addedAt: null, inflated: false }
: {
value: result.price ? result.price.toNumber() : null,
addedAt: result.priceAdded?.toJSON(),
addedAt: result.priceAdded?.toJSON() ?? null,
inflated: !!result.noInflation_id,
},
owls: result.owlsValue
? {
value: result.owlsValue,
pricedAt: result.owlsPriced,
pricedAt: result.owlsPriced.toJSON(),
valueMin: result.owlsValueMin,
buyable: result.owlsValue.toLowerCase().includes('buyable'),
}
Expand Down
9 changes: 9 additions & 0 deletions pages/item/[id].tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import {
ItemData,
ItemEffect,
ItemLastSeen,
ItemMMEData,
ItemOpenable,
ItemRecipe,
NCMallData,
Expand Down Expand Up @@ -44,6 +45,8 @@ import { getItemNCMall } from '../api/v1/items/[id_name]/ncmall';
import NcMallCard from '../../components/Items/NCMallCard';
import { getItemRecipes } from '../api/v1/items/[id_name]/recipes';
import { NextPageWithLayout } from '../_app';
import { getMMEData, isMME } from '../api/v1/items/[id_name]/mme';
import MMECard from '../../components/Items/MMECard';

const EditItemModal = dynamic<EditItemModalProps>(
() => import('../../components/Modal/EditItemModal')
Expand Down Expand Up @@ -82,6 +85,7 @@ type ItemPageProps = {
wearableData: WearableData[] | null;
ncMallData: NCMallData | null;
itemRecipes: ItemRecipe[] | null;
mmeData: ItemMMEData | null;
mainLayoutColor: string;
messages: any;
};
Expand All @@ -98,6 +102,7 @@ const ItemPage: NextPageWithLayout<ItemPageProps> = (props: ItemPageProps) => {
NPTrades: trades,
itemEffects,
itemRecipes,
mmeData,
} = props;
const [isEditModalOpen, setIsEditModalOpen] = useState(false);
const [feedbackModalOpen, setFeedbackModalOpen] = useState(false);
Expand Down Expand Up @@ -308,6 +313,7 @@ const ItemPage: NextPageWithLayout<ItemPageProps> = (props: ItemPageProps) => {
{itemEffects.length > 0 && <ItemEffectsCard item={item} effects={itemEffects} />}
{lists && <ItemOfficialLists item={item} lists={lists} />}
{!!user && <ItemMyLists item={item} />}
{mmeData && <MMECard item={item} mmeData={mmeData} />}
{itemRecipes && itemRecipes.length > 0 && (
<ItemRecipes item={item} recipes={itemRecipes} />
)}
Expand Down Expand Up @@ -388,6 +394,7 @@ export async function getStaticProps(context: GetStaticPropsContext) {
NCMallData,
itemRecipes,
colorRaw,
mmeData,
] = await Promise.all([
getItemColor([item.image_id]), //0
getItemLists(item.internal_id, true, false), // 1
Expand All @@ -405,6 +412,7 @@ export async function getStaticProps(context: GetStaticPropsContext) {
item.isNC ? getItemNCMall(item.internal_id) : null, // 11
!item.isNC ? getItemRecipes(item.internal_id) : null, // 12
import('color'), // 13
isMME(item.name) ? getMMEData(item.internal_id) : null, // 14
]);

if (!colors) return { notFound: true };
Expand All @@ -426,6 +434,7 @@ export async function getStaticProps(context: GetStaticPropsContext) {
wearableData: wearableData,
ncMallData: NCMallData,
itemRecipes: itemRecipes,
mmeData: mmeData,
mainLayoutColor: Color(item.color.hex).alpha(0.4).hexa(),
messages: (await import(`../../translation/${context.locale}.json`)).default,
};
Expand Down
5 changes: 4 additions & 1 deletion translation/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -247,7 +247,10 @@
"contribute-wall-2": "After that, you will be able to check the this data, <b>for every item</b>, for the next <b>24 hours</b> before needing to make another contribution.",
"latest-x-sold": "Latest {x} Sold",
"on-sale": "On Sale",
"added-to": "Added to <List></List>"
"added-to": "Added to <List></List>",
"mme-text": "This item is part of a <b>{isMini, select, true {Mini} other {}} Mysterious Morphing Experiments</b> ({name})",
"mme-chance": "You also have <b>a chance</b> of getting this item",
"mme-trail": "Trail {x}"
},
"Button": {
"feedback": "Feedback",
Expand Down
5 changes: 4 additions & 1 deletion translation/pt.json
Original file line number Diff line number Diff line change
Expand Up @@ -248,7 +248,10 @@
"contribute-wall-2": "Depois disso, você poderá conferir esses dados para <b>todos os itens</b> pelas próximas <b>24 horas</b> antes de precisar fazer outra contribuição.",
"latest-x-sold": "Últimos {x} Vendidos",
"on-sale": "Promoção",
"added-to": "Adicionado em <List></List>"
"added-to": "Adicionado em <List></List>",
"mme-text": "Esse item faz parte de um <b>{isMini, select, true {Mini} other {}} Mysterious Morphing Experiments</b> ({name})",
"mme-chance": "Você também tem <b>chances</b> de conseguir este item",
"mme-trail": "Trilha {x}"
},
"Button": {
"feedback": "Feedback",
Expand Down
10 changes: 10 additions & 0 deletions types.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -484,6 +484,16 @@ type ContributeWallData = {
needVotes: number;
};

type ItemMMEData = {
name: string;
isMini: boolean;
initial: ItemData;
bonus: ItemData;
trails: {
[trailName: string]: ItemData[];
};
};

// ------- FEEDBACKS JSON -------- //
export type Feedback = {
feedback_id: number;
Expand Down

0 comments on commit 8aa8bef

Please sign in to comment.