diff --git a/app/app/account/profile/decks/page.tsx b/app/app/account/profile/decks/page.tsx index 3292861..92c877c 100644 --- a/app/app/account/profile/decks/page.tsx +++ b/app/app/account/profile/decks/page.tsx @@ -47,7 +47,6 @@ interface bsetJson extends bset { interface cardEntryAPIProps { amount: number, sanitized_name: string, - set: string } interface deckAPIProps { @@ -97,24 +96,10 @@ export default function Signin() { function getDataFromLine(line: string){ if(line != "") { - const values = line.split(" ") - if (values.length >= 4) { - const amount: number = parseInt(values.at(0)!.toString()) - - let set_index = 0 - for(let i = 1; i < values.length; i++){ - if(values.at(-i)!.toString().match(/\([A-Z]{3}\)/gm)){ - set_index = -i - } - } - - const set = values.at(set_index)!.toString().replace(/[()]/gm,"").toLowerCase() - const card_name = values.slice(1,set_index).join(" ").replace(/[^a-zA-Z0-9]/gim,"-").toLowerCase() - const card_data : cardEntryAPIProps = {amount, sanitized_name: card_name, set} - return card_data - } else { - return null - } + const data = line.split(" ") + const amount = parseInt(data[0]) + const name = data.slice(1).join(" ").split("/")[0].replace(/[^a-zA-Z0-9]/gim,"-").toLowerCase() + return {"sanitized_name":name, "amount":amount} } else { return null } @@ -136,14 +121,15 @@ export default function Signin() { function updateDeckInput(txt:string){ setDeckImporter(txt) const lines = txt.split("\n") - setDeckCommanderName(lines[0]) + setDeckCommanderName(lines[lines.length - 1]) } function importDeck(){ const deckText = deckImporter - const lines = deckText.split("\n") + let lines = deckText.split("\n") + lines = lines.filter((line) => line.match(/[0-9]+\s[\w]+/) != undefined) const dataToSend : deckAPIProps = { name: deckName, selected_bset: selectedBset.replace(/[^a-zA-Z0-9]/gim,"-").toLowerCase() ,commander_name: getDataFromLine(deckCommanderName)!.sanitized_name, cards: [] } - lines.slice(1).forEach((line: string) => { + lines.slice(0, lines.length - 1).forEach((line: string) => { const data = getDataFromLine(line) if(data != null) { dataToSend.cards.push(data) @@ -151,7 +137,6 @@ export default function Signin() { }); console.log(dataToSend) - fetch('http://localhost:3000/api/account/decks/create', { method: "POST", headers: {Authorization: 'Bearer ' + token}, diff --git a/app/app/api/account/decks/create/route.ts b/app/app/api/account/decks/create/route.ts index 4cc2842..c8dfad2 100644 --- a/app/app/api/account/decks/create/route.ts +++ b/app/app/api/account/decks/create/route.ts @@ -14,7 +14,6 @@ interface orSetFilterProps { interface cardEntryAPIProps { amount: number, sanitized_name: string, - set: string } export async function POST(req: NextRequest) { @@ -62,20 +61,28 @@ export async function POST(req: NextRequest) { cardsFilter.push({sanitized_name: card.sanitized_name, OR: set_codes}) }) - const cardsData = await db.carte.findMany({ + let cardsData = await db.carte.findMany({ where: { - OR: cardsFilter + OR: set_codes } }) + + // Sort cards to select non promo types first and fallback to promo cards if not found + cardsData = cardsData.sort((a,b) => +a.is_promo - +b.is_promo) let allCardFound = true if(cardsData.findIndex(cardData => cardData.sanitized_name == commander_name) == -1){ - allCardFound = false + if(cardsData.findIndex(cardData => cardData.sanitized_name.includes(commander_name)) == -1){ + console.log(commander_name) + allCardFound = false + } } cards.forEach((card: cardEntryAPIProps) => { if(cardsData.findIndex(cardData => cardData.sanitized_name == card.sanitized_name) == -1){ - console.log(card) - allCardFound = false + if(cardsData.findIndex(cardData => cardData.sanitized_name.includes(card.sanitized_name)) == -1 ){ + console.log(card) + allCardFound = false + } } }) @@ -85,9 +92,12 @@ export async function POST(req: NextRequest) { }); } + const commander_card = cardsData.findIndex(cardData => cardData.sanitized_name == commander_name) == -1 ? cardsData[cardsData.findIndex(cardData => cardData.sanitized_name.includes(commander_name))] : cardsData[cardsData.findIndex(cardData => cardData.sanitized_name == commander_name)] + const deck = await db.deck.create({ data: { name, + color_identity: commander_card.color_identity, utilisateurice: { connect: { id: tokenData.id @@ -95,7 +105,7 @@ export async function POST(req: NextRequest) { }, commander: { connect: { - id: cardsData[cardsData.findIndex(cardData => cardData.sanitized_name == commander_name)].id + id: commander_card.id } }, bset: { @@ -107,7 +117,7 @@ export async function POST(req: NextRequest) { }) cards.forEach(async (card: cardEntryAPIProps) => { - const cardData_id = cardsData[cardsData.findIndex(cardData => cardData.sanitized_name == card.sanitized_name)].id + const cardData_id = cardsData.findIndex(cardData => cardData.sanitized_name == card.sanitized_name) == -1 ? cardsData[cardsData.findIndex(cardData => cardData.sanitized_name.includes(card.sanitized_name))].id : cardsData[cardsData.findIndex(cardData => cardData.sanitized_name == card.sanitized_name)].id console.log(card.sanitized_name) await db.cartes_dans_deck.create({ data: { diff --git a/app/app/bset/[bset]/page.tsx b/app/app/bset/[bset]/page.tsx new file mode 100644 index 0000000..2469a28 --- /dev/null +++ b/app/app/bset/[bset]/page.tsx @@ -0,0 +1,10 @@ +'use server' + +import PageContent from './page_content' + +export default async function Home({ params }: { params: { bset: string } } ) { + const bset = (await params).bset + return ( + + ); +} diff --git a/app/app/bset/[bset]/page_content.tsx b/app/app/bset/[bset]/page_content.tsx new file mode 100644 index 0000000..c6a70bd --- /dev/null +++ b/app/app/bset/[bset]/page_content.tsx @@ -0,0 +1,50 @@ +'use client' + +import { useEffect, useState } from 'react' +import { CardGroup } from '@/components/ui/card-group' + +interface PageContentProps { + bset: string +} + +export default function PageContent({bset}: PageContentProps) { + const [commanderList, setCommanderList] = useState([]) + const [creatureList, setCreatureList] = useState([]) + const [planeswalkerList, setPlaneswalkerList] = useState([]) + const [instantList, setInstantList] = useState([]) + const [sorceryList, setSorceryList] = useState([]) + const [artifactList, setArtifactList] = useState([]) + const [enchantmentList, setEnchantmentList] = useState([]) + const [landList, setLandList] = useState([]) + + useEffect(() => { + fetch('http://localhost:8072/bset/'+bset+'.json').then((res) => { + if(res.status == 200) { + res.json().then((data) => { + const limit = 20 + setCommanderList(data["commander"].slice(0,limit)) + setCreatureList(data["creature"].slice(0,limit)) + setPlaneswalkerList(data["planeswalker"].slice(0,limit)) + setSorceryList(data["sorcery"].slice(0,limit)) + setInstantList(data["instant"].slice(0,limit)) + setEnchantmentList(data["enchantment"].slice(0,limit)) + setLandList(data["land"].slice(0,limit)) + setArtifactList(data["artifact"].slice(0,limit)) + console.log(data) + }) + } + }) + }, []) + return ( +
+ + + + + + + + +
+ ); +} diff --git a/app/app/bset/all/page.tsx b/app/app/bset/all/page.tsx new file mode 100644 index 0000000..48a0da6 --- /dev/null +++ b/app/app/bset/all/page.tsx @@ -0,0 +1,39 @@ +'use client' + +import { useEffect, useState } from 'react' + +interface bsetJsonObject { + name: string, + sanitized_name: string, + set_codes: string[], + icons: string[] +} + + +export default function Home() { + const [BsetList, setBsetList] = useState([]) + + useEffect(() => { + fetch('http://localhost:8072/misc/bsets.json').then((res) => { + if(res.status == 200) { + res.json().then((data) => { + setBsetList(data) + }) + } + }) + }, []) + return ( +
+ { BsetList.map((bset: bsetJsonObject) => ( + +
+ { bset.icons.map((icon) => ( + + ))} +
+ {bset.name} +
+ ))} +
+ ); +} diff --git a/app/app/commander/[color]/page.tsx b/app/app/commander/[color]/page.tsx new file mode 100644 index 0000000..37fb45f --- /dev/null +++ b/app/app/commander/[color]/page.tsx @@ -0,0 +1,10 @@ +'use server' + +import PageContent from './page_content' + +export default async function Home({ params }: { params: { color: string } } ) { + const color = (await params).color + return ( + + ); +} diff --git a/app/app/commander/[color]/page_content.tsx b/app/app/commander/[color]/page_content.tsx new file mode 100644 index 0000000..120f2bf --- /dev/null +++ b/app/app/commander/[color]/page_content.tsx @@ -0,0 +1,29 @@ +'use client' + +import { useEffect, useState } from 'react' +import { CardGroup } from '@/components/ui/card-group' + +interface PageContentProps { + color: string +} + +export default function PageContent({color}: PageContentProps) { + const [commanderCardList, setCommanderCardList] = useState([]) + + useEffect(() => { + fetch('http://localhost:8072/commander/'+color+'.json').then((res) => { + if(res.status == 200) { + res.json().then((data) => { + const limit = 20 + setCommanderCardList(data.slice(0,limit)) + console.log(data) + }) + } + }) + }, []) + return ( +
+ +
+ ); +} diff --git a/app/app/commander/top/page.tsx b/app/app/commander/top/page.tsx new file mode 100644 index 0000000..7b61e02 --- /dev/null +++ b/app/app/commander/top/page.tsx @@ -0,0 +1,25 @@ +'use client' + +import { useEffect, useState } from 'react' +import { CardGroup } from '@/components/ui/card-group' + +export default function Home() { + const [commanderCardList, setCommanderCardList] = useState([]) + + useEffect(() => { + fetch('http://localhost:8072/commander/top.json').then((res) => { + if(res.status == 200) { + res.json().then((data) => { + const limit = 20 + setCommanderCardList(data.slice(0,limit)) + console.log(data) + }) + } + }) + }, []) + return ( +
+ +
+ ); +} diff --git a/app/app/top/black/page.tsx b/app/app/top/black/page.tsx deleted file mode 100644 index d8ac0ef..0000000 --- a/app/app/top/black/page.tsx +++ /dev/null @@ -1,91 +0,0 @@ -'use client' - -import { useEffect, useState } from 'react' -import { MTGCard } from '@/components/ui/mtg-card' - -interface carte_from_stats { - id: string, - name: string, - normal_image: string, - sanitized_name: string, - nbr_decks: number, - total_decks: number, - percent_decks: number, - price: string, - cardmarket_uri: string -} - -export default function Home() { - const [creatureCardList, setCreatureCardList] = useState([]) - const [instantCardList, setInstantCardList] = useState([]) - const [sorceryCardList, setSorceryCardList] = useState([]) - const [planeswalkerCardList, setPlaneswalkerCardList] = useState([]) - const [artifactCardList, setArtifactCardList] = useState([]) - const [enchantmentCardList, setEnchantmentCardList] = useState([]) - const [landCardList, setLandCardList] = useState([]) - - useEffect(() => { - fetch('http://localhost:8072/top/mono-black.json').then((res) => { - if(res.status == 200) { - res.json().then((data) => { - const limit = 20 - setCreatureCardList(data["creature"].slice(0,limit)) - setInstantCardList(data["instant"].slice(0,limit)) - setSorceryCardList(data["sorcery"].slice(0,limit)) - setPlaneswalkerCardList(data["planeswalker"].slice(0,limit)) - setArtifactCardList(data["artifact"].slice(0,limit)) - setEnchantmentCardList(data["enchantment"].slice(0,limit)) - setLandCardList(data["land"].slice(0,limit)) - console.log(data) - }) - } - }) - }, []) - return ( -
-

Creature

-
- {creatureCardList.map((card: carte_from_stats) => ( - - ))} -
-

Instants

-
- {instantCardList.map((card: carte_from_stats) => ( - - ))} -
-

Sorceries

-
- {sorceryCardList.map((card: carte_from_stats) => ( - - ))} -
-

Enchantment

-
- {enchantmentCardList.map((card: carte_from_stats) => ( - - ))} -
-

Planeswalker

-
- {planeswalkerCardList.map((card: carte_from_stats) => ( - - ))} -
-

Artifact

-
- {artifactCardList.map((card: carte_from_stats) => ( - - ))} -
-

Lands

-
- {landCardList.map((card: carte_from_stats) => ( - - ))} -
- -
- ); -} diff --git a/app/app/top/blue/page.tsx b/app/app/top/blue/page.tsx deleted file mode 100644 index 379a9fd..0000000 --- a/app/app/top/blue/page.tsx +++ /dev/null @@ -1,91 +0,0 @@ -'use client' - -import { useEffect, useState } from 'react' -import { MTGCard } from '@/components/ui/mtg-card' - -interface carte_from_stats { - id: string, - name: string, - normal_image: string, - sanitized_name: string, - nbr_decks: number, - total_decks: number, - percent_decks: number, - price: string, - cardmarket_uri: string -} - -export default function Home() { - const [creatureCardList, setCreatureCardList] = useState([]) - const [instantCardList, setInstantCardList] = useState([]) - const [sorceryCardList, setSorceryCardList] = useState([]) - const [planeswalkerCardList, setPlaneswalkerCardList] = useState([]) - const [artifactCardList, setArtifactCardList] = useState([]) - const [enchantmentCardList, setEnchantmentCardList] = useState([]) - const [landCardList, setLandCardList] = useState([]) - - useEffect(() => { - fetch('http://localhost:8072/top/mono-blue.json').then((res) => { - if(res.status == 200) { - res.json().then((data) => { - const limit = 20 - setCreatureCardList(data["creature"].slice(0,limit)) - setInstantCardList(data["instant"].slice(0,limit)) - setSorceryCardList(data["sorcery"].slice(0,limit)) - setPlaneswalkerCardList(data["planeswalker"].slice(0,limit)) - setArtifactCardList(data["artifact"].slice(0,limit)) - setEnchantmentCardList(data["enchantment"].slice(0,limit)) - setLandCardList(data["land"].slice(0,limit)) - console.log(data) - }) - } - }) - }, []) - return ( -
-

Creature

-
- {creatureCardList.map((card: carte_from_stats) => ( - - ))} -
-

Instants

-
- {instantCardList.map((card: carte_from_stats) => ( - - ))} -
-

Sorceries

-
- {sorceryCardList.map((card: carte_from_stats) => ( - - ))} -
-

Enchantment

-
- {enchantmentCardList.map((card: carte_from_stats) => ( - - ))} -
-

Planeswalker

-
- {planeswalkerCardList.map((card: carte_from_stats) => ( - - ))} -
-

Artifact

-
- {artifactCardList.map((card: carte_from_stats) => ( - - ))} -
-

Lands

-
- {landCardList.map((card: carte_from_stats) => ( - - ))} -
- -
- ); -} diff --git a/app/app/top/colorless/page.tsx b/app/app/top/colorless/page.tsx deleted file mode 100644 index 4cd2eb1..0000000 --- a/app/app/top/colorless/page.tsx +++ /dev/null @@ -1,91 +0,0 @@ -'use client' - -import { useEffect, useState } from 'react' -import { MTGCard } from '@/components/ui/mtg-card' - -interface carte_from_stats { - id: string, - name: string, - normal_image: string, - sanitized_name: string, - nbr_decks: number, - total_decks: number, - percent_decks: number, - price: string, - cardmarket_uri: string -} - -export default function Home() { - const [creatureCardList, setCreatureCardList] = useState([]) - const [instantCardList, setInstantCardList] = useState([]) - const [sorceryCardList, setSorceryCardList] = useState([]) - const [planeswalkerCardList, setPlaneswalkerCardList] = useState([]) - const [artifactCardList, setArtifactCardList] = useState([]) - const [enchantmentCardList, setEnchantmentCardList] = useState([]) - const [landCardList, setLandCardList] = useState([]) - - useEffect(() => { - fetch('http://localhost:8072/top/mono-colorless.json').then((res) => { - if(res.status == 200) { - res.json().then((data) => { - const limit = 20 - setCreatureCardList(data["creature"].slice(0,limit)) - setInstantCardList(data["instant"].slice(0,limit)) - setSorceryCardList(data["sorcery"].slice(0,limit)) - setPlaneswalkerCardList(data["planeswalker"].slice(0,limit)) - setArtifactCardList(data["artifact"].slice(0,limit)) - setEnchantmentCardList(data["enchantment"].slice(0,limit)) - setLandCardList(data["land"].slice(0,limit)) - console.log(data) - }) - } - }) - }, []) - return ( -
-

Creature

-
- {creatureCardList.map((card: carte_from_stats) => ( - - ))} -
-

Instants

-
- {instantCardList.map((card: carte_from_stats) => ( - - ))} -
-

Sorceries

-
- {sorceryCardList.map((card: carte_from_stats) => ( - - ))} -
-

Enchantment

-
- {enchantmentCardList.map((card: carte_from_stats) => ( - - ))} -
-

Planeswalker

-
- {planeswalkerCardList.map((card: carte_from_stats) => ( - - ))} -
-

Artifact

-
- {artifactCardList.map((card: carte_from_stats) => ( - - ))} -
-

Lands

-
- {landCardList.map((card: carte_from_stats) => ( - - ))} -
- -
- ); -} diff --git a/app/app/top/green/page.tsx b/app/app/top/green/page.tsx deleted file mode 100644 index e5c5f42..0000000 --- a/app/app/top/green/page.tsx +++ /dev/null @@ -1,91 +0,0 @@ -'use client' - -import { useEffect, useState } from 'react' -import { MTGCard } from '@/components/ui/mtg-card' - -interface carte_from_stats { - id: string, - name: string, - normal_image: string, - sanitized_name: string, - nbr_decks: number, - total_decks: number, - percent_decks: number, - price: string, - cardmarket_uri: string -} - -export default function Home() { - const [creatureCardList, setCreatureCardList] = useState([]) - const [instantCardList, setInstantCardList] = useState([]) - const [sorceryCardList, setSorceryCardList] = useState([]) - const [planeswalkerCardList, setPlaneswalkerCardList] = useState([]) - const [artifactCardList, setArtifactCardList] = useState([]) - const [enchantmentCardList, setEnchantmentCardList] = useState([]) - const [landCardList, setLandCardList] = useState([]) - - useEffect(() => { - fetch('http://localhost:8072/top/mono-green.json').then((res) => { - if(res.status == 200) { - res.json().then((data) => { - const limit = 20 - setCreatureCardList(data["creature"].slice(0,limit)) - setInstantCardList(data["instant"].slice(0,limit)) - setSorceryCardList(data["sorcery"].slice(0,limit)) - setPlaneswalkerCardList(data["planeswalker"].slice(0,limit)) - setArtifactCardList(data["artifact"].slice(0,limit)) - setEnchantmentCardList(data["enchantment"].slice(0,limit)) - setLandCardList(data["land"].slice(0,limit)) - console.log(data) - }) - } - }) - }, []) - return ( -
-

Creature

-
- {creatureCardList.map((card: carte_from_stats) => ( - - ))} -
-

Instants

-
- {instantCardList.map((card: carte_from_stats) => ( - - ))} -
-

Sorceries

-
- {sorceryCardList.map((card: carte_from_stats) => ( - - ))} -
-

Enchantment

-
- {enchantmentCardList.map((card: carte_from_stats) => ( - - ))} -
-

Planeswalker

-
- {planeswalkerCardList.map((card: carte_from_stats) => ( - - ))} -
-

Artifact

-
- {artifactCardList.map((card: carte_from_stats) => ( - - ))} -
-

Lands

-
- {landCardList.map((card: carte_from_stats) => ( - - ))} -
- -
- ); -} diff --git a/app/app/top/multicolor/page.tsx b/app/app/top/multicolor/page.tsx deleted file mode 100644 index 5cc4194..0000000 --- a/app/app/top/multicolor/page.tsx +++ /dev/null @@ -1,91 +0,0 @@ -'use client' - -import { useEffect, useState } from 'react' -import { MTGCard } from '@/components/ui/mtg-card' - -interface carte_from_stats { - id: string, - name: string, - normal_image: string, - sanitized_name: string, - nbr_decks: number, - total_decks: number, - percent_decks: number, - price: string, - cardmarket_uri: string -} - -export default function Home() { - const [creatureCardList, setCreatureCardList] = useState([]) - const [instantCardList, setInstantCardList] = useState([]) - const [sorceryCardList, setSorceryCardList] = useState([]) - const [planeswalkerCardList, setPlaneswalkerCardList] = useState([]) - const [artifactCardList, setArtifactCardList] = useState([]) - const [enchantmentCardList, setEnchantmentCardList] = useState([]) - const [landCardList, setLandCardList] = useState([]) - - useEffect(() => { - fetch('http://localhost:8072/top/mono-multicolor.json').then((res) => { - if(res.status == 200) { - res.json().then((data) => { - const limit = 20 - setCreatureCardList(data["creature"].slice(0,limit)) - setInstantCardList(data["instant"].slice(0,limit)) - setSorceryCardList(data["sorcery"].slice(0,limit)) - setPlaneswalkerCardList(data["planeswalker"].slice(0,limit)) - setArtifactCardList(data["artifact"].slice(0,limit)) - setEnchantmentCardList(data["enchantment"].slice(0,limit)) - setLandCardList(data["land"].slice(0,limit)) - console.log(data) - }) - } - }) - }, []) - return ( -
-

Creature

-
- {creatureCardList.map((card: carte_from_stats) => ( - - ))} -
-

Instants

-
- {instantCardList.map((card: carte_from_stats) => ( - - ))} -
-

Sorceries

-
- {sorceryCardList.map((card: carte_from_stats) => ( - - ))} -
-

Enchantment

-
- {enchantmentCardList.map((card: carte_from_stats) => ( - - ))} -
-

Planeswalker

-
- {planeswalkerCardList.map((card: carte_from_stats) => ( - - ))} -
-

Artifact

-
- {artifactCardList.map((card: carte_from_stats) => ( - - ))} -
-

Lands

-
- {landCardList.map((card: carte_from_stats) => ( - - ))} -
- -
- ); -} diff --git a/app/app/top/red/page.tsx b/app/app/top/red/page.tsx deleted file mode 100644 index bda446c..0000000 --- a/app/app/top/red/page.tsx +++ /dev/null @@ -1,91 +0,0 @@ -'use client' - -import { useEffect, useState } from 'react' -import { MTGCard } from '@/components/ui/mtg-card' - -interface carte_from_stats { - id: string, - name: string, - normal_image: string, - sanitized_name: string, - nbr_decks: number, - total_decks: number, - percent_decks: number, - price: string, - cardmarket_uri: string -} - -export default function Home() { - const [creatureCardList, setCreatureCardList] = useState([]) - const [instantCardList, setInstantCardList] = useState([]) - const [sorceryCardList, setSorceryCardList] = useState([]) - const [planeswalkerCardList, setPlaneswalkerCardList] = useState([]) - const [artifactCardList, setArtifactCardList] = useState([]) - const [enchantmentCardList, setEnchantmentCardList] = useState([]) - const [landCardList, setLandCardList] = useState([]) - - useEffect(() => { - fetch('http://localhost:8072/top/mono-red.json').then((res) => { - if(res.status == 200) { - res.json().then((data) => { - const limit = 20 - setCreatureCardList(data["creature"].slice(0,limit)) - setInstantCardList(data["instant"].slice(0,limit)) - setSorceryCardList(data["sorcery"].slice(0,limit)) - setPlaneswalkerCardList(data["planeswalker"].slice(0,limit)) - setArtifactCardList(data["artifact"].slice(0,limit)) - setEnchantmentCardList(data["enchantment"].slice(0,limit)) - setLandCardList(data["land"].slice(0,limit)) - console.log(data) - }) - } - }) - }, []) - return ( -
-

Creature

-
- {creatureCardList.map((card: carte_from_stats) => ( - - ))} -
-

Instants

-
- {instantCardList.map((card: carte_from_stats) => ( - - ))} -
-

Sorceries

-
- {sorceryCardList.map((card: carte_from_stats) => ( - - ))} -
-

Enchantment

-
- {enchantmentCardList.map((card: carte_from_stats) => ( - - ))} -
-

Planeswalker

-
- {planeswalkerCardList.map((card: carte_from_stats) => ( - - ))} -
-

Artifact

-
- {artifactCardList.map((card: carte_from_stats) => ( - - ))} -
-

Lands

-
- {landCardList.map((card: carte_from_stats) => ( - - ))} -
- -
- ); -} diff --git a/app/app/top/white/page.tsx b/app/app/top/white/page.tsx deleted file mode 100644 index 6d6b211..0000000 --- a/app/app/top/white/page.tsx +++ /dev/null @@ -1,91 +0,0 @@ -'use client' - -import { useEffect, useState } from 'react' -import { MTGCard } from '@/components/ui/mtg-card' - -interface carte_from_stats { - id: string, - name: string, - normal_image: string, - sanitized_name: string, - nbr_decks: number, - total_decks: number, - percent_decks: number, - price: string, - cardmarket_uri: string -} - -export default function Home() { - const [creatureCardList, setCreatureCardList] = useState([]) - const [instantCardList, setInstantCardList] = useState([]) - const [sorceryCardList, setSorceryCardList] = useState([]) - const [planeswalkerCardList, setPlaneswalkerCardList] = useState([]) - const [artifactCardList, setArtifactCardList] = useState([]) - const [enchantmentCardList, setEnchantmentCardList] = useState([]) - const [landCardList, setLandCardList] = useState([]) - - useEffect(() => { - fetch('http://localhost:8072/top/mono-white.json').then((res) => { - if(res.status == 200) { - res.json().then((data) => { - const limit = 20 - setCreatureCardList(data["creature"].slice(0,limit)) - setInstantCardList(data["instant"].slice(0,limit)) - setSorceryCardList(data["sorcery"].slice(0,limit)) - setPlaneswalkerCardList(data["planeswalker"].slice(0,limit)) - setArtifactCardList(data["artifact"].slice(0,limit)) - setEnchantmentCardList(data["enchantment"].slice(0,limit)) - setLandCardList(data["land"].slice(0,limit)) - console.log(data) - }) - } - }) - }, []) - return ( -
-

Creature

-
- {creatureCardList.map((card: carte_from_stats) => ( - - ))} -
-

Instants

-
- {instantCardList.map((card: carte_from_stats) => ( - - ))} -
-

Sorceries

-
- {sorceryCardList.map((card: carte_from_stats) => ( - - ))} -
-

Enchantment

-
- {enchantmentCardList.map((card: carte_from_stats) => ( - - ))} -
-

Planeswalker

-
- {planeswalkerCardList.map((card: carte_from_stats) => ( - - ))} -
-

Artifact

-
- {artifactCardList.map((card: carte_from_stats) => ( - - ))} -
-

Lands

-
- {landCardList.map((card: carte_from_stats) => ( - - ))} -
- -
- ); -} diff --git a/app/components/ui/card-group.tsx b/app/components/ui/card-group.tsx new file mode 100644 index 0000000..ba5ea52 --- /dev/null +++ b/app/components/ui/card-group.tsx @@ -0,0 +1,46 @@ +import * as React from "react" + +import { cn } from "@/lib/utils" +import { MTGCardProps } from "@/components/ui/mtg-card" +import { MTGCard } from '@/components/ui/mtg-card' + +interface carte_from_stats { + id: string, + name: string, + normal_image: string, + sanitized_name: string, + nbr_decks: number, + total_decks: number, + percent_decks: number, + price: string, + cardmarket_uri: string +} + +interface CardGroupProps { + className?: string, + groupName: string, + cards: carte_from_stats[], + showPrice?: boolean, + showStats?: boolean +} + +const CardGroup = ({ className, groupName, cards, showPrice=true, showStats=true}: CardGroupProps) => { + return ( +
+

{groupName}

+
+ + {cards.map((card: carte_from_stats) => ( + + ))} +
+
+ )} +MTGCard.displayName = "MTGCard" + +export { CardGroup } diff --git a/app/components/ui/card-page.tsx b/app/components/ui/card-page.tsx new file mode 100644 index 0000000..e69de29 diff --git a/app/components/ui/mtg-card.tsx b/app/components/ui/mtg-card.tsx index b4d49ca..3317881 100644 --- a/app/components/ui/mtg-card.tsx +++ b/app/components/ui/mtg-card.tsx @@ -44,4 +44,4 @@ const MTGCard = ({ className, imageURI, cardname, url, nbrDecks, totalDecks, per )} MTGCard.displayName = "MTGCard" -export { MTGCard } +export { MTGCard, type MTGCardProps } diff --git a/app/components/ui/navigation-bar.tsx b/app/components/ui/navigation-bar.tsx index 43bc371..37fedd3 100644 --- a/app/components/ui/navigation-bar.tsx +++ b/app/components/ui/navigation-bar.tsx @@ -18,13 +18,36 @@ import { Input } from "@/components/ui/input" import { Button } from "@/components/ui/button" import { IconUserFilled } from "@tabler/icons-react" import { Black, Blue, Green, White, Red, Colorless } from "@/components/ui/mana-icons" +import { useEffect, useState } from 'react' interface NavigationProps { isLoggedIn: boolean, username: string } + +interface bsetJsonObject { + name: string, + sanitized_name: string, + set_codes: string[], + icons: string[] +} + export function NavigationBar ({ isLoggedIn, username}: NavigationProps) { + const [bsetsList, setBsetsList] = useState([]) + + useEffect(() => { + fetch('http://localhost:8072/misc/bsets.json').then((res) => { + if(res.status == 200) { + res.json().then((data) => { + setBsetsList(data) + console.log(data) + }) + } + }) + }, []) + + return (
@@ -34,137 +57,12 @@ export function NavigationBar ({ isLoggedIn, username}: NavigationProps) { - + - Top cartes - - - Terrains - - - Cartes salées - - - - Par couleurs - - - - - - - Blanc - - - - - - Bleu - - - - - - Noir - - - - - - Rouge - - - - - - Vert - - - - - - Incolor - - - - - Multicolor - - - - - - - - Par type - - - - - Créatures - - - Éphémères - - - Rituels - - - Artefacts - - - Équipements - - - Artefacts de mana - - - Artefacts utilitaires - - - Enchantements - - - Aura - - - Planeswalker - - - Terrains - - - Terrains utilitaires - - - Terrains ajusteurs - - - - - - Combos - - - - - - - - - - - - Top commandant·es - - - Second plan - - - Partenaires + Top commandants @@ -173,28 +71,40 @@ export function NavigationBar ({ isLoggedIn, username}: NavigationProps) { - - Blanc + + + White + - - Bleu + + + Bleu + - - Noir + + + Noir + - - Rouge + + + Rouge + - - Vert + + + Vert + - - Incolor + + + Incolor + @@ -206,54 +116,74 @@ export function NavigationBar ({ isLoggedIn, username}: NavigationProps) { - - - Azorius + + + + Azorius + - - - Dimir + + + + Dimir + - - - Rakdos + + + + Rakdos + - - - Gruul + + + + Gruul + - - - Selesnya + + + + Selesnya + - - - Orzhov + + + + Orzhov + - - - Izzet + + + + Izzet + - - - Golgari + + + + Golgari + - - - Boros + + + + Boros + - - - Simic + + + + Simic + @@ -265,64 +195,84 @@ export function NavigationBar ({ isLoggedIn, username}: NavigationProps) { - - - - Esper + + + + + Esper + - - - - Grixis + + + + + Grixis + - - - - Jund + + + + + Jund + - - - - Naya + + + + + Naya + - - - - Bant + + + + + Bant + - - - - Abzan + + + + + Abzan + - - - - Jeskai + + + + + Jeskai + - - - - Sultai + + + + + Sultai + - - - - Mardu + + + + + Mardu + - - - - Temur + + + + + Temur + @@ -334,47 +284,59 @@ export function NavigationBar ({ isLoggedIn, username}: NavigationProps) { - - - - - Yore-Tiller + + + + + + Yore-Tiller + - - - - - Glint-Eye + + + + + + Glint-Eye + - - - - - Dune-Brood + + + + + + Dune-Brood + - - - - - Ink-Treader + + + + + + Ink-Treader + - - - - - Witch-Maw + + + + + + Witch-Maw + - - - - - - 5 couleurs + + + + + + + 5 couleurs + @@ -382,6 +344,35 @@ export function NavigationBar ({ isLoggedIn, username}: NavigationProps) { + + + + + + + { bsetsList.length == 0 && ( + + Loading + + )} + { bsetsList.length != 0 && bsetsList.slice(0,7).map((bset) => ( + + +
+ { bset.icons.map((icon) => ( + + ))} +
+ {bset.name} +
+
+ ))} + + Plus de BSets... + +
+
+
diff --git a/app/prisma/schema.prisma b/app/prisma/schema.prisma index cbd3fe2..7444167 100644 --- a/app/prisma/schema.prisma +++ b/app/prisma/schema.prisma @@ -28,7 +28,7 @@ model carte { normal_image String normal_image_back String? type_line String? - colors String[] + color_identity String[] set set @relation(fields: [set_id], references: [id]) set_id String @db.Uuid set_code String @@ -36,12 +36,15 @@ model carte { type String? price String? cardmarket_uri String? + can_be_commander Boolean + is_promo Boolean decks cartes_dans_deck[] decks_as_commander deck[] } model deck { id String @id @default(uuid()) @db.Uuid + color_identity String[] name String utilisateurice_id String @db.Uuid utilisateurice utilisateurice @relation(fields: [utilisateurice_id], references: [id]) diff --git a/app/tools/createBsets.mjs b/app/tools/createBsets.mjs index bf5f3be..8f225c7 100644 --- a/app/tools/createBsets.mjs +++ b/app/tools/createBsets.mjs @@ -4,8 +4,12 @@ const db = new PrismaClient() const Bsets = [ {"name": "Wild of Eldraine", sets: ["woe"]}, + {"name": "Bloomburrow", sets: ["blb"]}, + {"name": "Duskmourn", sets: ["dsk"]}, {"name": "Phyrexia", sets: ["one"]}, {"name": "The Brothers' War", sets: ["bro"]}, + {"name": "Murders at Karlov Manor", sets: ["mkm"]}, + {"name": "The lost caverns of Ixalan", sets: ["lci"]}, {"name": "Dominaria United", sets: ["dmu"]}, {"name": "New Capenna", sets: ["snc"]}, {"name": "Kamigawa", sets: ["neo"]}, @@ -19,6 +23,7 @@ const Bsets = [ {"name": "War of the Spark", sets: ["war"]}, {"name": "Dominaria", sets: ["dom"]}, {"name": "March of the machine", sets: ["mom","mat"]}, + {"name": "Outlaws", sets: ["otj","big"]}, {"name": "Innistrad Midnight Hunt", sets: ["vow","mid"]}, {"name": "Guilds of Ravnica", sets: ["rna","grn"]}, {"name": "Ixalan", sets: ["rix","xln"]}, diff --git a/app/tools/createDecks.mjs b/app/tools/createDecks.mjs new file mode 100644 index 0000000..4b8e74c --- /dev/null +++ b/app/tools/createDecks.mjs @@ -0,0 +1,49 @@ +import { readFileSync, readdirSync } from "fs" + +const base_api_url = "http://localhost:3000" + +const token = "eyJhbGciOiJIUzI1NiIsInR5cCI6Imp3dCJ9.eyJ1c2VybmFtZSI6Imdsb2J1em1hIiwiYWRtaW4iOnRydWUsImlkIjoiMDc4YWViYTYtNzZlNC00YzRkLTg3NjYtNjA0N2JhNjkxM2Y5IiwibWF4QWdlIjo2MDQ4MDB9.acd6b0fab88719f708fa0553f18a6b034b2c3a84659e3a63b32e87f22c611d3e" + +let bsets_sanitized_names = readdirSync(import.meta.dirname + "/data/bsets/") + +function get_line_data(line) { + let data = line.split(" ") + let amount = parseInt(data[0]) + let name = data.slice(1).join(" ").split("/")[0].replace(/[^a-zA-Z0-9]/gim,"-").toLowerCase() + return {"sanitized_name":name, "amount":amount} +} + +for(const sanitized_name of bsets_sanitized_names) { + let path = import.meta.dirname + "/data/bsets/" + sanitized_name + "/" + let deck_files = readdirSync(path) + for( const deck_file of deck_files) { + let api_object = { + "selected_bset": sanitized_name, + "name": deck_file.split(".txt")[0], + "commander_name": "", + "cards": [] + } + + let data = readFileSync(path + deck_file, 'utf8') + let lines = data.split(/\n/) + lines = lines.filter((line) => line.match(/[0-9]+\s[\w]+/) != undefined) + let commander_line = lines[lines.length - 1] + api_object["commander_name"] = get_line_data(commander_line).sanitized_name + for(const card of lines.slice(0, lines.length - 1)){ + api_object.cards.push(get_line_data(card)) + } + + + fetch(base_api_url + '/api/account/decks/create', { + method: "POST", + headers: {Authorization: 'Bearer ' + token}, + body: JSON.stringify(api_object) + }).then((res) => { + if(res.status == 200) { + console.log("Deck created") + } else { + console.log("Problem with : " + deck_file) + } + }) + } +} diff --git a/app/tools/createJson.mjs b/app/tools/createJson.mjs index f883bf0..095274c 100644 --- a/app/tools/createJson.mjs +++ b/app/tools/createJson.mjs @@ -4,11 +4,11 @@ import { writeFileSync } from 'fs' const db = new PrismaClient() const color_names = { - "mono-white": ["W"], - "mono-black": ["B"], - "mono-blue": ["U"], - "mono-green": ["G"], - "mono-red": ["R"], + "white": ["W"], + "black": ["B"], + "blue": ["U"], + "green": ["G"], + "red": ["R"], "colorless": [], "azorius": ["W","U"], "dimir": ["U","B"], @@ -49,6 +49,15 @@ function getColorName(colorArray) { } // I need to create +// +// Commanders +// top all +// top by colors +// +// bsets +// Commanders +// +// // Lands // lands.json // All jsons lands from colors @@ -63,21 +72,38 @@ async function createJson() { include: { cards: { include: { - decks: true + decks: true, + decks_as_commander: true, } } } }, - decks: true + decks: { + include: { + commander: { + include: { + decks_as_commander: true + } + } + } + } } }) - let bsets_export = [] + let bsets_list_export = [] let all_cards = [] + const commanderData = {"top": []} + for (const colorName of Object.keys(color_names)) { + commanderData[colorName] = [] + } + let bset_cards_data_export = {} + bsets.forEach((bset) => { let icons = [] let set_codes = [] + let bset_cards = [] + bset.sets.forEach((set) => { icons.push(set.icon_svg_uri) set_codes.push(set.code) @@ -85,76 +111,78 @@ async function createJson() { for(let i = 0; i < cards_temp.length; i++){ cards_temp[i].bset_id = bset.id } + bset_cards = [...bset_cards, ...cards_temp] all_cards = [...all_cards, ...cards_temp] }) - bsets_export.push({name: bset.name, sanitized_name: bset.sanitized_name, icons, set_codes}) - }) - - writeFileSync(import.meta.dirname + "/json/misc/bsets.json",JSON.stringify(bsets_export), 'utf8') - - const landsData = {} - for (const colorName of Object.keys(color_names)) { - landsData[colorName] = [] - } - const type_dict = {"creature": [],"land": [],"instant": [],"sorcery": [], "planeswalker": [], "artifact": [], "enchantment": []} - const colorsData = {"mono-white": structuredClone(type_dict),"mono-black": structuredClone(type_dict),"mono-blue": structuredClone(type_dict),"mono-green": structuredClone(type_dict),"mono-red": structuredClone(type_dict),"colorless": structuredClone(type_dict),"multicolor": structuredClone(type_dict)} - - for (const card of all_cards) { - let card_object = { - "name": card.name, - "sanitized_name": card.sanitized_name, - "normal_image": card.normal_image, - "small_image": card.small_image, - "type": card.type, - "layout": card.layout, - "price": card.price, - "cardmarket_uri": card.cardmarket_uri, - "nbr_decks": card.decks.length, - "total_decks": bsets.find((bset) => bset.id == card.bset_id).decks.length, - "colors": card.colors, + bsets_list_export.push({name: bset.name, sanitized_name: bset.sanitized_name, icons, set_codes}) + + // BSETS CARDS STATS + bset_cards_data_export[bset.sanitized_name] = { + "commander": [], + "creature": [], + "land": [], + "enchantment": [], + "sorcery": [], + "instant": [], + "planeswalker": [], + "artifact": [], } - card_object.percent_decks = (card_object.total_decks != 0) ? parseInt(10000 * (card_object.nbr_decks / card_object.total_decks)) / 100 : 0 + for (const card of bset_cards) { + let card_object = { + "name": card.name, + "sanitized_name": card.sanitized_name, + "normal_image": card.normal_image, + "small_image": card.small_image, + "type": card.type, + "layout": card.layout, + "price": card.price, + "cardmarket_uri": card.cardmarket_uri, + "nbr_decks": card.decks.length, + "total_decks": bset.decks.filter((deck) => card.color_identity.every(color => deck.color_identity.includes(color))).length, + "color_identity": card.color_identity, + } - const colorName = getColorName(card.colors) - if (card.type == "land") { - if (colorName != "") { - landsData[colorName].push(card_object) + card_object.percent_decks = (card_object.total_decks != 0) ? parseInt(10000 * (card_object.nbr_decks / card_object.total_decks)) / 100 : 0 + + bset_cards_data_export[bset.sanitized_name][card.type].push(card_object) + + if(card.can_be_commander) { + card_object.total_decks = bset.decks.length + card_object.nbr_decks = card.decks_as_commander != undefined ? card.decks_as_commander.length : 0 + card_object.percent_decks = (card_object.total_decks != 0) ? parseInt(10000 * (card_object.nbr_decks / card_object.total_decks)) / 100 : 0 + bset_cards_data_export[bset.sanitized_name]["commander"].push(card_object) + + const colorName = getColorName(card.color_identity) + + if(colorName != "") { + commanderData[colorName].push(card_object) + commanderData["top"].push(card_object) + } } } + }) - if (card.colors.length <= 1) { - colorsData[colorName][card.type].push(card_object) - } else { - colorsData["multicolor"][card.type].push(card_object) - } + writeFileSync(import.meta.dirname + "/json/misc/bsets.json",JSON.stringify(bsets_list_export), 'utf8') + + + //for (const card of all_cards) { + //} + + for (const index of Object.keys(commanderData)) { + let JSONToWrite = commanderData[index].sort((a,b) => b.percent_decks - a.percent_decks) + writeFileSync(import.meta.dirname + "/json/commander/" + index + ".json",JSON.stringify(JSONToWrite), 'utf8') } - - for (const index of Object.keys(colorsData)) { - let JSONToWrite = colorsData[index] - for (const key of Object.keys(JSONToWrite)){ - JSONToWrite[key].sort((a,b) => b.percent_decks - a.percent_decks) + for (const index of Object.keys(bset_cards_data_export)) { + let JSONToWrite = bset_cards_data_export[index] + for (const type of Object.keys(JSONToWrite)) { + JSONToWrite[type] = JSONToWrite[type].sort((a,b) => b.percent_decks - a.percent_decks) } - writeFileSync(import.meta.dirname + "/json/top/" + index + ".json",JSON.stringify(JSONToWrite), 'utf8') + writeFileSync(import.meta.dirname + "/json/bset/" + index + ".json",JSON.stringify(JSONToWrite), 'utf8') } - - const landsJsonRoot = [[],[],[],[]] - for (const colorName of Object.keys(color_names)){ - if(color_names[colorName].length <= 3){ - let index = color_names[colorName].length - 1 - if(index < 0) { index = 0 } - landsJsonRoot[index].push({ "name": colorName, "count": landsData[colorName].length}) - } else { - landsJsonRoot[3].push({ "name": colorName, "count": landsData[colorName].length}) - } - let JSONToWrite = landsData[colorName] - JSONToWrite.sort((a,b) => b.percent_decks - a.percent_decks) - writeFileSync(import.meta.dirname + "/json/lands/" + colorName + ".json",JSON.stringify(JSONToWrite), 'utf8') - } - writeFileSync(import.meta.dirname + "/json/lands/lands.json",JSON.stringify(landsJsonRoot), 'utf8') } createJson() diff --git a/app/tools/updateDatabase.mjs b/app/tools/updateDatabase.mjs index cc91ea5..d304ff4 100644 --- a/app/tools/updateDatabase.mjs +++ b/app/tools/updateDatabase.mjs @@ -54,11 +54,16 @@ try { // For each card check if we need to upload it to the database for (const carte of scryfallData) { - if(!preUpdateCardsIds.includes(carte.id) && carte.layout != "art_series"){ + if(!preUpdateCardsIds.includes(carte.id) && carte.legalities.commander != "not_legal"){ let type = "" const layout = carte.layout const card_type = (carte.type_line == undefined) ? carte.card_faces[0].type_line.toLowerCase() : carte.type_line.toLowerCase() + let promo = (carte.promo_types == undefined) ? false : true + let can_be_commander = (card_type.includes("legendary") && (card_type.includes("creature") || card_type.includes("planeswalker"))) ? true : false + + + if(card_type.includes("creature")){ type = "creature" } else if (card_type.includes("planeswalker")) { @@ -77,10 +82,10 @@ try { try { if(two_faced_layouts.includes(layout)) { - const addingCardsQuery = await client.query('INSERT INTO carte(id, name, released_at, small_image, small_image_back, normal_image, normal_image_back, type_line, colors, set_id, rarity, cardmarket_uri, price, type, sanitized_name, set_code, layout) VALUES($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13, $14, $15, $16, $17)', [carte.id, carte.name, carte.released_at, carte.card_faces[0].image_uris.small, carte.card_faces[1].image_uris.small, carte.card_faces[0].image_uris.normal, carte.card_faces[0].image_uris.normal, carte.type_line, carte.color_identity, carte.set_id, carte.rarity, carte.purchase_uris?.cardmarket, carte.prices.eur, type, carte.name.replace(/[^a-zA-Z0-9]/gim,"-").toLowerCase(), carte.set, layout]) + const addingCardsQuery = await client.query('INSERT INTO carte(id, name, released_at, small_image, small_image_back, normal_image, normal_image_back, type_line, color_identity, set_id, rarity, cardmarket_uri, price, type, sanitized_name, set_code, layout, is_promo, can_be_commander) VALUES($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13, $14, $15, $16, $17, $18, $19)', [carte.id, carte.name, carte.released_at, carte.card_faces[0].image_uris.small, carte.card_faces[1].image_uris.small, carte.card_faces[0].image_uris.normal, carte.card_faces[0].image_uris.normal, carte.type_line, carte.color_identity, carte.set_id, carte.rarity, carte.purchase_uris?.cardmarket, carte.prices.eur, type, carte.name.replace(/[^a-zA-Z0-9]/gim,"-").toLowerCase(), carte.set, layout, promo, can_be_commander]) } else { - const addingCardsQuery = await client.query('INSERT INTO carte(id, name, released_at, small_image, normal_image, type_line, colors, set_id, rarity, cardmarket_uri, price, type, sanitized_name, set_code, layout) VALUES($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13, $14, $15)', [carte.id, carte.name, carte.released_at, carte.image_uris.small, carte.image_uris.normal, carte.type_line, carte.color_identity, carte.set_id, carte.rarity, carte.purchase_uris?.cardmarket, carte.prices.eur, type, carte.name.replace(/[^a-zA-Z0-9]/gim,"-").toLowerCase(), carte.set, layout]) + const addingCardsQuery = await client.query('INSERT INTO carte(id, name, released_at, small_image, normal_image, type_line, color_identity, set_id, rarity, cardmarket_uri, price, type, sanitized_name, set_code, layout, is_promo, can_be_commander) VALUES($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13, $14, $15, $16, $17)', [carte.id, carte.name, carte.released_at, carte.image_uris.small, carte.image_uris.normal, carte.type_line, carte.color_identity, carte.set_id, carte.rarity, carte.purchase_uris?.cardmarket, carte.prices.eur, type, carte.name.replace(/[^a-zA-Z0-9]/gim,"-").toLowerCase(), carte.set, layout, promo, can_be_commander]) } total_inserted = total_inserted + 1 @@ -94,6 +99,7 @@ try { // Add the card to the database } else { total_skipped = total_skipped + 1 + } }