Merge pull request #3 from calcorum/marketplace-page

Marketplace page
This commit is contained in:
Cal Corum 2025-05-12 21:18:21 -05:00 committed by GitHub
commit ed33f1886c
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
14 changed files with 839 additions and 41 deletions

0
assets/css/styles.css Normal file
View File

426
components/Marketplace.vue Normal file
View File

@ -0,0 +1,426 @@
<template>
<main class="marketplace-layout">
<section class="filters-section">
<!-- Filters Toggle -->
<details class="filters-toggle" :open="showFilters">
<summary @click.prevent="showFilters = !showFilters">
Filters
<small v-if="hasActiveFilters" style="margin-left: 0.5rem;">({{ activeFilterCount }} active)</small>
</summary>
<form @submit.prevent class="filters">
<fieldset>
<div class="grid">
<label>
Min Cost
<input type="number" v-model.number="marketplace.minCost" inputmode="numeric" />
</label>
<label>
Max Cost
<input type="number" v-model.number="marketplace.maxCost" inputmode="numeric" />
</label>
</div>
<label>
Rarity
<select v-model="marketplace.rarities" multiple size="6">
<option value="Replacement">Replacement</option>
<option value="Reserve">Reserve</option>
<option value="Starter">Starter</option>
<option value="All-Star">All-Star</option>
<option value="MVP">MVP</option>
<option value="Hall of Fame">Hall of Fame</option>
</select>
</label>
<label>
Cardset
<select v-model="marketplace.cardset" multiple size="5">
<option v-for="name in cardsetNames" :key="name" :value="name">
{{ name }}
</option>
</select>
</label>
<button type="button" @click="marketplace.clearFilters" class="secondary">
Clear Filters
</button>
</fieldset>
</form>
</details>
<!-- Active Filter Chips -->
<div v-if="hasActiveFilters" class="filter-chips">
<span v-if="marketplace.minCost" class="chip">
Min: {{ marketplace.minCost }}
<button @click="marketplace.minCost = null" aria-label="Remove Min Cost">&times;</button>
</span>
<span v-if="marketplace.maxCost" class="chip">
Max: {{ marketplace.maxCost }}
<button @click="marketplace.maxCost = null" aria-label="Remove Max Cost">&times;</button>
</span>
<span v-for="rar in marketplace.rarities" :key="rar" class="chip">
{{ rar }}
<button @click="removeRarity(rar)" aria-label="Remove Rarity">&times;</button>
</span>
<span v-for="set in marketplace.cardset" :key="set" class="chip">
{{ set }}
<button @click="removeCardset(set)" aria-label="Remove Cardset">&times;</button>
</span>
</div>
</section>
<!-- Player List -->
<section class="player-list">
<div v-if="loading">
<article v-for="n in 6" :key="n" aria-busy="true">
<header><h2>Loading...</h2></header>
<p>Loading player data...</p>
</article>
</div>
<div v-else>
<article
v-for="player in players"
:key="player.player_id"
class="player-card"
@click="toggleExpanded(player.player_id)"
:aria-expanded="expandedPlayerId === player.player_id"
>
<header class="clickable-header">
<h2 class="player-name">{{ player.player_name }}</h2>
<div class="summary-info">
<small>
{{ player.cardset_name }} {{ player.franchise_name }}
<span class="rarity-badge" :style="{ backgroundColor: '#' + player.rarity_color }">
{{ player.rarity_name }}
</span> {{ player.player_cost }}
</small>
</div>
</header>
<transition name="fade">
<div v-if="expandedPlayerId === player.player_id" class="expanded-content">
<img :src="player.player_headshot" alt="Player Headshot" class="headshot" />
<div class="strat-card-container">
<img :src="player.player_card_image" alt="Card Image" class="strat-card" />
<img v-if="player.player_card_image2" :src="player.player_card_image2" alt="Card Image 2" class="strat-card" />
</div>
</div>
</transition>
</article>
</div>
</section>
<!-- Pagination -->
<nav class="pagination-controls">
<ul>
<li>
<button @click="previousPage" :disabled="page === 1">Previous</button>
</li>
<li>Page {{ page }}</li>
<li>
<button @click="nextPage">Next</button>
</li>
</ul>
</nav>
</main>
</template>
<script setup lang="ts">
import { ref, onMounted, watch, computed } from 'vue'
import { useRoute, useRouter } from 'vue-router'
import { useMarketplaceStore } from '@/stores/marketplace'
import type { MarketplacePlayer } from '~/types/MarketplacePlayer'
const route = useRoute()
const router = useRouter()
const client = useSupabaseClient()
const marketplace = useMarketplaceStore()
const players = ref<MarketplacePlayer[]>([])
const loading = ref(false)
const pageSize = ref(20)
const page = ref(1)
const expandedPlayerId = ref<number | null>(null)
const showFilters = ref(false)
// Example cardset list
const cardsetNames = [
'2021 Season', '2022 Season', '2023 Season', 'Mario Super Sluggers', 'Backyard Baseball'
]
// Computed
const hasActiveFilters = computed(() => {
return (
marketplace.minCost !== null ||
marketplace.maxCost !== null ||
marketplace.rarities.length > 0 ||
marketplace.cardset.length > 0
)
})
const activeFilterCount = computed(() => {
let count = 0
if (marketplace.minCost !== null) count++
if (marketplace.maxCost !== null) count++
count += marketplace.rarities.length
count += marketplace.cardset.length
return count
})
const fetchPlayers = async () => {
loading.value = true
const from = (page.value - 1) * pageSize.value
const to = from + pageSize.value - 1
let query = client.from('marketplace').select('*').range(from, to)
if (marketplace.minCost !== null && marketplace.minCost > 0) {
query = query.gte('player_cost', marketplace.minCost)
}
if (marketplace.maxCost !== null && marketplace.maxCost > 0) {
query = query.lte('player_cost', marketplace.maxCost)
}
if (marketplace.rarities?.length > 0) {
query = query.in('rarity_name', marketplace.rarities)
}
if (marketplace.cardset?.length > 0) {
query = query.in('cardset_name', marketplace.cardset)
}
const { data, error } = await query
if (error) console.error('Supabase error:', error)
loading.value = false
players.value = data || []
}
const toggleExpanded = (playerId: number) => {
expandedPlayerId.value = expandedPlayerId.value === playerId ? null : playerId
}
const removeRarity = (rarity: string) => {
marketplace.rarities = marketplace.rarities.filter(r => r !== rarity)
}
const removeCardset = (cardset: string) => {
marketplace.cardset = marketplace.cardset.filter(c => c !== cardset)
}
const updateRoute = () => {
router.replace({
query: {
page: page.value.toString(),
...(marketplace.minCost != null && { minCost: marketplace.minCost }),
...(marketplace.maxCost != null && { maxCost: marketplace.maxCost }),
...(marketplace.rarities.length && { rarity: marketplace.rarities }),
...(marketplace.cardset.length && { cardset: marketplace.cardset }),
}
})
}
const previousPage = () => {
if (page.value > 1) {
page.value--
updateRoute()
fetchPlayers()
}
}
const nextPage = () => {
page.value++
updateRoute()
fetchPlayers()
}
onMounted(async () => {
const { getNumber, getArray } = useSafeQuery()
page.value = getNumber('page') || 1
marketplace.setFilters({
minCost: getNumber('minCost'),
maxCost: getNumber('maxCost'),
rarities: getArray('rarities'),
cardset: getArray('cardset'),
})
await fetchPlayers()
})
watch(
[() => marketplace.minCost, () => marketplace.maxCost, () => marketplace.rarities, () => marketplace.cardset],
() => {
page.value = 1
updateRoute()
fetchPlayers()
},
{ deep: true }
)
</script>
<style scoped>
.marketplace-layout {
display: flex;
flex-direction: column;
min-height: 100vh; /* Full height of screen */
}
.filters-section {
padding-left: 1rem;
padding-right: 1rem;
padding-top: 1rem;
}
.player-list {
flex: 1 1 auto; /* Take up the leftover space */
overflow-y: auto; /* Scroll if too many players */
padding-left: 1rem;
padding-right: 1rem;
padding-bottom: 1rem;
}
.pagination-controls {
padding: 1rem;
text-align: center;
}
.grid {
display: grid;
gap: 1rem;
grid-template-columns: 1fr 1fr;
}
.filters-toggle summary {
cursor: pointer;
font-size: 1.25rem;
}
.filter-chips {
display: flex;
flex-wrap: wrap;
gap: 0.5rem;
margin: 1rem 0;
}
.chip {
display: inline-flex;
align-items: center;
background: var(--pico-primary-background);
color: var(--pico-primary-contrast);
padding: 0.25rem 0.5rem;
border-radius: var(--pico-border-radius);
}
.chip button {
background: transparent;
border: none;
color: inherit;
margin-left: 0.25rem;
cursor: pointer;
font-size: 1rem;
}
.player-card {
padding: 1rem;
margin-bottom: 1rem;
border: 1px solid var(--pico-border-color);
border-radius: var(--pico-border-radius);
cursor: pointer;
transition: background 0.3s;
display: flex;
flex-direction: column;
}
.player-card .clickable-header {
display: flex;
justify-content: space-between;
align-items: center;
flex-wrap: wrap; /* Allow wrapping of content if it exceeds screen width */
gap: 0.5rem; /* Space between name and summary info */
}
.player-card .player-name {
font-size: 1.25rem;
font-weight: bold;
}
.player-card .summary-info {
display: flex;
align-items: center;
gap: 0.5rem;
}
.player-card .summary-info small {
font-size: 1rem;
color: var(--pico-muted-color);
}
.player-card:hover {
background: var(--pico-muted-color);
}
.rarity-badge {
display: inline-block;
padding: 0.2rem 0.5rem;
border-radius: 999px;
font-weight: bold;
font-size: 0.85rem;
line-height: 1;
}
.clickable-header {
display: flex;
justify-content: space-between;
align-items: center;
}
.expanded-content {
display: flex;
flex-direction: column;
align-items: center;
gap: 1rem;
}
.strat-card-container {
display: flex;
justify-content: center;
gap: 1rem;
flex-wrap: wrap; /* Wrap on small screens */
}
img.strat-card {
width: 100%;
height: auto;
margin-bottom: 1rem;
}
img.headshot {
min-width: 80px;
max-width: 120px;
width: 20%;
aspect-ratio: 1/1; /* Force it to be a perfect square */
object-fit: cover;
border-radius: 50%;
border: 3px solid white;
background: white;
margin: 0 auto 8px;
}
.fade-enter-active,
.fade-leave-active {
transition: all 0.3s ease;
}
.fade-enter-from,
.fade-leave-to {
opacity: 0;
transform: translateY(-10px);
}
</style>

