Feat: Add card list and top structure
This commit is contained in:
parent
8e33dd45fe
commit
eec6c6bfe8
19 changed files with 994 additions and 24 deletions
3
.gitignore
vendored
3
.gitignore
vendored
|
@ -19,4 +19,5 @@ app/*.tsbuildinfo
|
|||
app/next-env.d.ts
|
||||
|
||||
# data
|
||||
app/tools/data/
|
||||
app/tools/data/*
|
||||
app/tools/json/*
|
||||
|
|
|
@ -95,7 +95,8 @@ export default function Home() {
|
|||
}).then((res) => {
|
||||
if(res.status == 200) {
|
||||
res.json().then((apiData) => {
|
||||
setBsetList(old => [...old, { id: apiData.data, name: bset_name, sets: selectedSets }])
|
||||
const addedBset : bsetExtended = { sanitized_name: bset_name.replace(/[^a-zA-Z0-9]/gim,"-").toLowerCase() ,id: apiData.data, name: bset_name, sets: selectedSets }
|
||||
setBsetList(old => [...old, addedBset])
|
||||
setSelectedSets([])
|
||||
})
|
||||
}
|
||||
|
|
|
@ -19,7 +19,8 @@ export async function POST(req: NextRequest) {
|
|||
if(bset_name != undefined && selected_sets != undefined) {
|
||||
const bset = await db.bset.create({
|
||||
data: {
|
||||
name: bset_name
|
||||
name: bset_name,
|
||||
sanitized_name: bset_name.replace(/[^a-zA-Z0-9]/gim,"-").toLowerCase()
|
||||
}
|
||||
})
|
||||
|
||||
|
|
81
app/app/top/black/page.tsx
Normal file
81
app/app/top/black/page.tsx
Normal file
|
@ -0,0 +1,81 @@
|
|||
'use client'
|
||||
|
||||
import { useEffect, useState } from 'react'
|
||||
import { MTGCard } from '@/components/ui/mtg-card'
|
||||
|
||||
import type { carte } from "@prisma/client";
|
||||
|
||||
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 (
|
||||
<div className="flex flex-col items-center mt-32">
|
||||
<h1>Creature</h1>
|
||||
<div className="flex flex-row flex-wrap gap-4 p-8">
|
||||
{creatureCardList.map((card: carte) => (
|
||||
<MTGCard key={card.id} cardname={card.name_fr} imageURI={card.normal_image} url={"/card/" + card.sanitized_name}/>
|
||||
))}
|
||||
</div>
|
||||
<h1>Instants</h1>
|
||||
<div className="flex flex-row flex-wrap gap-4 p-8">
|
||||
{instantCardList.map((card: carte) => (
|
||||
<MTGCard key={card.id} cardname={card.name_fr} imageURI={card.normal_image} url={"/card/" + card.sanitized_name}/>
|
||||
))}
|
||||
</div>
|
||||
<h1>Sorceries</h1>
|
||||
<div className="flex flex-row flex-wrap gap-4 p-8">
|
||||
{sorceryCardList.map((card: carte) => (
|
||||
<MTGCard key={card.id} cardname={card.name_fr} imageURI={card.normal_image} url={"/card/" + card.sanitized_name}/>
|
||||
))}
|
||||
</div>
|
||||
<h1>Enchantment</h1>
|
||||
<div className="flex flex-row flex-wrap gap-4 p-8">
|
||||
{enchantmentCardList.map((card: carte) => (
|
||||
<MTGCard key={card.id} cardname={card.name_fr} imageURI={card.normal_image} url={"/card/" + card.sanitized_name}/>
|
||||
))}
|
||||
</div>
|
||||
<h1>Planeswalker</h1>
|
||||
<div className="flex flex-row flex-wrap gap-4 p-8">
|
||||
{planeswalkerCardList.map((card: carte) => (
|
||||
<MTGCard key={card.id} cardname={card.name_fr} imageURI={card.normal_image} url={"/card/" + card.sanitized_name}/>
|
||||
))}
|
||||
</div>
|
||||
<h1>Artifact</h1>
|
||||
<div className="flex flex-row flex-wrap gap-4 p-8">
|
||||
{artifactCardList.map((card: carte) => (
|
||||
<MTGCard key={card.id} cardname={card.name_fr} imageURI={card.normal_image} url={"/card/" + card.sanitized_name}/>
|
||||
))}
|
||||
</div>
|
||||
<h1>Lands</h1>
|
||||
<div className="flex flex-row flex-wrap gap-4 p-8">
|
||||
{landCardList.map((card: carte) => (
|
||||
<MTGCard key={card.id} cardname={card.name_fr} imageURI={card.normal_image} url={"/card/" + card.sanitized_name}/>
|
||||
))}
|
||||
</div>
|
||||
|
||||
</div>
|
||||
);
|
||||
}
|
81
app/app/top/blue/page.tsx
Normal file
81
app/app/top/blue/page.tsx
Normal file
|
@ -0,0 +1,81 @@
|
|||
'use client'
|
||||
|
||||
import { useEffect, useState } from 'react'
|
||||
import { MTGCard } from '@/components/ui/mtg-card'
|
||||
|
||||
import type { carte } from "@prisma/client";
|
||||
|
||||
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 (
|
||||
<div className="flex flex-col items-center mt-32">
|
||||
<h1>Creature</h1>
|
||||
<div className="flex flex-row flex-wrap gap-4 p-8">
|
||||
{creatureCardList.map((card: carte) => (
|
||||
<MTGCard key={card.id} cardname={card.name_fr} imageURI={card.normal_image} url={"/card/" + card.sanitized_name}/>
|
||||
))}
|
||||
</div>
|
||||
<h1>Instants</h1>
|
||||
<div className="flex flex-row flex-wrap gap-4 p-8">
|
||||
{instantCardList.map((card: carte) => (
|
||||
<MTGCard key={card.id} cardname={card.name_fr} imageURI={card.normal_image} url={"/card/" + card.sanitized_name}/>
|
||||
))}
|
||||
</div>
|
||||
<h1>Sorceries</h1>
|
||||
<div className="flex flex-row flex-wrap gap-4 p-8">
|
||||
{sorceryCardList.map((card: carte) => (
|
||||
<MTGCard key={card.id} cardname={card.name_fr} imageURI={card.normal_image} url={"/card/" + card.sanitized_name}/>
|
||||
))}
|
||||
</div>
|
||||
<h1>Enchantment</h1>
|
||||
<div className="flex flex-row flex-wrap gap-4 p-8">
|
||||
{enchantmentCardList.map((card: carte) => (
|
||||
<MTGCard key={card.id} cardname={card.name_fr} imageURI={card.normal_image} url={"/card/" + card.sanitized_name}/>
|
||||
))}
|
||||
</div>
|
||||
<h1>Planeswalker</h1>
|
||||
<div className="flex flex-row flex-wrap gap-4 p-8">
|
||||
{planeswalkerCardList.map((card: carte) => (
|
||||
<MTGCard key={card.id} cardname={card.name_fr} imageURI={card.normal_image} url={"/card/" + card.sanitized_name}/>
|
||||
))}
|
||||
</div>
|
||||
<h1>Artifact</h1>
|
||||
<div className="flex flex-row flex-wrap gap-4 p-8">
|
||||
{artifactCardList.map((card: carte) => (
|
||||
<MTGCard key={card.id} cardname={card.name_fr} imageURI={card.normal_image} url={"/card/" + card.sanitized_name}/>
|
||||
))}
|
||||
</div>
|
||||
<h1>Lands</h1>
|
||||
<div className="flex flex-row flex-wrap gap-4 p-8">
|
||||
{landCardList.map((card: carte) => (
|
||||
<MTGCard key={card.id} cardname={card.name_fr} imageURI={card.normal_image} url={"/card/" + card.sanitized_name}/>
|
||||
))}
|
||||
</div>
|
||||
|
||||
</div>
|
||||
);
|
||||
}
|
81
app/app/top/colorless/page.tsx
Normal file
81
app/app/top/colorless/page.tsx
Normal file
|
@ -0,0 +1,81 @@
|
|||
'use client'
|
||||
|
||||
import { useEffect, useState } from 'react'
|
||||
import { MTGCard } from '@/components/ui/mtg-card'
|
||||
|
||||
import type { carte } from "@prisma/client";
|
||||
|
||||
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/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 (
|
||||
<div className="flex flex-col items-center mt-32">
|
||||
<h1>Creature</h1>
|
||||
<div className="flex flex-row flex-wrap gap-4 p-8">
|
||||
{creatureCardList.map((card: carte) => (
|
||||
<MTGCard key={card.id} cardname={card.name_fr} imageURI={card.normal_image} url={"/card/" + card.sanitized_name}/>
|
||||
))}
|
||||
</div>
|
||||
<h1>Instants</h1>
|
||||
<div className="flex flex-row flex-wrap gap-4 p-8">
|
||||
{instantCardList.map((card: carte) => (
|
||||
<MTGCard key={card.id} cardname={card.name_fr} imageURI={card.normal_image} url={"/card/" + card.sanitized_name}/>
|
||||
))}
|
||||
</div>
|
||||
<h1>Sorceries</h1>
|
||||
<div className="flex flex-row flex-wrap gap-4 p-8">
|
||||
{sorceryCardList.map((card: carte) => (
|
||||
<MTGCard key={card.id} cardname={card.name_fr} imageURI={card.normal_image} url={"/card/" + card.sanitized_name}/>
|
||||
))}
|
||||
</div>
|
||||
<h1>Enchantment</h1>
|
||||
<div className="flex flex-row flex-wrap gap-4 p-8">
|
||||
{enchantmentCardList.map((card: carte) => (
|
||||
<MTGCard key={card.id} cardname={card.name_fr} imageURI={card.normal_image} url={"/card/" + card.sanitized_name}/>
|
||||
))}
|
||||
</div>
|
||||
<h1>Planeswalker</h1>
|
||||
<div className="flex flex-row flex-wrap gap-4 p-8">
|
||||
{planeswalkerCardList.map((card: carte) => (
|
||||
<MTGCard key={card.id} cardname={card.name_fr} imageURI={card.normal_image} url={"/card/" + card.sanitized_name}/>
|
||||
))}
|
||||
</div>
|
||||
<h1>Artifact</h1>
|
||||
<div className="flex flex-row flex-wrap gap-4 p-8">
|
||||
{artifactCardList.map((card: carte) => (
|
||||
<MTGCard key={card.id} cardname={card.name_fr} imageURI={card.normal_image} url={"/card/" + card.sanitized_name}/>
|
||||
))}
|
||||
</div>
|
||||
<h1>Lands</h1>
|
||||
<div className="flex flex-row flex-wrap gap-4 p-8">
|
||||
{landCardList.map((card: carte) => (
|
||||
<MTGCard key={card.id} cardname={card.name_fr} imageURI={card.normal_image} url={"/card/" + card.sanitized_name}/>
|
||||
))}
|
||||
</div>
|
||||
|
||||
</div>
|
||||
);
|
||||
}
|
81
app/app/top/green/page.tsx
Normal file
81
app/app/top/green/page.tsx
Normal file
|
@ -0,0 +1,81 @@
|
|||
'use client'
|
||||
|
||||
import { useEffect, useState } from 'react'
|
||||
import { MTGCard } from '@/components/ui/mtg-card'
|
||||
|
||||
import type { carte } from "@prisma/client";
|
||||
|
||||
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 (
|
||||
<div className="flex flex-col items-center mt-32">
|
||||
<h1>Creature</h1>
|
||||
<div className="flex flex-row flex-wrap gap-4 p-8">
|
||||
{creatureCardList.map((card: carte) => (
|
||||
<MTGCard key={card.id} cardname={card.name_fr} imageURI={card.normal_image} url={"/card/" + card.sanitized_name}/>
|
||||
))}
|
||||
</div>
|
||||
<h1>Instants</h1>
|
||||
<div className="flex flex-row flex-wrap gap-4 p-8">
|
||||
{instantCardList.map((card: carte) => (
|
||||
<MTGCard key={card.id} cardname={card.name_fr} imageURI={card.normal_image} url={"/card/" + card.sanitized_name}/>
|
||||
))}
|
||||
</div>
|
||||
<h1>Sorceries</h1>
|
||||
<div className="flex flex-row flex-wrap gap-4 p-8">
|
||||
{sorceryCardList.map((card: carte) => (
|
||||
<MTGCard key={card.id} cardname={card.name_fr} imageURI={card.normal_image} url={"/card/" + card.sanitized_name}/>
|
||||
))}
|
||||
</div>
|
||||
<h1>Enchantment</h1>
|
||||
<div className="flex flex-row flex-wrap gap-4 p-8">
|
||||
{enchantmentCardList.map((card: carte) => (
|
||||
<MTGCard key={card.id} cardname={card.name_fr} imageURI={card.normal_image} url={"/card/" + card.sanitized_name}/>
|
||||
))}
|
||||
</div>
|
||||
<h1>Planeswalker</h1>
|
||||
<div className="flex flex-row flex-wrap gap-4 p-8">
|
||||
{planeswalkerCardList.map((card: carte) => (
|
||||
<MTGCard key={card.id} cardname={card.name_fr} imageURI={card.normal_image} url={"/card/" + card.sanitized_name}/>
|
||||
))}
|
||||
</div>
|
||||
<h1>Artifact</h1>
|
||||
<div className="flex flex-row flex-wrap gap-4 p-8">
|
||||
{artifactCardList.map((card: carte) => (
|
||||
<MTGCard key={card.id} cardname={card.name_fr} imageURI={card.normal_image} url={"/card/" + card.sanitized_name}/>
|
||||
))}
|
||||
</div>
|
||||
<h1>Lands</h1>
|
||||
<div className="flex flex-row flex-wrap gap-4 p-8">
|
||||
{landCardList.map((card: carte) => (
|
||||
<MTGCard key={card.id} cardname={card.name_fr} imageURI={card.normal_image} url={"/card/" + card.sanitized_name}/>
|
||||
))}
|
||||
</div>
|
||||
|
||||
</div>
|
||||
);
|
||||
}
|
81
app/app/top/multicolor/page.tsx
Normal file
81
app/app/top/multicolor/page.tsx
Normal file
|
@ -0,0 +1,81 @@
|
|||
'use client'
|
||||
|
||||
import { useEffect, useState } from 'react'
|
||||
import { MTGCard } from '@/components/ui/mtg-card'
|
||||
|
||||
import type { carte } from "@prisma/client";
|
||||
|
||||
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/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 (
|
||||
<div className="flex flex-col items-center mt-32">
|
||||
<h1>Creature</h1>
|
||||
<div className="flex flex-row flex-wrap gap-4 p-8">
|
||||
{creatureCardList.map((card: carte) => (
|
||||
<MTGCard key={card.id} cardname={card.name_fr} imageURI={card.normal_image} url={"/card/" + card.sanitized_name}/>
|
||||
))}
|
||||
</div>
|
||||
<h1>Instants</h1>
|
||||
<div className="flex flex-row flex-wrap gap-4 p-8">
|
||||
{instantCardList.map((card: carte) => (
|
||||
<MTGCard key={card.id} cardname={card.name_fr} imageURI={card.normal_image} url={"/card/" + card.sanitized_name}/>
|
||||
))}
|
||||
</div>
|
||||
<h1>Sorceries</h1>
|
||||
<div className="flex flex-row flex-wrap gap-4 p-8">
|
||||
{sorceryCardList.map((card: carte) => (
|
||||
<MTGCard key={card.id} cardname={card.name_fr} imageURI={card.normal_image} url={"/card/" + card.sanitized_name}/>
|
||||
))}
|
||||
</div>
|
||||
<h1>Enchantment</h1>
|
||||
<div className="flex flex-row flex-wrap gap-4 p-8">
|
||||
{enchantmentCardList.map((card: carte) => (
|
||||
<MTGCard key={card.id} cardname={card.name_fr} imageURI={card.normal_image} url={"/card/" + card.sanitized_name}/>
|
||||
))}
|
||||
</div>
|
||||
<h1>Planeswalker</h1>
|
||||
<div className="flex flex-row flex-wrap gap-4 p-8">
|
||||
{planeswalkerCardList.map((card: carte) => (
|
||||
<MTGCard key={card.id} cardname={card.name_fr} imageURI={card.normal_image} url={"/card/" + card.sanitized_name}/>
|
||||
))}
|
||||
</div>
|
||||
<h1>Artifact</h1>
|
||||
<div className="flex flex-row flex-wrap gap-4 p-8">
|
||||
{artifactCardList.map((card: carte) => (
|
||||
<MTGCard key={card.id} cardname={card.name_fr} imageURI={card.normal_image} url={"/card/" + card.sanitized_name}/>
|
||||
))}
|
||||
</div>
|
||||
<h1>Lands</h1>
|
||||
<div className="flex flex-row flex-wrap gap-4 p-8">
|
||||
{landCardList.map((card: carte) => (
|
||||
<MTGCard key={card.id} cardname={card.name_fr} imageURI={card.normal_image} url={"/card/" + card.sanitized_name}/>
|
||||
))}
|
||||
</div>
|
||||
|
||||
</div>
|
||||
);
|
||||
}
|
81
app/app/top/red/page.tsx
Normal file
81
app/app/top/red/page.tsx
Normal file
|
@ -0,0 +1,81 @@
|
|||
'use client'
|
||||
|
||||
import { useEffect, useState } from 'react'
|
||||
import { MTGCard } from '@/components/ui/mtg-card'
|
||||
|
||||
import type { carte } from "@prisma/client";
|
||||
|
||||
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 (
|
||||
<div className="flex flex-col items-center mt-32">
|
||||
<h1>Creature</h1>
|
||||
<div className="flex flex-row flex-wrap gap-4 p-8">
|
||||
{creatureCardList.map((card: carte) => (
|
||||
<MTGCard key={card.id} cardname={card.name_fr} imageURI={card.normal_image} url={"/card/" + card.sanitized_name}/>
|
||||
))}
|
||||
</div>
|
||||
<h1>Instants</h1>
|
||||
<div className="flex flex-row flex-wrap gap-4 p-8">
|
||||
{instantCardList.map((card: carte) => (
|
||||
<MTGCard key={card.id} cardname={card.name_fr} imageURI={card.normal_image} url={"/card/" + card.sanitized_name}/>
|
||||
))}
|
||||
</div>
|
||||
<h1>Sorceries</h1>
|
||||
<div className="flex flex-row flex-wrap gap-4 p-8">
|
||||
{sorceryCardList.map((card: carte) => (
|
||||
<MTGCard key={card.id} cardname={card.name_fr} imageURI={card.normal_image} url={"/card/" + card.sanitized_name}/>
|
||||
))}
|
||||
</div>
|
||||
<h1>Enchantment</h1>
|
||||
<div className="flex flex-row flex-wrap gap-4 p-8">
|
||||
{enchantmentCardList.map((card: carte) => (
|
||||
<MTGCard key={card.id} cardname={card.name_fr} imageURI={card.normal_image} url={"/card/" + card.sanitized_name}/>
|
||||
))}
|
||||
</div>
|
||||
<h1>Planeswalker</h1>
|
||||
<div className="flex flex-row flex-wrap gap-4 p-8">
|
||||
{planeswalkerCardList.map((card: carte) => (
|
||||
<MTGCard key={card.id} cardname={card.name_fr} imageURI={card.normal_image} url={"/card/" + card.sanitized_name}/>
|
||||
))}
|
||||
</div>
|
||||
<h1>Artifact</h1>
|
||||
<div className="flex flex-row flex-wrap gap-4 p-8">
|
||||
{artifactCardList.map((card: carte) => (
|
||||
<MTGCard key={card.id} cardname={card.name_fr} imageURI={card.normal_image} url={"/card/" + card.sanitized_name}/>
|
||||
))}
|
||||
</div>
|
||||
<h1>Lands</h1>
|
||||
<div className="flex flex-row flex-wrap gap-4 p-8">
|
||||
{landCardList.map((card: carte) => (
|
||||
<MTGCard key={card.id} cardname={card.name_fr} imageURI={card.normal_image} url={"/card/" + card.sanitized_name}/>
|
||||
))}
|
||||
</div>
|
||||
|
||||
</div>
|
||||
);
|
||||
}
|
81
app/app/top/white/page.tsx
Normal file
81
app/app/top/white/page.tsx
Normal file
|
@ -0,0 +1,81 @@
|
|||
'use client'
|
||||
|
||||
import { useEffect, useState } from 'react'
|
||||
import { MTGCard } from '@/components/ui/mtg-card'
|
||||
|
||||
import type { carte } from "@prisma/client";
|
||||
|
||||
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 (
|
||||
<div className="flex flex-col items-center mt-32">
|
||||
<h1>Creature</h1>
|
||||
<div className="flex flex-row flex-wrap gap-4 p-8">
|
||||
{creatureCardList.map((card: carte) => (
|
||||
<MTGCard key={card.id} cardname={card.name_fr} imageURI={card.normal_image} url={"/card/" + card.sanitized_name}/>
|
||||
))}
|
||||
</div>
|
||||
<h1>Instants</h1>
|
||||
<div className="flex flex-row flex-wrap gap-4 p-8">
|
||||
{instantCardList.map((card: carte) => (
|
||||
<MTGCard key={card.id} cardname={card.name_fr} imageURI={card.normal_image} url={"/card/" + card.sanitized_name}/>
|
||||
))}
|
||||
</div>
|
||||
<h1>Sorceries</h1>
|
||||
<div className="flex flex-row flex-wrap gap-4 p-8">
|
||||
{sorceryCardList.map((card: carte) => (
|
||||
<MTGCard key={card.id} cardname={card.name_fr} imageURI={card.normal_image} url={"/card/" + card.sanitized_name}/>
|
||||
))}
|
||||
</div>
|
||||
<h1>Enchantment</h1>
|
||||
<div className="flex flex-row flex-wrap gap-4 p-8">
|
||||
{enchantmentCardList.map((card: carte) => (
|
||||
<MTGCard key={card.id} cardname={card.name_fr} imageURI={card.normal_image} url={"/card/" + card.sanitized_name}/>
|
||||
))}
|
||||
</div>
|
||||
<h1>Planeswalker</h1>
|
||||
<div className="flex flex-row flex-wrap gap-4 p-8">
|
||||
{planeswalkerCardList.map((card: carte) => (
|
||||
<MTGCard key={card.id} cardname={card.name_fr} imageURI={card.normal_image} url={"/card/" + card.sanitized_name}/>
|
||||
))}
|
||||
</div>
|
||||
<h1>Artifact</h1>
|
||||
<div className="flex flex-row flex-wrap gap-4 p-8">
|
||||
{artifactCardList.map((card: carte) => (
|
||||
<MTGCard key={card.id} cardname={card.name_fr} imageURI={card.normal_image} url={"/card/" + card.sanitized_name}/>
|
||||
))}
|
||||
</div>
|
||||
<h1>Lands</h1>
|
||||
<div className="flex flex-row flex-wrap gap-4 p-8">
|
||||
{landCardList.map((card: carte) => (
|
||||
<MTGCard key={card.id} cardname={card.name_fr} imageURI={card.normal_image} url={"/card/" + card.sanitized_name}/>
|
||||
))}
|
||||
</div>
|
||||
|
||||
</div>
|
||||
);
|
||||
}
|
32
app/components/ui/mtg-card.tsx
Normal file
32
app/components/ui/mtg-card.tsx
Normal file
|
@ -0,0 +1,32 @@
|
|||
import * as React from "react"
|
||||
|
||||
import { cn } from "@/lib/utils"
|
||||
|
||||
interface MTGCardProps {
|
||||
className?: string,
|
||||
imageURI: string,
|
||||
cardname: string,
|
||||
url: string
|
||||
}
|
||||
|
||||
const MTGCard = ({ className, imageURI, cardname, url }: MTGCardProps) => {
|
||||
const [loaded, setLoaded] = React.useState(false)
|
||||
|
||||
return (
|
||||
<a
|
||||
href={url}
|
||||
className={cn(
|
||||
"flex flex-col w-48",
|
||||
className
|
||||
)}
|
||||
>
|
||||
{!loaded &&
|
||||
<span className="h-64 shadow">Loading...</span>
|
||||
}
|
||||
<img src={imageURI} className="rounded" height={loaded ? 'auto' : '0'} onLoad={() => {setLoaded(true)}} loading="lazy" />
|
||||
<span className="text-center">{cardname}</span>
|
||||
</a>
|
||||
)}
|
||||
MTGCard.displayName = "MTGCard"
|
||||
|
||||
export { MTGCard }
|
|
@ -54,31 +54,45 @@ export function NavigationBar ({ isLoggedIn, username}: NavigationProps) {
|
|||
<DropdownMenuPortal>
|
||||
<DropdownMenuSubContent>
|
||||
<DropdownMenuItem>
|
||||
<White className="h-4 w-4"/>
|
||||
<span>Blanc</span>
|
||||
<a className="flex flex-row gap-2" href="/top/white">
|
||||
<White className="h-4 w-4"/>
|
||||
<span>Blanc</span>
|
||||
</a>
|
||||
</DropdownMenuItem>
|
||||
<DropdownMenuItem>
|
||||
<Blue className="h-4 w-4"/>
|
||||
<span>Bleu</span>
|
||||
<a className="flex flex-row gap-2" href="/top/blue">
|
||||
<Blue className="h-4 w-4"/>
|
||||
<span>Bleu</span>
|
||||
</a>
|
||||
</DropdownMenuItem>
|
||||
<DropdownMenuItem>
|
||||
<Black className="h-4 w-4"/>
|
||||
<span>Noir</span>
|
||||
<a className="flex flex-row gap-2" href="/top/blue">
|
||||
<Black className="h-4 w-4"/>
|
||||
<span>Noir</span>
|
||||
</a>
|
||||
</DropdownMenuItem>
|
||||
<DropdownMenuItem>
|
||||
<Red className="h-4 w-4"/>
|
||||
<span>Rouge</span>
|
||||
<a className="flex flex-row gap-2" href="/top/red">
|
||||
<Red className="h-4 w-4"/>
|
||||
<span>Rouge</span>
|
||||
</a>
|
||||
</DropdownMenuItem>
|
||||
<DropdownMenuItem>
|
||||
<Green className="h-4 w-4"/>
|
||||
<span>Vert</span>
|
||||
<a className="flex flex-row gap-2" href="/top/green">
|
||||
<Green className="h-4 w-4"/>
|
||||
<span>Vert</span>
|
||||
</a>
|
||||
</DropdownMenuItem>
|
||||
<DropdownMenuItem>
|
||||
<Colorless className="h-4 w-4"/>
|
||||
<span>Incolor</span>
|
||||
<a className="flex flex-row gap-2" href="/top/colorless">
|
||||
<Colorless className="h-4 w-4"/>
|
||||
<span>Incolor</span>
|
||||
</a>
|
||||
</DropdownMenuItem>
|
||||
<DropdownMenuItem>
|
||||
<span>Multicolor</span>
|
||||
<a className="flex flex-row gap-2" href="/top/multicolor">
|
||||
<span>Multicolor</span>
|
||||
</a>
|
||||
</DropdownMenuItem>
|
||||
</DropdownMenuSubContent>
|
||||
</DropdownMenuPortal>
|
||||
|
|
10
app/docker-compose.yml
Normal file
10
app/docker-compose.yml
Normal file
|
@ -0,0 +1,10 @@
|
|||
services:
|
||||
nginx:
|
||||
container_name: json_files
|
||||
image: nginx
|
||||
ports:
|
||||
- 8072:80
|
||||
volumes:
|
||||
- ./tools/json:/usr/share/nginx/html:ro
|
||||
- ./nginx.conf:/etc/nginx/conf.d/default.conf:ro
|
||||
restart: unless-stopped
|
56
app/nginx.conf
Normal file
56
app/nginx.conf
Normal file
|
@ -0,0 +1,56 @@
|
|||
server {
|
||||
listen 80;
|
||||
listen [::]:80;
|
||||
server_name localhost;
|
||||
|
||||
#access_log /var/log/nginx/host.access.log main;
|
||||
|
||||
location / {
|
||||
root /usr/share/nginx/html;
|
||||
index index.html index.htm;
|
||||
|
||||
if ($request_method = 'OPTIONS') {
|
||||
add_header 'Access-Control-Allow-Origin' '*';
|
||||
add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS';
|
||||
#
|
||||
# Custom headers and headers various browsers *should* be OK with but aren't
|
||||
#
|
||||
add_header 'Access-Control-Allow-Headers' 'DNT,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Range';
|
||||
#
|
||||
# Tell client that this pre-flight info is valid for 20 days
|
||||
#
|
||||
add_header 'Access-Control-Max-Age' 1728000;
|
||||
add_header 'Content-Type' 'text/plain; charset=utf-8';
|
||||
add_header 'Content-Length' 0;
|
||||
return 204;
|
||||
}
|
||||
if ($request_method = 'POST') {
|
||||
add_header 'Access-Control-Allow-Origin' '*' always;
|
||||
add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS' always;
|
||||
add_header 'Access-Control-Allow-Headers' 'DNT,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Range' always;
|
||||
add_header 'Access-Control-Expose-Headers' 'Content-Length,Content-Range' always;
|
||||
}
|
||||
if ($request_method = 'GET') {
|
||||
add_header 'Access-Control-Allow-Origin' '*' always;
|
||||
add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS' always;
|
||||
add_header 'Access-Control-Allow-Headers' 'DNT,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Range' always;
|
||||
add_header 'Access-Control-Expose-Headers' 'Content-Length,Content-Range' always;
|
||||
}
|
||||
}
|
||||
|
||||
error_page 404 /404.html;
|
||||
|
||||
# redirect server error pages to the static page /50x.html
|
||||
#
|
||||
error_page 500 502 503 504 /50x.html;
|
||||
location = /50x.html {
|
||||
root /usr/share/nginx/html;
|
||||
}
|
||||
|
||||
# deny access to .htaccess files, if Apache's document root
|
||||
# concurs with nginx's one
|
||||
#
|
||||
#location ~ /\.ht {
|
||||
# deny all;
|
||||
#}
|
||||
}
|
150
app/package-lock.json
generated
150
app/package-lock.json
generated
|
@ -28,7 +28,8 @@
|
|||
"react": "^18",
|
||||
"react-dom": "^18",
|
||||
"tailwind-merge": "^2.5.4",
|
||||
"tailwindcss-animate": "^1.0.7"
|
||||
"tailwindcss-animate": "^1.0.7",
|
||||
"ts-node": "^10.9.2"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/node": "^20.17.6",
|
||||
|
@ -67,6 +68,28 @@
|
|||
"node": ">=6.9.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@cspotcode/source-map-support": {
|
||||
"version": "0.8.1",
|
||||
"resolved": "https://registry.npmjs.org/@cspotcode/source-map-support/-/source-map-support-0.8.1.tgz",
|
||||
"integrity": "sha512-IchNf6dN4tHoMFIn/7OE8LWZ19Y6q/67Bmf6vnGREv8RSbBVb9LPJxEcnwrcwX6ixSvaiGoomAUvu4YSxXrVgw==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@jridgewell/trace-mapping": "0.3.9"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=12"
|
||||
}
|
||||
},
|
||||
"node_modules/@cspotcode/source-map-support/node_modules/@jridgewell/trace-mapping": {
|
||||
"version": "0.3.9",
|
||||
"resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.9.tgz",
|
||||
"integrity": "sha512-3Belt6tdc8bPgAtbcmdtNJlirVoTmEb5e2gC94PnkwEW9jI6CAHUeoG85tjWP5WquqfavoMtMwiG4P926ZKKuQ==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@jridgewell/resolve-uri": "^3.0.3",
|
||||
"@jridgewell/sourcemap-codec": "^1.4.10"
|
||||
}
|
||||
},
|
||||
"node_modules/@esbuild/aix-ppc64": {
|
||||
"version": "0.23.1",
|
||||
"resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.23.1.tgz",
|
||||
|
@ -1776,6 +1799,30 @@
|
|||
"react": ">= 16"
|
||||
}
|
||||
},
|
||||
"node_modules/@tsconfig/node10": {
|
||||
"version": "1.0.11",
|
||||
"resolved": "https://registry.npmjs.org/@tsconfig/node10/-/node10-1.0.11.tgz",
|
||||
"integrity": "sha512-DcRjDCujK/kCk/cUe8Xz8ZSpm8mS3mNNpta+jGCA6USEDfktlNvm1+IuZ9eTcDbNk41BHwpHHeW+N1lKCz4zOw==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/@tsconfig/node12": {
|
||||
"version": "1.0.11",
|
||||
"resolved": "https://registry.npmjs.org/@tsconfig/node12/-/node12-1.0.11.tgz",
|
||||
"integrity": "sha512-cqefuRsh12pWyGsIoBKJA9luFu3mRxCA+ORZvA4ktLSzIuCUtWVxGIuXigEwO5/ywWFMZ2QEGKWvkZG1zDMTag==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/@tsconfig/node14": {
|
||||
"version": "1.0.3",
|
||||
"resolved": "https://registry.npmjs.org/@tsconfig/node14/-/node14-1.0.3.tgz",
|
||||
"integrity": "sha512-ysT8mhdixWK6Hw3i1V2AeRqZ5WfXg1G43mqoYlM2nc6388Fq5jcXyr5mRsqViLx/GJYdoL0bfXD8nmF+Zn/Iow==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/@tsconfig/node16": {
|
||||
"version": "1.0.4",
|
||||
"resolved": "https://registry.npmjs.org/@tsconfig/node16/-/node16-1.0.4.tgz",
|
||||
"integrity": "sha512-vxhUy4J8lyeyinH7Azl1pdd43GJhZH/tP2weN8TntQblOY+A0XbT8DJk1/oCPuOOyg/Ja757rG0CgHcWC8OfMA==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/@types/json5": {
|
||||
"version": "0.0.29",
|
||||
"resolved": "https://registry.npmjs.org/@types/json5/-/json5-0.0.29.tgz",
|
||||
|
@ -1787,7 +1834,6 @@
|
|||
"version": "20.17.6",
|
||||
"resolved": "https://registry.npmjs.org/@types/node/-/node-20.17.6.tgz",
|
||||
"integrity": "sha512-VEI7OdvK2wP7XHnsuXbAJnEpEkF6NjSN45QJlL4VGqZSXsnicpesdTWsg9RISeSdYd3yeRj/y3k5KGjUXYnFwQ==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"undici-types": "~6.19.2"
|
||||
|
@ -2048,7 +2094,6 @@
|
|||
"version": "8.12.1",
|
||||
"resolved": "https://registry.npmjs.org/acorn/-/acorn-8.12.1.tgz",
|
||||
"integrity": "sha512-tcpGyI9zbizT9JbV6oYE477V6mTlXvvi0T0G3SNIYE2apm/G5huBa1+K89VGeovbg+jycCrfhl3ADxErOuO6Jg==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"bin": {
|
||||
"acorn": "bin/acorn"
|
||||
|
@ -2067,6 +2112,18 @@
|
|||
"acorn": "^6.0.0 || ^7.0.0 || ^8.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/acorn-walk": {
|
||||
"version": "8.3.4",
|
||||
"resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.3.4.tgz",
|
||||
"integrity": "sha512-ueEepnujpqee2o5aIYnvHU6C0A42MNdsIDeqy5BydrkuC5R1ZuUFnm27EeFJGoEHJQgn3uleRvmTXaJgfXbt4g==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"acorn": "^8.11.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=0.4.0"
|
||||
}
|
||||
},
|
||||
"node_modules/ajv": {
|
||||
"version": "6.12.6",
|
||||
"resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz",
|
||||
|
@ -2975,6 +3032,12 @@
|
|||
"dev": true,
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/create-require": {
|
||||
"version": "1.1.1",
|
||||
"resolved": "https://registry.npmjs.org/create-require/-/create-require-1.1.1.tgz",
|
||||
"integrity": "sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/cross-spawn": {
|
||||
"version": "7.0.3",
|
||||
"resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz",
|
||||
|
@ -3175,6 +3238,15 @@
|
|||
"integrity": "sha512-gxtyfqMg7GKyhQmb056K7M3xszy/myH8w+B4RT+QXBQsvAOdc3XymqDDPHx1BgPgsdAA5SIifona89YtRATDzw==",
|
||||
"license": "Apache-2.0"
|
||||
},
|
||||
"node_modules/diff": {
|
||||
"version": "4.0.2",
|
||||
"resolved": "https://registry.npmjs.org/diff/-/diff-4.0.2.tgz",
|
||||
"integrity": "sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==",
|
||||
"license": "BSD-3-Clause",
|
||||
"engines": {
|
||||
"node": ">=0.3.1"
|
||||
}
|
||||
},
|
||||
"node_modules/dlv": {
|
||||
"version": "1.1.3",
|
||||
"resolved": "https://registry.npmjs.org/dlv/-/dlv-1.1.3.tgz",
|
||||
|
@ -5127,6 +5199,12 @@
|
|||
"react": "^16.5.1 || ^17.0.0 || ^18.0.0 || ^19.0.0-rc"
|
||||
}
|
||||
},
|
||||
"node_modules/make-error": {
|
||||
"version": "1.3.6",
|
||||
"resolved": "https://registry.npmjs.org/make-error/-/make-error-1.3.6.tgz",
|
||||
"integrity": "sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==",
|
||||
"license": "ISC"
|
||||
},
|
||||
"node_modules/merge2": {
|
||||
"version": "1.4.1",
|
||||
"resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz",
|
||||
|
@ -6856,6 +6934,55 @@
|
|||
"integrity": "sha512-Y/arvbn+rrz3JCKl9C4kVNfTfSm2/mEp5FSz5EsZSANGPSlQrpRI5M4PKF+mJnE52jOO90PnPSc3Ur3bTQw0gA==",
|
||||
"license": "Apache-2.0"
|
||||
},
|
||||
"node_modules/ts-node": {
|
||||
"version": "10.9.2",
|
||||
"resolved": "https://registry.npmjs.org/ts-node/-/ts-node-10.9.2.tgz",
|
||||
"integrity": "sha512-f0FFpIdcHgn8zcPSbf1dRevwt047YMnaiJM3u2w2RewrB+fob/zePZcrOyQoLMMO7aBIddLcQIEK5dYjkLnGrQ==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@cspotcode/source-map-support": "^0.8.0",
|
||||
"@tsconfig/node10": "^1.0.7",
|
||||
"@tsconfig/node12": "^1.0.7",
|
||||
"@tsconfig/node14": "^1.0.0",
|
||||
"@tsconfig/node16": "^1.0.2",
|
||||
"acorn": "^8.4.1",
|
||||
"acorn-walk": "^8.1.1",
|
||||
"arg": "^4.1.0",
|
||||
"create-require": "^1.1.0",
|
||||
"diff": "^4.0.1",
|
||||
"make-error": "^1.1.1",
|
||||
"v8-compile-cache-lib": "^3.0.1",
|
||||
"yn": "3.1.1"
|
||||
},
|
||||
"bin": {
|
||||
"ts-node": "dist/bin.js",
|
||||
"ts-node-cwd": "dist/bin-cwd.js",
|
||||
"ts-node-esm": "dist/bin-esm.js",
|
||||
"ts-node-script": "dist/bin-script.js",
|
||||
"ts-node-transpile-only": "dist/bin-transpile.js",
|
||||
"ts-script": "dist/bin-script-deprecated.js"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@swc/core": ">=1.2.50",
|
||||
"@swc/wasm": ">=1.2.50",
|
||||
"@types/node": "*",
|
||||
"typescript": ">=2.7"
|
||||
},
|
||||
"peerDependenciesMeta": {
|
||||
"@swc/core": {
|
||||
"optional": true
|
||||
},
|
||||
"@swc/wasm": {
|
||||
"optional": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"node_modules/ts-node/node_modules/arg": {
|
||||
"version": "4.1.3",
|
||||
"resolved": "https://registry.npmjs.org/arg/-/arg-4.1.3.tgz",
|
||||
"integrity": "sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/tsconfig-paths": {
|
||||
"version": "3.15.0",
|
||||
"resolved": "https://registry.npmjs.org/tsconfig-paths/-/tsconfig-paths-3.15.0.tgz",
|
||||
|
@ -7002,7 +7129,6 @@
|
|||
"version": "5.6.3",
|
||||
"resolved": "https://registry.npmjs.org/typescript/-/typescript-5.6.3.tgz",
|
||||
"integrity": "sha512-hjcS1mhfuyi4WW8IWtjP7brDrG2cuDZukyrYrSauoXGNgx0S7zceP07adYkJycEr56BOUTNPzbInooiN3fn1qw==",
|
||||
"dev": true,
|
||||
"license": "Apache-2.0",
|
||||
"bin": {
|
||||
"tsc": "bin/tsc",
|
||||
|
@ -7032,7 +7158,6 @@
|
|||
"version": "6.19.8",
|
||||
"resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.19.8.tgz",
|
||||
"integrity": "sha512-ve2KP6f/JnbPBFyobGHuerC9g1FYGn/F8n1LWTwNxCEzd6IfqTwUQcNXgEtmmQ6DlRrC1hrSrBnCZPokRrDHjw==",
|
||||
"dev": true,
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/uri-js": {
|
||||
|
@ -7094,6 +7219,12 @@
|
|||
"integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/v8-compile-cache-lib": {
|
||||
"version": "3.0.1",
|
||||
"resolved": "https://registry.npmjs.org/v8-compile-cache-lib/-/v8-compile-cache-lib-3.0.1.tgz",
|
||||
"integrity": "sha512-wa7YjyUGfNZngI/vtK0UHAN+lgDCxBPCylVXGp0zu59Fz5aiGtNXaq3DhIov063MorB+VfufLh3JlF2KdTK3xg==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/which": {
|
||||
"version": "2.0.2",
|
||||
"resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz",
|
||||
|
@ -7324,6 +7455,15 @@
|
|||
"node": ">= 14"
|
||||
}
|
||||
},
|
||||
"node_modules/yn": {
|
||||
"version": "3.1.1",
|
||||
"resolved": "https://registry.npmjs.org/yn/-/yn-3.1.1.tgz",
|
||||
"integrity": "sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q==",
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=6"
|
||||
}
|
||||
},
|
||||
"node_modules/yocto-queue": {
|
||||
"version": "0.1.0",
|
||||
"resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz",
|
||||
|
|
|
@ -29,7 +29,8 @@
|
|||
"react": "^18",
|
||||
"react-dom": "^18",
|
||||
"tailwind-merge": "^2.5.4",
|
||||
"tailwindcss-animate": "^1.0.7"
|
||||
"tailwindcss-animate": "^1.0.7",
|
||||
"ts-node": "^10.9.2"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/node": "^20.17.6",
|
||||
|
|
|
@ -20,6 +20,7 @@ model carte {
|
|||
id String @id @default(uuid()) @db.Uuid
|
||||
name_en String
|
||||
name_fr String
|
||||
sanitized_name String
|
||||
released_at String
|
||||
small_image String
|
||||
normal_image String
|
||||
|
@ -36,12 +37,14 @@ model carte {
|
|||
set set @relation(fields: [set_id], references: [id])
|
||||
set_id String @db.Uuid
|
||||
rarity String
|
||||
type String?
|
||||
cardmarket_uri String?
|
||||
}
|
||||
|
||||
model set {
|
||||
id String @id @default(uuid()) @db.Uuid
|
||||
name_en String
|
||||
sanitized_name String
|
||||
code String
|
||||
set_type String
|
||||
released_at String?
|
||||
|
@ -54,5 +57,6 @@ model set {
|
|||
model bset {
|
||||
id String @id @default(uuid()) @db.Uuid
|
||||
name String
|
||||
sanitized_name String
|
||||
sets set[]
|
||||
}
|
||||
|
|
122
app/tools/createJson.mjs
Normal file
122
app/tools/createJson.mjs
Normal file
|
@ -0,0 +1,122 @@
|
|||
import { PrismaClient } from '@prisma/client'
|
||||
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"],
|
||||
"colorless": [],
|
||||
"azorius": ["W","U"],
|
||||
"dimir": ["U","B"],
|
||||
"rakdos": ["B","R"],
|
||||
"gruul": ["R","G"],
|
||||
"selesnya": ["G","W"],
|
||||
"orzhov": ["W","B"],
|
||||
"izzet": ["U","R"],
|
||||
"golgari": ["B","G"],
|
||||
"boros": ["R","W"],
|
||||
"simic": ["G","U"],
|
||||
"esper": ["W","U","B"],
|
||||
"grixis": ["U","B","R"],
|
||||
"jund": ["B","R","G"],
|
||||
"naya": ["R","G","W"],
|
||||
"bant": ["G","W","U"],
|
||||
"abzan": ["W","B","G"],
|
||||
"jeskai": ["U","R","W"],
|
||||
"sultai": ["B","G","U"],
|
||||
"mardu": ["R","W","B"],
|
||||
"temur": ["G","U","R"],
|
||||
"yore-tiller": ["W","U","B","R"],
|
||||
"glint-eye": ["U","B","R","G"],
|
||||
"dune-brood": ["B","R","G","W"],
|
||||
"ink-treader": ["R","G","W","U"],
|
||||
"witch-maw": ["G","W","U","B"],
|
||||
"five-color": ["G","W","U","B","R"],
|
||||
}
|
||||
|
||||
function getColorName(colorArray) {
|
||||
const colorArrayID = colorArray.sort().join(',')
|
||||
for (const colorName of Object.keys(color_names)) {
|
||||
if(colorArrayID === color_names[colorName].sort().join(',')){
|
||||
return(colorName)
|
||||
}
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
// I need to create
|
||||
// Lands
|
||||
// lands.json
|
||||
// All jsons lands from colors
|
||||
// Types
|
||||
|
||||
async function createJson() {
|
||||
console.log("Fetching data...")
|
||||
const bsets = await db.bset.findMany({
|
||||
relationLoadStrategy: "join",
|
||||
include: {
|
||||
sets: {
|
||||
include: {
|
||||
cards: true
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
let all_cards = []
|
||||
bsets.forEach((bset) => {
|
||||
bset.sets.forEach((set) => {
|
||||
all_cards = [...all_cards, ...set.cards]
|
||||
})
|
||||
})
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
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) {
|
||||
const colorName = getColorName(card.colors)
|
||||
if (card.type == "land") {
|
||||
if (colorName != "") {
|
||||
landsData[colorName].push(card)
|
||||
}
|
||||
}
|
||||
|
||||
if (card.colors.length <= 1) {
|
||||
colorsData[colorName][card.type].push(card)
|
||||
} else {
|
||||
colorsData["multicolor"][card.type].push(card)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
for (const index of Object.keys(colorsData)) {
|
||||
writeFileSync(import.meta.dirname + "/json/top/" + index + ".json",JSON.stringify(colorsData[index]), '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})
|
||||
}
|
||||
writeFileSync(import.meta.dirname + "/json/lands/" + colorName + ".json",JSON.stringify(landsData[colorName]), 'utf8')
|
||||
}
|
||||
writeFileSync(import.meta.dirname + "/json/lands/lands.json",JSON.stringify(landsJsonRoot), 'utf8')
|
||||
}
|
||||
|
||||
createJson()
|
|
@ -33,7 +33,7 @@ try {
|
|||
|
||||
for (const set of sets.data) {
|
||||
if(!preUpdateSetIds.includes(set.id)){
|
||||
const addingSetQuery = await client.query('INSERT INTO set(id, name_en, code, set_type, released_at, icon_svg_uri) VALUES($1, $2, $3, $4, $5, $6)', [set.id, set.name, set.code, set.set_type, set.released_at, set.icon_svg_uri])
|
||||
const addingSetQuery = await client.query('INSERT INTO set(id, name_en, sanitized_name, code, set_type, released_at, icon_svg_uri) VALUES($1, $2, $3, $4, $5, $6, $7)', [set.id, set.name, set.name.replace(/[^a-zA-Z0-9]/gim,"-").toLowerCase(), set.code, set.set_type, set.released_at, set.icon_svg_uri])
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -54,6 +54,27 @@ try {
|
|||
// For each card check if we need to upload it to the database
|
||||
for (const carte of scryfallData) {
|
||||
if(!preUpdateCardsIds.includes(carte.id)){
|
||||
let type = null
|
||||
const card_type = carte.type_line.toLowerCase()
|
||||
|
||||
if(card_type.includes("creature")){
|
||||
type = "creature"
|
||||
} else if (card_type.includes("planeswalker")) {
|
||||
type = "planeswalker"
|
||||
} else if (card_type.includes("artifact")) {
|
||||
type = "artifact"
|
||||
} else if (card_type.includes("instant")) {
|
||||
type = "instant"
|
||||
} else if (card_type.includes("enchantment")) {
|
||||
type = "enchantment"
|
||||
} else if (card_type.includes("sorcery")) {
|
||||
type = "sorcery"
|
||||
} else if (card_type.includes("land")) {
|
||||
type = "land"
|
||||
}
|
||||
|
||||
|
||||
|
||||
if(carte.printed_name == undefined) {
|
||||
// If the card doesn't have a french name, print it to the console and skip
|
||||
|
||||
|
@ -65,7 +86,7 @@ try {
|
|||
}
|
||||
|
||||
// Add the card to the database
|
||||
const addingCardsQuery = await client.query('INSERT INTO carte(id, name_en, name_fr, released_at, small_image, normal_image, mana_cost, cmc, type_line_en, type_line_fr, oracle_text_en, oracle_text_fr, power, toughness, colors, keywords, set_id, rarity, cardmarket_uri) 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.printed_name, carte.released_at, carte.image_uris.small, carte.image_uris.normal, carte.mana_cost, carte.cmc, carte.type_line, carte.printed_type_line, carte.oracle_text, carte.printed_text, carte.power, carte.toughness, carte.colors, carte.keywords, carte.set_id, carte.rarity, carte.purchase_uris?.cardmarket])
|
||||
const addingCardsQuery = await client.query('INSERT INTO carte(id, name_en, name_fr, released_at, small_image, normal_image, mana_cost, cmc, type_line_en, type_line_fr, oracle_text_en, oracle_text_fr, power, toughness, colors, keywords, set_id, rarity, cardmarket_uri, type, sanitized_name) VALUES($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13, $14, $15, $16, $17, $18, $19, $20, $21)', [carte.id, carte.name, carte.printed_name, carte.released_at, carte.image_uris.small, carte.image_uris.normal, carte.mana_cost, carte.cmc, carte.type_line, carte.printed_type_line, carte.oracle_text, carte.printed_text, carte.power, carte.toughness, carte.color_identity, carte.keywords, carte.set_id, carte.rarity, carte.purchase_uris?.cardmarket, type, carte.name.replace(/[^a-zA-Z0-9]/gim,"-").toLowerCase()])
|
||||
total_inserted = total_inserted + 1
|
||||
} else {
|
||||
total_skipped = total_skipped + 1
|
||||
|
|
Loading…
Reference in a new issue