This commit is contained in:
SushiDesigner 2023-09-11 22:19:16 -06:00
parent 2c80cbbfb9
commit 1dd918fc1c
30 changed files with 1394 additions and 561 deletions

1182
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,75 @@
<script lang="ts">
import { SlideToggle } from "@skeletonlabs/skeleton";
import { Regex } from "lucide-svelte";
let regEnabled = false
let mainEnabled = false
let gameEnabled = false
let keyEnabled = false
let bannerMessage = ""
export let jwt: string
async function updateSliders(){
const response = await fetch('admin/config',{method: "POST", headers: {"content-type": "application/json",'Authorization': jwt,}});
const data = (await response.json()).data
if (!data.error){
regEnabled = data.RegistrationEnabled
mainEnabled = data.MaintenanceEnabled
gameEnabled = data.GamesEnabled
keyEnabled = data.KeysEnabled
bannerMessage = data.bannermessage
}
}
updateSliders()
async function updateSetting(setting: String, update:boolean){
const response = await fetch('admin/config/update',{method: "POST", body:JSON.stringify({setting, update: update === true ? false : true}), headers: {"content-type": "application/json",'Authorization': jwt,}});
const data = (await response.json()).data
if (!data.error){
regEnabled = data.RegistrationEnabled
mainEnabled = data.MaintenanceEnabled
gameEnabled = data.GamesEnabled
keyEnabled = data.KeysEnabled
bannerMessage = data.bannermessage
}
}
</script>
<div class="grow">
<h2>Config</h2>
<div class="flex flex-col gap-4 justify-between">
<div class="flex flex-row space-x-2 grow">
<h5 class="text-tertiary-600 text-base">Registration enabled</h5>
<SlideToggle name="" active="bg-success-600" on:click={() => {updateSetting("RegistrationEnabled", regEnabled)}} bind:checked={regEnabled}></SlideToggle>
</div>
<div class="flex flex-row space-x-2 grow">
<h5 class="text-tertiary-600 text-base">Maintenance enabled</h5>
<SlideToggle name="" active="bg-success-600" on:click={() => {updateSetting("MaintenanceEnabled", mainEnabled)}} bind:checked={mainEnabled}></SlideToggle>
</div>
<div class="flex flex-row space-x-2 grow">
<h5 class="text-tertiary-600 text-base">Games enabled</h5>
<SlideToggle name="" active="bg-success-600" on:click={() => {updateSetting("GamesEnabled", gameEnabled)}} bind:checked={gameEnabled}></SlideToggle>
</div>
<div class="flex flex-row space-x-2 grow">
<h5 class="text-tertiary-600 text-base">Keys enabled (Keys can't be generated normally)</h5>
<SlideToggle name="" active="bg-success-600" on:click={() => {updateSetting("KeysEnabled", keyEnabled)}} bind:checked={keyEnabled}></SlideToggle>
</div>
<div class="flex flex-row space-x-2 grow">
<h5 class="text-tertiary-600 text-base">Banner message (Not functional yet.)</h5>
<input type="text" bind:value={bannerMessage} placeholder="..." class="input input-bordered input-primary w-full max-w-xs rounded-md" required>
</div>
</div>
</div>

View File

@ -0,0 +1,36 @@
<script lang="ts">
export let jwt: string
</script>
<div class="grow">
<h2 class="">Admin Logs</h2>
<table class="border-separate border-spacing-2 border border-slate-500 w-full">
<thead>
<tr>
<th class="border border-slate-600">Person</th>
<th class="border border-slate-600">Action</th>
<th class="border border-slate-600">Date</th>
</tr>
</thead>
<tbody>
<tr>
<td class="border border-slate-700">Indiana</td>
<td class="border border-slate-700">Indianapolis</td>
<td class="border border-slate-700">Indianapolis</td>
</tr>
<tr>
<td class="border border-slate-700">Ohio</td>
<td class="border border-slate-700">Columbus</td>
<td class="border border-slate-700">Indianapolis</td>
</tr>
<tr>
<td class="border border-slate-700">Michigan</td>
<td class="border border-slate-700">Detroit</td>
<td class="border border-slate-700">Indianapolis</td>
</tr>
</tbody>
</table>
</div>

View File

@ -7,7 +7,7 @@
let price:string
let creations: any[] = []
$:if (!itemname || !price){
$:if (!itemname || typeof price === "undefined"){
disabled = true
message.message = "Item name and price required."
message.error = true

View File

@ -98,8 +98,8 @@ $:type,updatecreations() // if type variable changes run updatecreations again
</label>
<label class="input-label gap-8">
<span class="pt-3">Description:</span>
<input bind:value={itemdesc} type="text" class="input input-bordered input-primary w-full max-w-md rounded-md" required>
<span class="">Description:</span>
<textarea bind:value={itemdesc} class="input input-bordered input-primary w-full max-w-md rounded-md" required></textarea>
</label>
<label class="input-label gap-8">

View File

@ -12,8 +12,8 @@ export let type = ""
<div class="flex flex-row grow gap-2">
<img alt={itemname} class="w-16" src="/api/thumbnailrender/asset/?id={itemid}"/>
<a href="/catalog/{itemid}/{itemname.replace(/[^a-zA-Z ]/g, "").replaceAll(' ', '-')}"><h5 class="!text-sm">{itemname}</h5></a>
<a href="/catalog/{itemid}/{itemname.replace(/[^0-9a-z ]/gi, '').replaceAll(' ', '-')}"><h5 class="!text-sm">{itemname}</h5></a>
</div>
<svg fill="none" stroke="currentColor" height="24" width="24" stroke-width="1.5" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg" aria-hidden="true"><path stroke-linecap="round" stroke-linejoin="round" d="M10.343 3.94c.09-.542.56-.94 1.11-.94h1.093c.55 0 1.02.398 1.11.94l.149.894c.07.424.384.764.78.93.398.164.855.142 1.205-.108l.737-.527a1.125 1.125 0 011.45.12l.773.774c.39.389.44 1.002.12 1.45l-.527.737c-.25.35-.272.806-.107 1.204.165.397.505.71.93.78l.893.15c.543.09.94.56.94 1.109v1.094c0 .55-.397 1.02-.94 1.11l-.893.149c-.425.07-.765.383-.93.78-.165.398-.143.854.107 1.204l.527.738c.32.447.269 1.06-.12 1.45l-.774.773a1.125 1.125 0 01-1.449.12l-.738-.527c-.35-.25-.806-.272-1.203-.107-.397.165-.71.505-.781.929l-.149.894c-.09.542-.56.94-1.11.94h-1.094c-.55 0-1.019-.398-1.11-.94l-.148-.894c-.071-.424-.384-.764-.781-.93-.398-.164-.854-.142-1.204.108l-.738.527c-.447.32-1.06.269-1.45-.12l-.773-.774a1.125 1.125 0 01-.12-1.45l.527-.737c.25-.35.273-.806.108-1.204-.165-.397-.505-.71-.93-.78l-.894-.15c-.542-.09-.94-.56-.94-1.109v-1.094c0-.55.398-1.02.94-1.11l.894-.149c.424-.07.765-.383.93-.78.165-.398.143-.854-.107-1.204l-.527-.738a1.125 1.125 0 01.12-1.45l.773-.773a1.125 1.125 0 011.45-.12l.737.527c.35.25.807.272 1.204.107.397-.165.71-.505.78-.929l.15-.894z"></path><path stroke-linecap="round" stroke-linejoin="round" d="M15 12a3 3 0 11-6 0 3 3 0 016 0z"></path></svg>
<a href="/catalog/{itemid}/configure" class="unstyled"><svg fill="none" stroke="currentColor" height="24" width="24" stroke-width="1.5" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg" aria-hidden="true"><path stroke-linecap="round" stroke-linejoin="round" d="M10.343 3.94c.09-.542.56-.94 1.11-.94h1.093c.55 0 1.02.398 1.11.94l.149.894c.07.424.384.764.78.93.398.164.855.142 1.205-.108l.737-.527a1.125 1.125 0 011.45.12l.773.774c.39.389.44 1.002.12 1.45l-.527.737c-.25.35-.272.806-.107 1.204.165.397.505.71.93.78l.893.15c.543.09.94.56.94 1.109v1.094c0 .55-.397 1.02-.94 1.11l-.893.149c-.425.07-.765.383-.93.78-.165.398-.143.854.107 1.204l.527.738c.32.447.269 1.06-.12 1.45l-.774.773a1.125 1.125 0 01-1.449.12l-.738-.527c-.35-.25-.806-.272-1.203-.107-.397.165-.71.505-.781.929l-.149.894c-.09.542-.56.94-1.11.94h-1.094c-.55 0-1.019-.398-1.11-.94l-.148-.894c-.071-.424-.384-.764-.781-.93-.398-.164-.854-.142-1.204.108l-.738.527c-.447.32-1.06.269-1.45-.12l-.773-.774a1.125 1.125 0 01-.12-1.45l.527-.737c.25-.35.273-.806.108-1.204-.165-.397-.505-.71-.93-.78l-.894-.15c-.542-.09-.94-.56-.94-1.109v-1.094c0-.55.398-1.02.94-1.11l.894-.149c.424-.07.765-.383.93-.78.165-.398.143-.854-.107-1.204l-.527-.738a1.125 1.125 0 01.12-1.45l.773-.773a1.125 1.125 0 011.45-.12l.737.527c.35.25.807.272 1.204.107.397-.165.71-.505.78-.929l.15-.894z"></path><path stroke-linecap="round" stroke-linejoin="round" d="M15 12a3 3 0 11-6 0 3 3 0 016 0z"></path></svg></a>
</div>

View File

@ -27,7 +27,7 @@
</script>
{#if useragent.includes("Android") === true || useragent.includes("iPhone") === true}
<!-- svelte-ignore a11y-click-events-have-key-events -->
<div class="unstyled group" on:click={()=> {document.location.href="/games/"+idofgame+"/"+gamename.replace(/[^a-zA-Z ]/g, "").replaceAll(' ', '-')}}>
<div class="unstyled group" on:click={()=> {document.location.href="/games/"+idofgame+"/"+gamename.replace(/[^0-9a-z ]/gi, '').replaceAll(' ', '-')}}>
<div class="card rounded-md card-glass-surface snap-center card-hover w-20 sm:w-40 relative">
{#if imageloading}
<div class="w-20 h-20 sm:w-40 sm:h-40 rounded-none placeholder animate-pulse"></div>
@ -43,7 +43,7 @@
</div>
</div>
{:else}
<a class="unstyled group" href="/games/{idofgame}/{gamename.replace(/[^a-zA-Z ]/g, "").replaceAll(' ', '-')}">
<a class="unstyled group" href="/games/{idofgame}/{gamename.replace(/[^0-9a-z ]/gi, '').replaceAll(' ', '-')}">
<div class="card rounded-md card-glass-surface snap-center card-hover w-20 sm:w-40 relative">
{#if imageloading}
<div class="w-20 h-20 sm:w-40 sm:h-40 rounded-none placeholder animate-pulse"></div>

View File

@ -37,12 +37,12 @@
</script>
<div class="card rounded-md card-glass-surface snap-center card-hover {width} relative hidden sm:block">
<a class="unstyled hidden sm:block" href="/catalog/{itemid}/{itemname.replace(/[^a-zA-Z ]/g, "").replaceAll(' ', '-')}">
<a class="unstyled hidden sm:block" href="/catalog/{itemid}/{itemname.replace(/[^0-9a-z ]/gi, '').replaceAll(' ', '-')}">
{#if type != "Audio" && type != "Video"}
{#if imageloading}
<div class="w-36 h-36 rounded-none placeholder animate-pulse"></div>
{/if}
<img alt="" class="avatar-image bg-surface-400-500-token w-full h-full flex aspect-square object-cover {imageloading === true ? 'hidden' : ''} " use:onload={()=> imageloading=false} src="/api/thumbnailrender/asset/?id={itemid}{moderation === false ? "": "&nonapproved=true"}" />
<img alt="" class="avatar-image bg-surface-400-500-token w-{width} h-{width} flex aspect-square object-cover {imageloading === true ? 'hidden' : ''} " use:onload={()=> imageloading=false} src="/api/thumbnailrender/asset/?id={itemid}{moderation === false ? "": "&nonapproved=true"}" />
{/if}
</a>
@ -61,13 +61,14 @@
{#if interact === "true"}
{#if equipped === true}
<button on:click={() => {action('remove',parseFloat({itemid}.itemid))}} class="btn variant-filled-primary rounded-md btn-sm absolute right-0 top-0">Remove</button>
<button on:click={() => {action('remove',parseFloat({itemid}.itemid))}} class="btn variant-filled-primary rounded-none btn-sm absolute right-0 top-0">Remove</button>
{:else}
<button on:click={() => {action('wear',parseFloat({itemid}.itemid))}} class="btn variant-filled-primary rounded-md btn-sm absolute right-0 top-0">Wear</button>
<button on:click={() => {action('wear',parseFloat({itemid}.itemid))}} class="btn variant-filled-primary rounded-none btn-sm absolute right-0 top-0">Wear</button>
{/if}
{/if}
<p class="truncate w-28">{itemname}</p>
{#if sales}
{#if interact !== "true"}
<div class="!text-xs">{sales??"0"} Sales</div>
{/if}

View File

@ -120,7 +120,7 @@ listenCookieChange(async ()=> {
<div class="relative">
<input type="text" bind:value={search} on:click={() => {search = previousearch}} placeholder="Search" class="input input-bordered input-primary pr-8 w-full rounded-none" maxlength=50 required>
{#if search}
<svg on:click={()=>{search=""}} class="w-8 h-8 absolute inset-y-0 right-0 pt-2 pr-3" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><line x1="18" y1="6" x2="6" y2="18"></line><line x1="6" y1="6" x2="18" y2="18"></line></svg>
<svg on:click={()=>{search=""}} on:keydown on:keyup on:keypress class="w-8 h-8 absolute inset-y-0 right-0 pt-2 pr-3" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><line x1="18" y1="6" x2="6" y2="18"></line><line x1="6" y1="6" x2="18" y2="18"></line></svg>
{:else}
<svg class="w-8 h-8 absolute inset-y-0 right-0 pt-2 pr-3 pointer-events-none" fill="none" stroke="currentColor" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M21 21l-6-6m2-5a7 7 0 11-14 0 7 7 0 0114 0z"></path></svg>
{/if}
@ -166,7 +166,7 @@ listenCookieChange(async ()=> {
<AppBar padding="px" slotLead="space-x-2">
<svelte:fragment slot="lead">
<a href="/home"><img src="/assets/images/logo600200.png" alt="meteorite" class="max-h-12 pl-6 hidden xl:block"></a>
<svg class="w-6 h-6 md:hidden block" on:click={drawerOpen} fill="none" stroke="currentColor" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M4 6h16M4 12h16M4 18h16"></path></svg>
<svg class="w-6 h-6 md:hidden block" on:click={drawerOpen} on:keydown on:keyup on:keypress fill="none" stroke="currentColor" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M4 6h16M4 12h16M4 18h16"></path></svg>
<a href="/home"><img src="/assets/images/logosmall.png" alt="meteorite" class="max-h-12 xl:hidden block"></a>
<div class="hidden md:block">
<a class="btn btn-sm rounded-none group relative" href="/games">Games
@ -187,7 +187,7 @@ listenCookieChange(async ()=> {
<div class="relative hidden md:block">
<input type="text" bind:value={search} on:dblclick={() => {search = previousearch}} placeholder="Search" class="input input-bordered input-primary pr-8 w-48 lg:w-96 max-w-full rounded-md" maxlength=50 required> <!-- refill on double click as well -->
{#if search}
<svg on:click={()=>{search=""}} class="w-8 h-8 absolute inset-y-0 right-0 pt-2 pr-3" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><line x1="18" y1="6" x2="6" y2="18"></line><line x1="6" y1="6" x2="18" y2="18"></line></svg>
<svg on:click={()=>{search=""}} on:keydown on:keyup on:keypress class="w-8 h-8 absolute inset-y-0 right-0 pt-2 pr-3" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><line x1="18" y1="6" x2="6" y2="18"></line><line x1="6" y1="6" x2="18" y2="18"></line></svg>
{:else}
<svg class="w-8 h-8 absolute inset-y-0 right-0 pt-2 pr-3 pointer-events-none" fill="none" stroke="currentColor" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M21 21l-6-6m2-5a7 7 0 11-14 0 7 7 0 0114 0z"></path></svg>
{/if}
@ -229,7 +229,7 @@ listenCookieChange(async ()=> {
<svelte:fragment slot="trail">
{#if data.user}
<Rocks/>
{coins??"0"}
{coins??"?"}
<span class="relative pr-2">
<button class="w-6 pt-2" use:menu={{ menu: 'navigation' }}>
<svg fill="none" stroke="currentColor" stroke-width="1.5" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg" aria-hidden="true">

View File

@ -6,7 +6,9 @@
import Lookup from "../../components/admin/lookup.svelte"
import Lookupdone from "../../components/admin/lookupdone.svelte"
import Assetqueue from '../../components/admin/assetqueue.svelte';
import Logs from '../../components/admin/logs.svelte';
import type { PageData } from '../$types';
import Config from "../../components/admin/config.svelte"
let lookupdata: any
let storeTab = "lookup"
@ -30,6 +32,14 @@
<Tab bind:group={storeTab} value="queue">Asset Queue</Tab>
</div>
<div class="pl-2">
<Tab bind:group={storeTab} value="logs">Logs</Tab>
</div>
<div class="pl-2">
<Tab bind:group={storeTab} value="config">Config</Tab>
</div>
<h5>Forums</h5>
<h5>Website</h5>
@ -62,5 +72,13 @@
<Assetqueue jwt={data.jwt}/>
{/if}
{#if storeTab === "logs"}
<Logs jwt={data.jwt}/>
{/if}
{#if storeTab === "config"}
<Config jwt={data.jwt}/>
{/if}
</div>
</div>

View File

@ -9,6 +9,8 @@
import { url } from "$lib/url"
let avatar: string;
import { avatarstore } from "$lib/avatarstore"
import { page } from '$app/stores';
import { goto, invalidate } from '$app/navigation';
import { onMount } from 'svelte';
avatarstore.subscribe(value => {
avatar = value
@ -16,13 +18,17 @@
let regenerating = false
$: query = $page.url
export let data: PageData;
const jwt = data.jwt;
const userid = data.user.userid
let avatartype = data.user.avatartype??"R6"
let avatarfilter = "shirts"
let currentItems: any[] = [];
$: avatarfilter = data.avatarfilter
$: currentPage = data.currentPage
$: maxiumumPage = data.maxiumumPage
$: currentItems = data.currentItems
async function updateBodyType(newavatartype: string){
if (avatartype != newavatartype){
avatartype = newavatartype
@ -36,19 +42,6 @@
}
}
async function updateItems(){
const response = await fetch(url+`/api/userinfo/${userid}`)
const data = await response.json()
if (currentItems){
currentItems.length = 0
currentItems = currentItems
}
currentItems = data.userinfo.inventory
currentItems = currentItems
currentItems = currentItems.filter(currentItems => currentItems.Type.toLowerCase() === avatarfilter)
//console.log(currentItems)
}
async function itemaction(action: any,itemid: Number){
console.log(action)
console.log(itemid)
@ -64,14 +57,11 @@
})
})
const itemaction = await itemactionresult.json()
updateItems()
invalidate("/api/userinfo/"+userid)
console.log(itemaction)
}
$:{
if (avatarfilter != "bodycolors"){
updateItems()
}else{
$:if (avatarfilter == "bodycolors"){
// pop up modal
const modalComponent: ModalComponent = {
// Pass a reference to your custom component
@ -86,7 +76,7 @@
};
modalStore.trigger(d);
}
}
let regeneratebtn = "Regenerate"
let regenerateimg: HTMLImageElement
@ -105,7 +95,19 @@
regenerating = false
}
}
</script>
function setPage(value: number){
if (currentPage-value >= 1 && currentPage-value <= maxiumumPage){
currentPage -= value
query.searchParams.set('page', currentPage.toString());
goto(query.href)
console.log(query.href)
}
}
//$:avatarfilter,updateAvatarFilter()
</script>
<div class="bg-surface-700 p-4 flex flex-row flex-wrap space-x-2 relative max-w-[1000px] m-0 m-auto">
@ -135,25 +137,25 @@
<div class="bg-surface-800">
<RadioGroup rounded="rounded-md truncate flex-wrap lg:flex-nowrap">
<RadioItem bind:group={avatarfilter} value="shirts">Shirts</RadioItem>
<RadioItem bind:group={avatarfilter} value="pants">Pants</RadioItem>
<RadioItem bind:group={avatarfilter} value="hats">Hats</RadioItem>
<RadioItem bind:group={avatarfilter} value="faces">Faces</RadioItem>
<RadioItem bind:group={avatarfilter} value="packages">Packages</RadioItem>
<RadioItem bind:group={avatarfilter} value="heads">Heads</RadioItem>
<RadioItem bind:group={avatarfilter} value="gears">Gears</RadioItem>
<RadioItem bind:group={avatarfilter} value="emotes">Emotes</RadioItem>
<RadioItem bind:group={avatarfilter} value="bodycolors">🖌️</RadioItem>
<a class="unstyled" href="?filter=shirts"><RadioItem bind:group={avatarfilter} value="shirts">Shirts</RadioItem></a>
<a class="unstyled" href="?filter=pants"><RadioItem bind:group={avatarfilter} value="pants">Pants</RadioItem></a>
<a class="unstyled" href="?filter=hats"><RadioItem bind:group={avatarfilter} value="hats">Hats</RadioItem></a>
<a class="unstyled" href="?filter=faces"><RadioItem bind:group={avatarfilter} value="faces">Faces</RadioItem></a>
<a class="unstyled" href="?filter=packages"><RadioItem bind:group={avatarfilter} value="packages">Packages</RadioItem></a>
<a class="unstyled" href="?filter=heads"><RadioItem bind:group={avatarfilter} value="heads">Heads</RadioItem></a>
<a class="unstyled" href="?filter=gears"><RadioItem bind:group={avatarfilter} value="gears">Gears</RadioItem></a>
<a class="unstyled" href="?filter=emotes"><RadioItem bind:group={avatarfilter} value="emotes">Emotes</RadioItem></a>
<a class="unstyled" href="?filter=bodycolors"><RadioItem bind:group={avatarfilter} value="bodycolors">🖌️</RadioItem></a>
</RadioGroup>
<div class="flex flex-col flex-wrap sm:grid sm:grid-cols-6 gap-2 p-2">
{#if currentItems && avatarfilter != "bodycolors"}
{#each currentItems as {ItemName, ItemId, Hidden, Equipped}}
{#each currentItems as {itemdata, ItemId, Hidden, Equipped}}
{#if !Hidden}
<Itemcard itemname={ItemName} itemid={ItemId} width="w-24" interact="true" equipped={Equipped} action={itemaction}/>
<Itemcard itemname={itemdata.Name} itemid={ItemId} width="w-24" interact="true" equipped={Equipped} action={itemaction}/>
<div class="bg-surface-800 flex flex-row block sm:hidden px-2 relative">
<a class="unstyled" href="/catalog/{ItemId}/{ItemName.replace(/[^a-zA-Z ]/g, "").replaceAll(' ', '-')}"><img class="w-20" alt="L" src="/api/thumbnailrender/asset/?id={ItemId}"/></a>
<a class="unstyled" href="/catalog/{ItemId}/{itemdata.Name.replace(/[^0-9a-z ]/gi, '').replaceAll(' ', '-')}"><img class="w-20" alt="L" src="/api/thumbnailrender/asset/?id={ItemId}"/></a>
<div>
<h3 class="truncate">{ItemName}</h3>
<h3 class="truncate">{itemdata.Name}</h3>
</div>
{#if Equipped === true}
<button on:click={() => {itemaction('remove',parseFloat(ItemId))}} class="btn variant-filled-primary rounded-md btn-sm absolute right-0 top-5">Remove</button>
@ -166,6 +168,13 @@
{/each}
{/if}
</div>
{#if avatarfilter != "bodycolors"}
<div class="flex flex-row space-x-2 justify-center">
<button on:click={() => {setPage(1)}} class="btn btn-sm bg-surface-600 rounded-md">&lt;</button>
<h5 class="">{currentPage} / {maxiumumPage}</h5>
<button on:click={() => {setPage(-1)}} class="btn btn-sm bg-surface-600 rounded-md">&gt;</button>
</div>
{/if}
</div>
</div>

View File

@ -0,0 +1,27 @@
import { error } from '@sveltejs/kit';
import type { PageLoad } from './$types';
import { url as url2 } from '$lib/url';
export const load = (async ({ parent, url, fetch }) => {
const avatarfilter = String(url.searchParams.get('filter') ?? 'shirts');
const currentPage = Number(url.searchParams.get('page') ?? '1');
let currentItems: Array<any> = [];
const userid = (await parent()).user.userid
const response = await fetch(url2+`/api/userinfo/${userid}/inventory`, {method: 'POST', headers: {'Content-Type': 'application/json'}, body: JSON.stringify({page: currentPage, filter: avatarfilter})})
const data = await response.json()
currentItems = data.inventory
currentItems = currentItems.filter(currentItems => currentItems.Type.toLowerCase() === avatarfilter)
if (!data.error){
return {
currentItems,
maxiumumPage: data.pages,
currentPage,
avatarfilter
}
}
}) satisfies PageLoad;

View File

@ -4,7 +4,7 @@
import Itemcard from '../../components/itemcard.svelte';
import Rocks from '../../components/rocks.svelte';
import { url } from "$lib/url"
import { Avatar } from '@skeletonlabs/skeleton';
import { menu } from '@skeletonlabs/skeleton';
import { page } from '$app/stores';
import { goto } from '$app/navigation';
import type { PageData } from "../$types";
@ -12,6 +12,7 @@
let bodyparts = false
let animations = false
let items: any
let currentSort = "Oldest"
$: query = $page.url.searchParams;
export let data: PageData;
@ -120,12 +121,41 @@
<h3>{currentFilter}</h3>
<div class="flex flex-row ">
<h4>{currentCategory}</h4>
<button class="ring-surface-500 hover:ring-surface-300 ring-2 rounded p-1 flex flex-row gap-x-3 relative ml-auto w-24" use:menu={{ menu: 'navigationsort' }}>
<h5 class="!text-sm hover:text-white">{currentSort}</h5>
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" class="w-4 ml-auto"><line x1="12" y1="5" x2="12" y2="19"></line><polyline points="19 12 12 19 5 12"></polyline></svg>
<nav class=" rounded-none mt-6 " data-menu="navigationsort">
<ul>
<button class="btn bg-surface-700 !rounded-none text-sm">Oldest</button>
</ul>
<ul>
<button class="btn bg-surface-700 !rounded-none text-sm">Newest</button>
</ul>
<ul>
<button class="btn bg-surface-700 !rounded-none text-sm">Bestselling</button>
</ul>
<ul>
<button class="btn bg-surface-700 !rounded-none text-sm">Price (High to Low)</button>
</ul>
<ul>
<button class="btn bg-surface-700 !rounded-none text-sm">Price (Low to High)</button>
</ul>
</nav>
</button>
</div>
<div class="flex flex-col flex-wrap sm:grid sm:grid-cols-6 sm:grid-rows-5 gap-2">
{#if items}
{#each items as {Name, Price, ItemId, Hidden, Sales}}
<Itemcard itemname={Name} itemid={ItemId} price={Price} sales={Sales}/>
<a class="unstyled block sm:hidden px-2" href="/catalog/{ItemId}/{Name.replace(/[^a-zA-Z ]/g, "").replaceAll(' ', '-')}"><div class="bg-surface-800 flex flex-row">
<a class="unstyled block sm:hidden px-2" href="/catalog/{ItemId}/{Name.replace(/[^0-9a-z ]/gi, '').replaceAll(' ', '-')}"><div class="bg-surface-800 flex flex-row">
<img class="w-20" alt="L" src="/api/thumbnailrender/asset/?id={ItemId}"/>
<div>
<h3 class="truncate">{Name}</h3>

View File

@ -5,7 +5,7 @@ export const load = (async ({ fetch, params }) => {
const res = await fetch(`http://mete0r.xyz/api/catalog/iteminfo/${params.slug}`)
const data = await res.json()
if (data.error === false){
throw redirect(301,'/catalog/'+params.slug+'/'+data.iteminfo.Name.replace(/[^a-zA-Z ]/g, "").replaceAll(' ', '-'))
throw redirect(301,'/catalog/'+params.slug+'/'+data.iteminfo.Name.replace(/[^0-9a-z ]/gi, '').replaceAll(' ', '-'))
}
throw error(404, 'Not found');
}) satisfies PageLoad;

View File

@ -3,9 +3,10 @@
import Rocks from '../../../../components/rocks.svelte';
import Commentcard from '../../../../components/commentcard.svelte';
import type { PageData } from './$types';
import { toastStore } from '@skeletonlabs/skeleton';
import { toastStore, menu } from '@skeletonlabs/skeleton';
import type { ToastSettings } from '@skeletonlabs/skeleton';
import { coinstore } from "$lib/coinstore"
import { MoreHorizontalIcon } from "lucide-svelte";
export let data: PageData;
@ -85,13 +86,25 @@
<div class="sm:border m-auto sm:p-12 sm:w-[418px] relative">
<img class="m-auto border sm:border-0 object-cover" alt={data.item.Name} src="/api/thumbnailrender/asset/?id={data.item.ItemId}"/>
{#if data.user.admin === true}
{#if data.user.admin === true || ( data.user.userid === data.item?.Creator && data.user.ugcpermission === true)}
<button on:click={moderate} class="btn variant-filled-primary rounded-md btn-sm absolute right-0 top-0">Delete</button>
{/if}
</div>
<div class="text-center sm:text-left">
<h2>{data.item.Name}</h2>
<div class="flex flex-row">
<h2>{data.item.Name}</h2>
<span class="relative ml-auto">
<button use:menu={{ menu: 'navigationconfig' }}>
<MoreHorizontalIcon />
</button>
<nav class=" rounded-none pb-2 pt-2 w-40" data-menu="navigationconfig">
<ul>
<a href="/catalog/{data.item.ItemId}/configure" class="btn variant-filled-primary !rounded-md w-full btn-sm text-xs">Configure</a>
</ul>
</nav>
</span>
</div>
<h5>By <a href="/users/{data.item.Creator??"0"}">{data.creatorusername??"SushiWasNotHere"}</a></h5>
@ -119,7 +132,7 @@
<div class="flex flex-row w-full pt-2">
<h5 class="text-base">Description</h5>
<div class=" pl-8 ">
<h5 class="text-base w-52 h-48 overflow-y-auto break-words">{data.item?.Description??""}</h5>
<h5 class="text-base w-52 h-48 overflow-y-auto break-words whitespace-pre-line">{data.item?.Description??""}</h5>
</div>
</div>
</div>

View File

@ -5,8 +5,8 @@ export const load = (async ({ fetch, params }) => {
const res = await fetch(`http://mete0r.xyz/api/catalog/iteminfo/${params.slug}`)
const data = await res.json()
if (params.name != data.iteminfo.Name.replace(/[^a-zA-Z ]/g, "").replaceAll(' ', '-')){
throw redirect(301,'/catalog/'+params.slug+'/'+data.iteminfo.Name.replace(/[^a-zA-Z ]/g, "").replaceAll(' ', '-'))
if (params.name != data.iteminfo.Name.replace(/[^0-9a-z ]/gi, '').replaceAll(' ', '-')){
throw redirect(301,'/catalog/'+params.slug+'/'+data.iteminfo.Name.replace(/[^0-9a-z ]/gi, '').replaceAll(' ', '-'))
}
if (data.error === false){

View File

@ -0,0 +1,92 @@
<script lang="ts">
import { goto } from '$app/navigation';
import type { PageData } from './$types';
export let data: PageData;
const jwt = data.jwt
let disabled = false
let message = {error: false, message: ""}
let name:string
let price:number
let description:string
async function save(){
const save = await fetch(`/api/catalog/iteminfo/${data.item.ItemId}/configure`, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Authorization': jwt,
},
body: JSON.stringify({
name,
description,
price
})
})
const saveJson = await save.json()
if (!saveJson.error){
message.message = "Done!"
message.error = false
goto("/catalog/"+data.item.ItemId)
}else{
message.message = saveJson.error
message.error = true
}
}
$:if (!name && !description && !price && price !== 0){
disabled = true
message.error = true
message.message = "Change required"
}else{
disabled = false
message.message = ""
}
</script>
<svelte:head>
<title>Meteorite - {data.item.Name} Configure</title>
</svelte:head>
<div class="bg-surface-700 p-4 space-x-2 flex flex-row flex-wrap sm:flex-nowrap max-w-[1100px] m-0 m-auto">
<div class="sm:border sm:p-12 sm:w-[418px] relative ">
<img class="m-auto border sm:border-0 object-cover" alt={data.item.Name} src="/api/thumbnailrender/asset/?id={data.item.ItemId}"/>
</div>
<div class="text-center sm:text-left ml-auto grow">
<h2>{data.item.Name} - Configure</h2>
<div class="space-y-4 w-full">
<h5 class="">Edit Asset</h5>
<label class="label">
<span>Name</span> <input type="text" bind:value={name} class="input input-bordered input-primary w-full rounded-md" >
</label>
<label class="label">
<span>Price</span> <input type="number" bind:value={price} min="0" step="1" class="input input-bordered input-primary w-full rounded-md" >
</label>
<label class="label">
<span>Description</span> <textarea bind:value={description} class="input input-bordered input-primary w-full rounded-md" ></textarea>
</label>
<div class="!text-xs mt-6 {message.error === true ? 'text-error-600' : 'text-success-600'}">{message.message??""}</div>
<button on:click={save} type="submit" class="btn variant-filled-primary btn-sm w-full text-base rounded-md" disabled={disabled}>Save</button>
</div>
</div>
</div>

View File

@ -0,0 +1,19 @@
import { error, redirect } from '@sveltejs/kit';
import type { PageLoad } from './$types';
export const load = (async ({ parent ,fetch, params }) => {
const res = await fetch(`http://mete0r.xyz/api/catalog/iteminfo/${params.slug}`)
const data = await res.json()
let self = (await parent()).user
if (data.iteminfo?.Creator != self.userid && self.admin === false){
throw error(403, 'Forbidden')
}
if (data.error === false){
return {
item: data.iteminfo
}
}
throw error(404, 'Not found');
}) satisfies PageLoad;

View File

@ -123,7 +123,7 @@
{#if items}
{#each items as {Name, Price, ItemId, Hidden, Sales}}
<Itemcard itemname={Name} itemid={ItemId} price={Price} sales={Sales}/>
<a class="unstyled block sm:hidden px-2" href="/catalog/{ItemId}/{Name.replace(/[^a-zA-Z ]/g, "").replaceAll(' ', '-')}"><div class="bg-surface-800 flex flex-row">
<a class="unstyled block sm:hidden px-2" href="/catalog/{ItemId}/{Name.replace(/[^0-9a-z ]/gi, '').replaceAll(' ', '-')}"><div class="bg-surface-800 flex flex-row">
<img class="w-20" alt="L" src="/api/thumbnailrender/asset/?id={ItemId}"/>
<div>
<h3 class="truncate">{Name}</h3>

View File

@ -5,7 +5,7 @@ export const load = (async ({ fetch, params }) => {
const res = await fetch(`http://mete0r.xyz/games/gameinfo/${params.slug}`)
const data = await res.json()
if (data.error === false){
throw redirect(301,'/games/'+params.slug+'/'+data.gameinfo.nameofgame.replace(/[^a-zA-Z ]/g, "").replaceAll(' ', '-'))
throw redirect(301,'/games/'+params.slug+'/'+data.gameinfo.nameofgame.replace(/[^0-9a-z ]/gi, '').replaceAll(' ', '-'))
}
throw error(404, 'Not found');
}) satisfies PageLoad;

View File

@ -12,6 +12,7 @@
import Linkdiscordmodal from '../../../../components/games/linkdiscordmodal.svelte';
import Advertisemodal from '../../../../components/assets/advertisemodal.svelte';
import Itemcard from '../../../../components/itemcard.svelte';
import { MoreHorizontalIcon } from 'lucide-svelte';
let storeTab = 'About'
export let data: PageData;
@ -139,10 +140,10 @@
{#if data?.user?.admin === true || data.game?.useridofowner === data?.user?.userid}
<span class="relative">
<button class="w-6 pt-2" use:menu={{ menu: 'navigationgame' }}>
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-menu"><line x1="3" y1="12" x2="21" y2="12"></line><line x1="3" y1="6" x2="21" y2="6"></line><line x1="3" y1="18" x2="21" y2="18"></line></svg>
<MoreHorizontalIcon />
</button>
<nav class="list-nav rounded-none pb-2 pt-2 w-40" data-menu="navigationgame">
<ul>
<nav class="rounded-none pb-2 pt-2 w-40" data-menu="navigationgame">
<ul class="space-y-1">
<button on:click={shutdown} class="btn variant-filled-primary !rounded-md w-full btn-sm text-xs">Shut Down All Servers</button>
<button on:click={advertise} class="btn variant-filled-primary !rounded-md w-full btn-sm text-xs">Advertise</button>
</ul>

View File

@ -5,8 +5,8 @@ export const load = (async ({ fetch, params }) => {
const res = await fetch(`http://mete0r.xyz/games/gameinfo/${params.slug}`)
const data = await res.json()
if (params.name != data.gameinfo.nameofgame.replace(/[^a-zA-Z ]/g, "").replaceAll(' ', '-')){
throw redirect(301,'/games/'+params.slug+'/'+data.gameinfo.nameofgame.replace(/[^a-zA-Z ]/g, "").replaceAll(' ', '-'))
if (params.name != data.gameinfo.nameofgame.replace(/[^0-9a-z ]/gi, '').replaceAll(' ', '-')){
throw redirect(301,'/games/'+params.slug+'/'+data.gameinfo.nameofgame.replace(/[^0-9a-z ]/gi, '').replaceAll(' ', '-'))
}
if (data.error === false){

View File

@ -0,0 +1,22 @@
<script lang="ts">
import type { PageData } from "../$types";
import Groupbar from "../../components/groups/groupbar.svelte";
let selectedgroup = "Lambda Media Group"
export let data: PageData;
</script>
<div class="sm:flex sm:flex-row gap-2 max-w-[1400px] m-0 m-auto">
{#if data.groups}
<Groupbar selectedgroup={selectedgroup} grouplist={data.groups}/>
{/if}
<div class="col-span-5">
</div>
</div>

View File

@ -0,0 +1,14 @@
import type { PageLoad } from './$types';
import { url } from "$lib/url"
export const load = (async ({ fetch, parent }) => {
let data = await parent()
const response = await fetch(url+'/api/groups',{method: "POST",headers: {"content-type": "application/json",'Authorization': data.jwt,}});
const groups = await response.json()
return {
groups
}
}) satisfies PageLoad;

View File

@ -0,0 +1,122 @@
<script lang="ts">
import { Avatar, menu } from "@skeletonlabs/skeleton";
import type { PageData } from "../$types";
import Groupbar from "../../../components/groups/groupbar.svelte";
import Commentcard from "../../../components/commentcard.svelte";
import { url } from "$lib/url"
let selectedgroup = "Lambda Media Group"
let currentPage = 1;
let maxiumumPage = 1;
let users: []
export let data: PageData;
let groupid = data.group.groupid
async function updateMembers(){
const response = await fetch(url+'/api/groups/'+groupid+'/members',{method: "POST", body: JSON.stringify({page: currentPage, rank: 1}),headers: {"content-type": "application/json"}});
const data = await response.json()
if (!data.error){
if (users){
users.length = 0
users = users
}
users = data.data
users = users
maxiumumPage = data.pages
}
}
updateMembers()
</script>
<div class="sm:flex sm:flex-row gap-2 max-w-[1400px] m-0 m-auto">
<Groupbar selectedgroup={selectedgroup} grouplist={data.groups}/>
<div class="col-span-5 mt-8 w-full space-y-2">
<div class="bg-surface-700 p-4">
<div class="">
<div class="flex flex-row gap-x-4">
<Avatar width="w-36" rounded="rounded-none" src="/assets/groupicons/icon-0.png" />
<div>
<h2 class="font-bold">{data.group.Name}</h2>
<h5 class="!text-sm">By <a href="/users/{data.group.owner.userid}">{data.group.owner.username}</a></h5>
</div>
</div>
<div class="w-full space-y-2">
<h5 class="font-bold !text-base">Description</h5>
<h5>{data.group.Description}</h5>
</div>
</div>
</div>
<h4 class="font-bold">Shout</h4>
<div class="">
<div class="bg-surface-700 p-4 flex flex-row gap-x-2">
<a href="/users/0"><Avatar width="w-12" src="/api/thumbnailrender?id=0&type=headshot" /></a>
<div>
<h5 class="!text-sm font-semibold">SushiWasNotHere</h5>
<h5 class="!text-sm">Hello, world!</h5>
</div>
</div>
<div class="bg-surface-700 p-4 flex flex-row gap-x-2">
<textarea class="rounded-md grow input input-bordered input-primary" placeholder="Shout here!!" />
<button class="btn mb-6 variant-filled-primary rounded-md ">Shout</button>
</div>
</div>
<div class="flex flex-row justify-between">
<h4 class="font-bold">Members</h4>
<div class="flex flex-row gap-x-2">
<button on:click={() => {}} class="btn btn-sm bg-surface-600 rounded-md">&lt;</button>
<h5 class="">1 / 1</h5>
<button on:click={() => {}} class="btn btn-sm bg-surface-600 rounded-md">&gt;</button>
<button class="ring-surface-500 hover:ring-surface-300 ring-2 rounded p-1 flex flex-row gap-x-3 relative">
<h5 class="!text-sm hover:text-white">Members</h5>
<h5 class="!text-sm hover:text-white">(1)</h5>
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" class="w-4 "><line x1="12" y1="5" x2="12" y2="19"></line><polyline points="19 12 12 19 5 12"></polyline></svg>
</button>
</div>
</div>
<div class="bg-surface-700 p-4 flex flex-row gap-x-2">
{#if users}
{#each users as {userid, username}}
<a class="unstyled" href="/users/{userid}"><div class="w-20">
<Avatar width="w-20" src="/api/thumbnailrender?id={userid}&type=headshot" />
<h5 class="!text-base truncate">{username}</h5>
</div></a>
{/each}
{/if}
</div>
<h4 class="font-bold">Wall</h4>
<Commentcard PostText="Post" PlaceholderText="Say something..."/>
</div>
</div>

View File

@ -0,0 +1,21 @@
import type { PageLoad } from './$types';
import { url } from "$lib/url"
import { error } from '@sveltejs/kit';
export const load = (async ({ fetch, parent, params }) => {
let data = await parent()
const response = await fetch(url+'/api/groups',{method: "POST",headers: {"content-type": "application/json",'Authorization': data.jwt,}});
const groups = await response.json()
const responsegroup = await fetch(url+'/api/groups/'+params.slug,{method: "POST",headers: {"content-type": "application/json",'Authorization': data.jwt,}});
const group = await responsegroup.json()
if (!group.error){
return {
groups,
group: group.data
}
}
throw error(404, 'Not found');
}) satisfies PageLoad;

View File

@ -0,0 +1,117 @@
<script lang="ts">
import { goto } from "$app/navigation";
import { FileDropzone } from "@skeletonlabs/skeleton";
import type { PageData } from "../$types";
let groupname:string
let groupdescription:string
let files: FileList;
let publicgroup = true
let disabled = true
import Rocks from "../../../components/rocks.svelte";
export let data: PageData;
let jwt = data.jwt
$:if (groupname && files && data.user.coins >= 100){
disabled = false
}else{
disabled = true
}
const toBase64 = (file: Blob) => new Promise((resolve, reject) => {
const reader = new FileReader();
reader.readAsDataURL(file);
reader.onload = () => resolve(reader.result);
reader.onerror = error => reject(error);
})
async function create(){
const formData = new FormData();
formData.append("groupicon", files[0])
formData.append("groupname", groupname)
formData.append("description", groupdescription??"...")
formData.append("publicgroup",publicgroup.toString())
const req = await fetch("/api/groups/create", {
method: "post",
body: formData,
headers: {
'Authorization': jwt,
},
});
const res = await req.json();
if (!res.error){
goto("/groups")
}else{
}
}
let base64:any
async function conv(){
base64 = await toBase64(files[0])
}
$:if (files){
conv()
}
</script>
<div class="max-w-[1200px] m-0 m-auto">
<div class="flex flex-col gap-y-2">
<h2 class="font-bold">Create a Group</h2>
<label>
<span class="block text-sm">Group Name</span>
<input bind:value={groupname} maxlength={20} type="text" class="input input-bordered input-primary w-full rounded-md" placeholder="Name of group" required>
</label>
<label>
<span class="block text-sm">Group Description</span>
<textarea bind:value={groupdescription} maxlength={500} class="input input-bordered input-primary w-full h-64 rounded-md" placeholder="Description" required ></textarea>
</label>
<label>
<span class="block text-sm">Icon</span>
<input class="w-full" accept="image/png" bind:files type="file" />
{#if base64}
<img alt="" class="w-32 aspect-square" src={base64}/>
{/if}
</label>
<h4 class="font-bold">Settings</h4>
<div class="space-y-4 w-full bg-surface-700 rounded-md p-4">
<label class="flex items-center space-x-2">
<input bind:group={publicgroup} class="radio" type="radio" checked name="radio-setting" value={true} />
<p>Anyone can join</p>
</label>
<label class="flex items-center space-x-2">
<input bind:group={publicgroup} class="radio" type="radio" name="radio-setting" value={false} />
<p>Manual Approval</p>
</label>
</div>
<div class="flex flex-row gap-2 justify-end">
<a href="/groups" class="btn variant-ringed-surface rounded-md btn-sm">Cancel</a>
<button class="btn variant-filled-primary rounded-md btn-sm" disabled={disabled} on:click={create}>
<Rocks width="w-4"/>
100
</button>
</div>
</div>
</div>

View File

@ -18,6 +18,7 @@
let creations: any[] = []
let editAbout = false
let about:string
let checkedgames = false
//$:console.log(friends)
async function saveabout(){
const result = await fetch('/settings/aboutme', {
@ -48,9 +49,10 @@
const res = await fetch(`/api/userinfo/${data.profile.userid}/creations`)
creations = await res.json()
console.log(creations)
checkedgames = true
}
$:if (storeTab === "Games" && creations.length === 0){
$:if (storeTab === "Games" && creations.length === 0 && checkedgames === false){
requestGames()
}
@ -236,10 +238,10 @@
<Avatar width="w-[300px] hidden md:block justify-self-center" background="" alt={data.profile.username} src="/api/thumbnailrender/?id={data.profile.userid+"&a="+Date.now()}"/>
<!-- if a user has less than 8 items in there inventory we space it differently -->
<div class="bg-primary-700 max-h-[300px] col-span-2 md:col-span-1 px-2 py-2 md:p-8 gap-2 {equippedcount <= 8 ? 'md:gap-y-10' : ''} overflow-x-scroll md:overflow-x-hidden md:overflow-y-scroll grid md:grid-cols-4 grid-flow-col md:grid-rows-none md:grid-flow-row auto-rows-max auto-cols-max">
{#if data.profile.inventory}
{#each data.profile.inventory as {Type, ItemId, ItemName,Equipped,Hidden}}
{#if data.wearingItems}
{#each data.wearingItems as {Type, ItemId, itemdata,Equipped,Hidden}}
{#if Equipped === true && !Hidden}
<a href="/catalog/{ItemId}/{ItemName.replace(/[^a-zA-Z ]/g, "").replaceAll(' ', '-')}"><img class="bg-surface-800 p-2 rounded-md w-28" alt={ItemName} src='/api/thumbnailrender/asset/?id={ItemId}'/></a>
<a href="/catalog/{ItemId}/{itemdata.Name.replace(/[^0-9a-z ]/gi, '').replaceAll(' ', '-')}"><img class="bg-surface-800 p-2 rounded-md w-28" alt={itemdata.Name} src='/api/thumbnailrender/asset/?id={ItemId}'/></a>
{/if}
{/each}
{/if}

View File

@ -1,10 +1,12 @@
import { error } from '@sveltejs/kit';
import type { PageLoad } from './$types';
import { url } from '$lib/url';
export const load = (async ({ fetch, params, parent }) => {
let data = await parent()
let alreadyFriends = false
let otherUserWantsToBeFriends = false
let wearingItems: Array<any> = [];
const res = await fetch(`http://mete0r.xyz/api/userinfo/${params.slug}`)
const datauser = await res.json()
@ -35,7 +37,9 @@ if (requestresult?.message === "Other user wants to be friends."){
}
const wearingresponse = await fetch(url+`/api/userinfo/${params.slug}/inventory`, {method: 'POST', headers: {'Content-Type': 'application/json'}, body: JSON.stringify({onlywearing: true})})
const wearingdata = await wearingresponse.json()
wearingItems = wearingdata.inventory
if (datauser.error === false){
@ -43,7 +47,8 @@ if (requestresult?.message === "Other user wants to be friends."){
profile: datauser.userinfo,
alreadyFriends,
otherUserWantsToBeFriends,
visits: datavisits.visits
visits: datavisits.visits,
wearingItems
}
}
throw error(404, 'Not found');

View File

@ -18,6 +18,7 @@ const defaultconfig = {
"/favicon": deb,
"/assets": deb,
"/settings/": deb,
"/admin/": deb,
}
}
};