View File

@ -44,6 +44,9 @@ function toggleMenu() {
<!-- Menu -->
<ul class="menu" :class="{ open: menuOpen }">
<li>
<NuxtLink to="/marketplace">Marketplace</NuxtLink>
</li>
<li>
<NuxtLink to="/players/random">Random Cards</NuxtLink>
</li>
@ -51,7 +54,7 @@ function toggleMenu() {
<NuxtLink to="/players/69">Card 69</NuxtLink>
</li>
<li>
<a href="#">Shop</a>
<a href="https://ko-fi.com/manticorum">Shop</a>
</li>
<li v-if="user?.id" class="user-info">

View File

@ -14,7 +14,7 @@
<p class="description">Description: {{ player?.description }}</p>
<p class="cost">Cost: ${{ player?.cost }}</p>
<p class="cost">Cost: {{ player?.cost }}</p>
</div>
</template>
@ -29,8 +29,8 @@ const props = defineProps<{
<style scoped>
.player-card {
max-width: 400px;
background: white;
border-radius: 12px;
background: var(--pico-card-background-color);
border-radius: var(--pico-border-radius);
overflow: hidden;
box-shadow: 0 4px 12px rgba(0,0,0,0.1);
padding: 16px;

View File

@ -0,0 +1,37 @@
// composables/useSafeQuery.ts
import { useRoute } from 'vue-router'
export const useSafeQuery = () => {
const route = useRoute()
const getNumber = (key: string): number | undefined => {
const value = route.query[key]
if (typeof value === 'string') {
const parsed = Number(value)
return isNaN(parsed) ? undefined : parsed
}
return undefined
}
const getArray = (key: string): string[] => {
const value = route.query[key]
if (Array.isArray(value)) {
return value.map(String)
}
if (typeof value === 'string') {
return [value]
}
return []
}
const getString = (key: string): string | undefined => {
const value = route.query[key]
return typeof value === 'string' ? value : undefined
}
return {
getNumber,
getArray,
getString,
}
}

View File

@ -1,19 +1,5 @@
// https://nuxt.com/docs/api/configuration/nuxt-config
export default defineNuxtConfig({
compatibilityDate: '2024-11-01',
devtools: {
enabled: true,
timeline: {
enabled: true,
},
},
modules: ['@nuxtjs/supabase'],
css: ['@picocss/pico'],
app: {
head: {
title: 'Paper Dynasty',
@ -26,6 +12,29 @@ export default defineNuxtConfig({
}
},
compatibilityDate: '2024-11-01',
css: [
'@picocss/pico',
'/assets/css/styles.css'
],
devtools: {
enabled: true,
timeline: {
enabled: true,
},
},
imports: {
dirs: [
'utils',
]
},
modules: ['@nuxtjs/supabase', '@pinia/nuxt'],
runtimeConfig: {
public: {
supabaseKey: 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJzdXBhYmFzZSIsInJlZiI6ImNucGhwbnV2aGp2cXprY2J3emRrIiwicm9sZSI6ImFub24iLCJpYXQiOjE3NDU4MTE3ODQsImV4cCI6MjA2MTM4Nzc4NH0.k3V9c2oiG8kufPa3_a4v6UdiGI6ML6-5lH2oifStB3I',

47
package-lock.json generated
View File

@ -9,7 +9,9 @@
"dependencies": {
"@nuxtjs/supabase": "^1.5.0",
"@picocss/pico": "^2.1.1",
"@pinia/nuxt": "^0.11.0",
"nuxt": "^3.17.1",
"pinia": "^3.0.2",
"vue": "^3.5.13",
"vue-router": "^4.5.1"
},
@ -3017,6 +3019,21 @@
"integrity": "sha512-kIDugA7Ps4U+2BHxiNHmvgPIQDWPDU4IeU6TNRdvXQM1uZX+FibqDQT2xUOnnO2yq/LUHcwnGlu1hvf4KfXnMg==",
"license": "MIT"
},
"node_modules/@pinia/nuxt": {
"version": "0.11.0",
"resolved": "https://registry.npmjs.org/@pinia/nuxt/-/nuxt-0.11.0.tgz",
"integrity": "sha512-QGFlUAkeVAhPCTXacrtNP4ti24sGEleVzmxcTALY9IkS6U5OUox7vmNL1pkqBeW39oSNq/UC5m40ofDEPHB1fg==",
"license": "MIT",
"dependencies": {
"@nuxt/kit": "^3.9.0"
},
"funding": {
"url": "https://github.com/sponsors/posva"
},
"peerDependencies": {
"pinia": "^3.0.2"
}
},
"node_modules/@pkgjs/parseargs": {
"version": "0.11.0",
"resolved": "https://registry.npmjs.org/@pkgjs/parseargs/-/parseargs-0.11.0.tgz",
@ -8998,6 +9015,36 @@
"url": "https://github.com/sponsors/jonschlinkert"
}
},
"node_modules/pinia": {
"version": "3.0.2",
"resolved": "https://registry.npmjs.org/pinia/-/pinia-3.0.2.tgz",
"integrity": "sha512-sH2JK3wNY809JOeiiURUR0wehJ9/gd9qFN2Y828jCbxEzKEmEt0pzCXwqiSTfuRsK9vQsOflSdnbdBOGrhtn+g==",
"license": "MIT",
"dependencies": {
"@vue/devtools-api": "^7.7.2"
},
"funding": {
"url": "https://github.com/sponsors/posva"
},
"peerDependencies": {
"typescript": ">=4.4.4",
"vue": "^2.7.0 || ^3.5.11"
},
"peerDependenciesMeta": {
"typescript": {
"optional": true
}
}
},
"node_modules/pinia/node_modules/@vue/devtools-api": {
"version": "7.7.6",
"resolved": "https://registry.npmjs.org/@vue/devtools-api/-/devtools-api-7.7.6.tgz",
"integrity": "sha512-b2Xx0KvXZObePpXPYHvBRRJLDQn5nhKjXh7vUhMEtWxz1AYNFOVIsh5+HLP8xDGL7sy+Q7hXeUxPHB/KgbtsPw==",
"license": "MIT",
"dependencies": {
"@vue/devtools-kit": "^7.7.6"
}
},
"node_modules/pkg-types": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/pkg-types/-/pkg-types-2.1.0.tgz",

View File

@ -13,7 +13,9 @@
"dependencies": {
"@nuxtjs/supabase": "^1.5.0",
"@picocss/pico": "^2.1.1",
"@pinia/nuxt": "^0.11.0",
"nuxt": "^3.17.1",
"pinia": "^3.0.2",
"vue": "^3.5.13",
"vue-router": "^4.5.1"
},

9
pages/marketplace.vue Normal file
View File

@ -0,0 +1,9 @@
<template>
<section>
<h1>Marketplace</h1>
<Marketplace />
</section>
</template>
<script lang="ts" setup>
</script>

View File

@ -12,8 +12,6 @@
async () => {
const { data } = await client.from('random_player')
.select('*,rarity!inner(*),mlb_player!inner(*)')
.eq('franchise', 'Baltimore Orioles')
.eq('mlb_player.offense_col', 1)
.limit(3)
console.log('players from supabase: ', data)

24
stores/marketplace.ts Normal file
View File

@ -0,0 +1,24 @@
import { defineStore } from 'pinia'
export const useMarketplaceStore = defineStore('marketplace', {
state: () => ({
minCost: null as number | null,
maxCost: null as number | null,
rarities: [] as string[],
cardset: [] as string[],
}),
actions: {
setFilters(filters: Partial<{ minCost: number, maxCost: number, rarities: string[], cardset: string[] }>) {
if (filters.minCost !== undefined) this.minCost = filters.minCost
if (filters.maxCost !== undefined) this.maxCost = filters.maxCost
if (filters.rarities !== undefined) this.rarities = filters.rarities
if (filters.cardset !== undefined) this.cardset = filters.cardset
},
clearFilters() {
this.minCost = null
this.maxCost = null
this.rarities = []
this.cardset = []
}
}
})

12
types/MarketplacePlayer.d.ts vendored Normal file
View File

@ -0,0 +1,12 @@
export interface MarketplacePlayer {
player_id: number
player_name: string
cardset_name: string
player_cost: number
rarity_name: string
rarity_color: string
franchise_name: string
player_headshot: string
player_card_image: string
player_card_image2: string
}

253
types/supabase.d.ts vendored
View File

@ -9,6 +9,69 @@ export type Json =
export type Database = {
public: {
Tables: {
cards: {
Row: {
created_at: string;
id: number;
pack_id: number | null;
player_id: number;
team_id: number;
variant: number | null;
};
Insert: {
created_at?: string;
id?: number;
pack_id?: number | null;
player_id: number;
team_id: number;
variant?: number | null;
};
Update: {
created_at?: string;
id?: number;
pack_id?: number | null;
player_id?: number;
team_id?: number;
variant?: number | null;
};
Relationships: [
{
foreignKeyName: "cards_pack_id_fkey";
columns: ["pack_id"];
isOneToOne: false;
referencedRelation: "packs";
referencedColumns: ["id"];
},
{
foreignKeyName: "cards_player_id_fkey";
columns: ["player_id"];
isOneToOne: false;
referencedRelation: "marketplace";
referencedColumns: ["player_id"];
},
{
foreignKeyName: "cards_player_id_fkey";
columns: ["player_id"];
isOneToOne: false;
referencedRelation: "players";
referencedColumns: ["id"];
},
{
foreignKeyName: "cards_player_id_fkey";
columns: ["player_id"];
isOneToOne: false;
referencedRelation: "random_player";
referencedColumns: ["id"];
},
{
foreignKeyName: "cards_team_id_fkey";
columns: ["team_id"];
isOneToOne: false;
referencedRelation: "teams";
referencedColumns: ["id"];
},
];
};
cardsets: {
Row: {
created_at: string;
@ -75,6 +138,95 @@ export type Database = {
};
Relationships: [];
};
pack_type: {
Row: {
card_count: number | null;
cost: number;
created_at: string;
description: string | null;
for_purchase: boolean | null;
id: number;
name: string;
};
Insert: {
card_count?: number | null;
cost: number;
created_at?: string;
description?: string | null;
for_purchase?: boolean | null;
id?: number;
name: string;
};
Update: {
card_count?: number | null;
cost?: number;
created_at?: string;
description?: string | null;
for_purchase?: boolean | null;
id?: number;
name?: string;
};
Relationships: [];
};
packs: {
Row: {
created_at: string;
id: number;
open_time: string | null;
owner_team_id: number | null;
pack_cardset_id: number | null;
pack_team_id: number | null;
pack_type_id: number | null;
};
Insert: {
created_at?: string;
id?: number;
open_time?: string | null;
owner_team_id?: number | null;
pack_cardset_id?: number | null;
pack_team_id?: number | null;
pack_type_id?: number | null;
};
Update: {
created_at?: string;
id?: number;
open_time?: string | null;
owner_team_id?: number | null;
pack_cardset_id?: number | null;
pack_team_id?: number | null;
pack_type_id?: number | null;
};
Relationships: [
{
foreignKeyName: "packs_owner_team_id_fkey";
columns: ["owner_team_id"];
isOneToOne: false;
referencedRelation: "teams";
referencedColumns: ["id"];
},
{
foreignKeyName: "packs_pack_cardset_id_fkey";
columns: ["pack_cardset_id"];
isOneToOne: false;
referencedRelation: "cardsets";
referencedColumns: ["id"];
},
{
foreignKeyName: "packs_pack_team_id_fkey";
columns: ["pack_team_id"];
isOneToOne: false;
referencedRelation: "teams";
referencedColumns: ["id"];
},
{
foreignKeyName: "packs_pack_type_id_fkey";
columns: ["pack_type_id"];
isOneToOne: false;
referencedRelation: "pack_type";
referencedColumns: ["id"];
},
];
};
players: {
Row: {
bbref_id: string | null;
@ -217,13 +369,47 @@ export type Database = {
};
Relationships: [];
};
rosters: {
Row: {
created_at: string;
description: string | null;
id: number;
name: string;
team_id: number;
};
Insert: {
created_at?: string;
description?: string | null;
id?: number;
name: string;
team_id: number;
};
Update: {
created_at?: string;
description?: string | null;
id?: number;
name?: string;
team_id?: number;
};
Relationships: [
{
foreignKeyName: "rosters_team_id_fkey";
columns: ["team_id"];
isOneToOne: false;
referencedRelation: "teams";
referencedColumns: ["id"];
},
];
};
teams: {
Row: {
abbrev: string | null;
career: string | null;
collection_value: string | null;
color: string | null;
discord_id: string;
event_id: string | null;
gm_profile_id: string | null;
gmid: number | null;
gmname: string | null;
gsheet: string | null;
@ -243,27 +429,9 @@ export type Database = {
career?: string | null;
collection_value?: string | null;
color?: string | null;
discord_id: string;
event_id?: string | null;
gmid?: number | null;
gmname?: string | null;
gsheet?: string | null;
has_guide?: string | null;
id: number;
is_ai?: number | null;
lname?: string | null;
logo?: string | null;
ranking?: number | null;
season?: number | null;
sname?: string | null;
team_value?: string | null;
wallet?: number | null;
};
Update: {
abbrev?: string | null;
career?: string | null;
collection_value?: string | null;
color?: string | null;
event_id?: string | null;
gm_profile_id?: string | null;
gmid?: number | null;
gmname?: string | null;
gsheet?: string | null;
@ -278,10 +446,53 @@ export type Database = {
team_value?: string | null;
wallet?: number | null;
};
Relationships: [];
Update: {
abbrev?: string | null;
career?: string | null;
collection_value?: string | null;
color?: string | null;
discord_id?: string;
event_id?: string | null;
gm_profile_id?: string | null;
gmid?: number | null;
gmname?: string | null;
gsheet?: string | null;
has_guide?: string | null;
id?: number;
is_ai?: number | null;
lname?: string | null;
logo?: string | null;
ranking?: number | null;
season?: number | null;
sname?: string | null;
team_value?: string | null;
wallet?: number | null;
};
Relationships: [
{
foreignKeyName: "teams_gm_profile_id_fkey";
columns: ["gm_profile_id"];
isOneToOne: false;
referencedRelation: "profiles";
referencedColumns: ["id"];
},
];
};
};
Views: {
marketplace: {
Row: {
cardset_name: string | null;
franchise_name: Database["public"]["Enums"]["franchise"] | null;
player_cost: number | null;
player_id: number | null;
player_name: string | null;
player_positions: string[] | null;
rarity_color: string | null;
rarity_name: string | null;
};
Relationships: [];
};
random_player: {
Row: {
bbref_id: string | null;

20
utils/playerMapper.ts Normal file
View File

@ -0,0 +1,20 @@
import type { MarketplacePlayer } from "~/types/MarketplacePlayer";
import type { Player } from "~/types/Player";
export function mapMarketplacePlayersToPlayers(marketplacePlayers: MarketplacePlayer[]): Player[] {
return marketplacePlayers.map(mp => ({
id: mp.player_id,
name: mp.player_name,
cost: mp.player_cost,
image: mp.player_card_image,
headshot: mp.player_headshot,
description: '',
franchise: mp.franchise_name,
rarity: {
id: 0,
name: mp.rarity_name,
color: mp.rarity_color,
value: 0,
},
}))
}