much progress on layout the foundations of the Friendship page in the front, also refactored some code to reuse displaying a users profile info

This commit is contained in:
Me
2022-12-10 07:13:28 +01:00
parent 15ea27955b
commit 61828e5be7
8 changed files with 874 additions and 173 deletions

View File

@@ -50,6 +50,7 @@ export class UsersController {
@Get('search')
findOneByUsername(@Query('username') username: string, @Req() req) {
const user : User = req.user;
console.log('searching for user' + user.username);
return this.usersService.findOneByUsername(user.id.toString(),username);
}

View File

@@ -0,0 +1,112 @@
<script lang="ts">
import { onMount } from 'svelte';
import { location } from 'svelte-spa-router';
import GenerateUserDisplay from './GenerateUserDisplay.svelte';
// using location won't work cuz i do a fetch but i don't change the page fragment, so means nothing to location...
// this is how you access /:first for example
// export let params = {}
// <p>Your name is: <b>{params.first}</b> <b>{#if params.last}{params.last}{/if}</b></p>
// If i export these vars, maybe as an nice tidy object, i could pass whatever i like to them
// The current user, some other user, whatever, and thus reuse this Componente for the user and their friends or whatever
// will have to coordinate with Back, will know more once the Game stats are in the back
// wait maybe this won't work, cuz like it's still going through a route, i would have to update a Store Var each time...
// not sure if that's what i want...
// maybe the rank is determined dynamically just in the front based on win loss ratio or something no one cares about
// why bother storing that shit in the back...
// maybe i need a Rank.svelte component
// ohhh i could make above a certain rank glitter! like that CSS tutorial showed me!
export let aUsername;
let user;
let rank = '';
let avatar;
// i think i don't need to do this once i sort out the {wrap} conditions: in theory i could pass values to the Route
// once the async authentication check is done
onMount( async() => {
console.log('Display aUser username: '+ aUsername)
// http://transcendance:8080/api/v2/user?username=NomDuUserATrouver
user = await fetch(`http://transcendance:8080/api/v2/user?username=${aUsername}`)
.then( (x) => x.json() );
console.log('Display a user: ' + user.username)
// console.log('profile display did my fetch')
// should i be updating the userStore or is that unnecessary?
if (user.loseGame > user.winGame) {
rank = 'Bitch Ass Loser!'
} else if (user.loseGame === user.winGame) {
rank = 'Fine i guess...'
} else {
rank = 'Yea you da Boss!'
}
await fetch("http://transcendance:8080/api/v2/user/avatar", {method: "GET"})
.then(response => {return response.blob()})
.then(data => {
const url = URL.createObjectURL(data);
avatar = url;
});
// tmp
// console.log('mounted Profile Display')
// console.log(user);
})
// Glittery Stars and such for Rank
let index = 0, interval = 1000;
const rand = (min, max) =>
Math.floor(Math.random() * (max - min + 1)) + min;
// it's unhappy that "star" isn't typeset, no idea what to do about it...
const animate = (star) => {
// the if seems to have fixed the type issue
if (star) {
star.style.setProperty("--star-left", `${rand(-10, 100)}%`);
star.style.setProperty("--star-top", `${rand(-40, 80)}%`);
star.style.animation = "none";
star.offsetHeight;
star.style.animation = "";
}
}
// This is the part i invented, it was kinda a fucking nightmare...
let stars = [];
for (let i = 0; i < 3; i++) {
setTimeout(() => {
animate(stars[i]);
setInterval(() => animate(stars[i]), 1000);
}, index++ * (interval / 3))
}
</script>
{#if user !== undefined}
<GenerateUserDisplay {user}/>
{:else}
<h2>Sorry</h2>
<div>Failed to load user {aUsername}</div>
{/if}
<style>
</style>

View File

@@ -0,0 +1,305 @@
<script lang="ts">
import { onMount } from 'svelte';
import { location } from 'svelte-spa-router';
// this is how you access /:first for example
// export let params = {}
// <p>Your name is: <b>{params.first}</b> <b>{#if params.last}{params.last}{/if}</b></p>
// If i export these vars, maybe as an nice tidy object, i could pass whatever i like to them
// The current user, some other user, whatever, and thus reuse this Componente for the user and their friends or whatever
// will have to coordinate with Back, will know more once the Game stats are in the back
// wait maybe this won't work, cuz like it's still going through a route, i would have to update a Store Var each time...
// not sure if that's what i want...
// maybe the rank is determined dynamically just in the front based on win loss ratio or something no one cares about
// why bother storing that shit in the back...
// maybe i need a Rank.svelte component
// ohhh i could make above a certain rank glitter! like that CSS tutorial showed me!
let user;
let rank = '';
let avatar;
// i think i don't need to do this once i sort out the {wrap} conditions: in theory i could pass values to the Route
// once the async authentication check is done
onMount( async() => {
// console.log('mounting profile display')
user = await fetch('http://transcendance:8080/api/v2/user')
.then( (x) => x.json() );
// console.log('profile display did my fetch')
// should i be updating the userStore or is that unnecessary?
if (user.loseGame > user.winGame) {
rank = 'Bitch Ass Loser!'
} else if (user.loseGame === user.winGame) {
rank = 'Fine i guess...'
} else {
rank = 'Yea you da Boss!'
}
await fetch("http://transcendance:8080/api/v2/user/avatar", {method: "GET"})
.then(response => {return response.blob()})
.then(data => {
const url = URL.createObjectURL(data);
avatar = url;
});
// tmp
// console.log('mounted Profile Display')
// console.log(user);
})
// Glittery Stars and such for Rank
let index = 0, interval = 1000;
const rand = (min, max) =>
Math.floor(Math.random() * (max - min + 1)) + min;
// it's unhappy that "star" isn't typeset, no idea what to do about it...
const animate = (star) => {
// the if seems to have fixed the type issue
if (star) {
star.style.setProperty("--star-left", `${rand(-10, 100)}%`);
star.style.setProperty("--star-top", `${rand(-40, 80)}%`);
star.style.animation = "none";
star.offsetHeight;
star.style.animation = "";
}
}
// This is the part i invented, it was kinda a fucking nightmare...
let stars = [];
for (let i = 0; i < 3; i++) {
setTimeout(() => {
animate(stars[i]);
setInterval(() => animate(stars[i]), 1000);
}, index++ * (interval / 3))
}
</script>
<!-- is this if excessive? -->
<div class="outer">
{#if user !== undefined}
<main>
<!-- <img class="icon" src="img/default_user_icon.png" alt="default user icon"> -->
<!-- <img class="icon" src="{user.image_url}" alt="default user icon"> -->
<img class="avatar" src="{avatar}" alt="default user icon">
<div class="username">{user.username}</div>
<div class="rank">Rank:
<span class="glitter">
<span bind:this={stars[0]} class="glitter-star">
<svg viewBox="0 0 512 512">
<path d="M512 255.1c0 11.34-7.406 20.86-18.44 23.64l-171.3 42.78l-42.78 171.1C276.7 504.6 267.2 512 255.9 512s-20.84-7.406-23.62-18.44l-42.66-171.2L18.47 279.6C7.406 276.8 0 267.3 0 255.1c0-11.34 7.406-20.83 18.44-23.61l171.2-42.78l42.78-171.1C235.2 7.406 244.7 0 256 0s20.84 7.406 23.62 18.44l42.78 171.2l171.2 42.78C504.6 235.2 512 244.6 512 255.1z" />
</svg>
</span>
<span bind:this={stars[1]} class="glitter-star">
<svg viewBox="0 0 512 512">
<path d="M512 255.1c0 11.34-7.406 20.86-18.44 23.64l-171.3 42.78l-42.78 171.1C276.7 504.6 267.2 512 255.9 512s-20.84-7.406-23.62-18.44l-42.66-171.2L18.47 279.6C7.406 276.8 0 267.3 0 255.1c0-11.34 7.406-20.83 18.44-23.61l171.2-42.78l42.78-171.1C235.2 7.406 244.7 0 256 0s20.84 7.406 23.62 18.44l42.78 171.2l171.2 42.78C504.6 235.2 512 244.6 512 255.1z" />
</svg>
</span>
<span bind:this={stars[2]} class="glitter-star">
<svg viewBox="0 0 512 512">
<path d="M512 255.1c0 11.34-7.406 20.86-18.44 23.64l-171.3 42.78l-42.78 171.1C276.7 504.6 267.2 512 255.9 512s-20.84-7.406-23.62-18.44l-42.66-171.2L18.47 279.6C7.406 276.8 0 267.3 0 255.1c0-11.34 7.406-20.83 18.44-23.61l171.2-42.78l42.78-171.1C235.2 7.406 244.7 0 256 0s20.84 7.406 23.62 18.44l42.78 171.2l171.2 42.78C504.6 235.2 512 244.6 512 255.1z" />
</svg>
</span>
<span class="glitter-text">{rank}</span>
</span>
</div>
<section class="main-stats">
<h4>Match Statistics</h4>
<p>Total: {user.stats.totalGame}</p>
<p>Victories: {user.stats.winGame}</p>
<p>Losses: {user.stats.loseGame}</p>
<p>Draws: {user.stats.drawGame}</p>
</section>
</main>
{/if}
</div>
<div>testing when there's tons of stuff</div>
<div>testing when there's tons of stuff</div>
<div>testing when there's tons of stuff</div>
<div>testing when there's tons of stuff</div>
<div>testing when there's tons of stuff</div>
<div>testing when there's tons of stuff</div>
<div>testing when there's tons of stuff</div>
<div>testing when there's tons of stuff</div>
<div>testing when there's tons of stuff</div>
<div>testing when there's tons of stuff</div>
<div>testing when there's tons of stuff</div>
<div>testing when there's tons of stuff</div>
<div>testing when there's tons of stuff</div>
<div>testing when there's tons of stuff</div>
<div>testing when there's tons of stuff</div>
<div>testing when there's tons of stuff</div>
<div>testing when there's tons of stuff</div>
<div>testing when there's tons of stuff</div>
<div>testing when there's tons of stuff</div>
<div>testing when there's tons of stuff</div>
<div>testing when there's tons of stuff</div>
<div>testing when there's tons of stuff</div>
<div>testing when there's tons of stuff</div>
<div>testing when there's tons of stuff</div>
<div>testing when there's tons of stuff</div>
<div>testing when there's tons of stuff</div>
<div>testing when there's tons of stuff</div>
<div>testing when there's tons of stuff</div>
<div>testing when there's tons of stuff</div>
<div>testing when there's tons of stuff</div>
<style>
div.outer{
max-width: 960px;
margin: 40px auto;
}
/* The main part */
main{
max-width: 960px;
margin: 40px auto;
text-align: center;
}
/* Normal CSS stuff */
.avatar{
max-width: 150px;
/* padding: 5px; */
}
/* The variable rich section */
section.main-stats{
max-width: 600px;
margin: 40px auto;
text-align: center;
/* i think i want to use a grid? */
display: grid;
grid-template-columns: repeat(3, 1fr);
/* not sure about this, maybe top should be larger? */
grid-template-rows: repeat(3, 1fr);
}
/* the stuff in the grid*/
section.main-stats h4{
grid-column: 1 / span 3;
}
div.username{
font-size: 1.5em;
font-weight: bold;
padding-bottom: 5px;
}
div.rank {
/* color: black; */
font-size: 1.2em;
font-weight: bold;
}
/* Glittery Star Stuff */
:root {
--purple: rgb(123, 31, 162);
--violet: rgb(103, 58, 183);
--pink: rgb(244, 143, 177);
/* make shit gold? */
}
@keyframes background-pan {
from {
background-position: 0% center;
}
to {
background-position: -200% center;
}
}
@keyframes scale {
from, to {
transform: scale(0);
}
50% {
transform: scale(1);
}
}
@keyframes rotate {
from {
transform: rotate(0deg);
}
to {
transform: rotate(180deg);
}
}
div > .glitter {
display: inline-block;
position: relative;
}
div > .glitter > .glitter-star {
--size: clamp(20px, 1.5vw, 30px);
animation: scale 700ms ease forwards;
display: block;
height: var(--size);
left: var(--star-left);
position: absolute;
top: var(--star-top);
width: var(--size);
}
div > .glitter > .glitter-star > svg {
animation: rotate 1000ms linear infinite;
display: block;
opacity: 0.7;
}
div > .glitter > .glitter-star > svg > path {
fill: var(--violet);
}
div > .glitter > .glitter-text {
animation: background-pan 3s linear infinite;
/* background-image: linear-gradient( */
background: linear-gradient(
to right,
var(--purple),
var(--violet),
var(--pink),
var(--purple)
);
background-size: 200%;
/* Keep these for Safari and chrome */
-webkit-background-clip: text;
-webkit-text-fill-color: transparent;
/* These are for Firefox */
background-clip: text;
color: transparent;
white-space: nowrap;
}
</style>

View File

@@ -1,129 +1,32 @@
<script lang="ts">
import { onMount } from 'svelte';
import { location } from 'svelte-spa-router';
// this is how you access /:first for example
// export let params = {}
// <p>Your name is: <b>{params.first}</b> <b>{#if params.last}{params.last}{/if}</b></p>
// If i export these vars, maybe as an nice tidy object, i could pass whatever i like to them
// The current user, some other user, whatever, and thus reuse this Componente for the user and their friends or whatever
// will have to coordinate with Back, will know more once the Game stats are in the back
// wait maybe this won't work, cuz like it's still going through a route, i would have to update a Store Var each time...
// not sure if that's what i want...
// maybe the rank is determined dynamically just in the front based on win loss ratio or something no one cares about
// why bother storing that shit in the back...
// maybe i need a Rank.svelte component
// ohhh i could make above a certain rank glitter! like that CSS tutorial showed me!
import GenerateUserDisplay from '../../pieces/GenerateUserDisplay.svelte';
let user;
let rank = '';
let avatar;
// i think i don't need to do this once i sort out the {wrap} conditions: in theory i could pass values to the Route
// once the async authentication check is done
onMount( async() => {
// console.log('mounting profile display')
user = await fetch('http://transcendance:8080/api/v2/user')
.then( (x) => x.json() );
// console.log('profile display did my fetch')
// should i be updating the userStore or is that unnecessary?
if (user.loseGame > user.winGame) {
rank = 'Bitch Ass Loser!'
} else if (user.loseGame === user.winGame) {
rank = 'Fine i guess...'
} else {
rank = 'Yea you da Boss!'
}
await fetch("http://transcendance:8080/api/v2/user/avatar", {method: "GET"})
.then(response => {return response.blob()})
.then(data => {
const url = URL.createObjectURL(data);
avatar = url;
});
// tmp
// console.log('mounted Profile Display')
// console.log(user);
})
// Glittery Stars and such for Rank
let index = 0, interval = 1000;
const rand = (min, max) =>
Math.floor(Math.random() * (max - min + 1)) + min;
// it's unhappy that "star" isn't typeset, no idea what to do about it...
const animate = (star) => {
// the if seems to have fixed the type issue
if (star) {
star.style.setProperty("--star-left", `${rand(-10, 100)}%`);
star.style.setProperty("--star-top", `${rand(-40, 80)}%`);
star.style.animation = "none";
star.offsetHeight;
star.style.animation = "";
}
}
// This is the part i invented, it was kinda a fucking nightmare...
let stars = [];
for (let i = 0; i < 3; i++) {
setTimeout(() => {
animate(stars[i]);
setInterval(() => animate(stars[i]), 1000);
}, index++ * (interval / 3))
}
</script>
<!-- is this if excessive? -->
{#if user !== undefined}
<main>
<!-- <img class="icon" src="img/default_user_icon.png" alt="default user icon"> -->
<!-- <img class="icon" src="{user.image_url}" alt="default user icon"> -->
<img class="avatar" src="{avatar}" alt="default user icon">
<div class="username">{user.username}</div>
<div class="rank">Rank:
<span class="glitter">
<span bind:this={stars[0]} class="glitter-star">
<svg viewBox="0 0 512 512">
<path d="M512 255.1c0 11.34-7.406 20.86-18.44 23.64l-171.3 42.78l-42.78 171.1C276.7 504.6 267.2 512 255.9 512s-20.84-7.406-23.62-18.44l-42.66-171.2L18.47 279.6C7.406 276.8 0 267.3 0 255.1c0-11.34 7.406-20.83 18.44-23.61l171.2-42.78l42.78-171.1C235.2 7.406 244.7 0 256 0s20.84 7.406 23.62 18.44l42.78 171.2l171.2 42.78C504.6 235.2 512 244.6 512 255.1z" />
</svg>
</span>
<span bind:this={stars[1]} class="glitter-star">
<svg viewBox="0 0 512 512">
<path d="M512 255.1c0 11.34-7.406 20.86-18.44 23.64l-171.3 42.78l-42.78 171.1C276.7 504.6 267.2 512 255.9 512s-20.84-7.406-23.62-18.44l-42.66-171.2L18.47 279.6C7.406 276.8 0 267.3 0 255.1c0-11.34 7.406-20.83 18.44-23.61l171.2-42.78l42.78-171.1C235.2 7.406 244.7 0 256 0s20.84 7.406 23.62 18.44l42.78 171.2l171.2 42.78C504.6 235.2 512 244.6 512 255.1z" />
</svg>
</span>
<span bind:this={stars[2]} class="glitter-star">
<svg viewBox="0 0 512 512">
<path d="M512 255.1c0 11.34-7.406 20.86-18.44 23.64l-171.3 42.78l-42.78 171.1C276.7 504.6 267.2 512 255.9 512s-20.84-7.406-23.62-18.44l-42.66-171.2L18.47 279.6C7.406 276.8 0 267.3 0 255.1c0-11.34 7.406-20.83 18.44-23.61l171.2-42.78l42.78-171.1C235.2 7.406 244.7 0 256 0s20.84 7.406 23.62 18.44l42.78 171.2l171.2 42.78C504.6 235.2 512 244.6 512 255.1z" />
</svg>
</span>
<span class="glitter-text">{rank}</span>
</span>
</div>
<section class="main-stats">
<h4>Match Statistics</h4>
<p>Total: {user.stats.totalGame}</p>
<p>Victories: {user.stats.winGame}</p>
<p>Losses: {user.stats.loseGame}</p>
<p>Draws: {user.stats.drawGame}</p>
</section>
</main>
{/if}
<div class="outer">
<!-- OHHHH i could use #await instead of if and have an nice loading page! -->
{#if user !== undefined}
<GenerateUserDisplay {user} primary={true}/>
{:else}
<!-- might be unnecessary since you can't access the page without fetching the user -->
<h2>Sorry</h2>
<div>Failed to load current</div>
{/if}
</div>
<div>testing when there's tons of stuff</div>
<div>testing when there's tons of stuff</div>
@@ -161,6 +64,11 @@
<style>
div.outer{
max-width: 960px;
margin: 40px auto;
}
/* The main part */
main{
max-width: 960px;

View File

@@ -2,6 +2,26 @@
import { onMount } from "svelte";
import Button from "../../pieces/Button.svelte";
import DisplayAUser from "../../pieces/DisplayAUser.svelte";
// Ok so i need to test all the paths Cherif has made but a major one doesn't work yet...
// in the mean time, i need to make some other stuff look nice
// what do i want?
/*
Ideas
- a list of all users and if they're active
could be a list of friends and if they're active but i can't see that yet
- I click on a thing and it lets me see all the users and i get a button that lets me add them
- would that be like a serachable list of all users?
- am i skipping optimization? i mean for now yes, but like
*/
let errors = {friendRequest: '',};
let set = {friendUsername: '', friendId: Number}
@@ -9,8 +29,9 @@
let user;
let myFriends;
let requestsMade, requestsRecieved;
// http://transcendance:8080/api/v2/network/received the ones you have recieved
// http://transcendance:8080/api/v2/network/pending the ones you have sent
let allUsers;
let allFriends;
let userToDisplay;
onMount( async() => {
@@ -42,16 +63,23 @@
console.log('Requests received ');
console.log(requestsRecieved);
allUsers = await fetch('http://transcendance:8080/api/v2/user/all')
.then( x => x.json() );
console.log('got all users ' + allUsers)
allFriends = await fetch('http://transcendance:8080/api/v2/network/myfriends')
.then( x => x.json() );
console.log('got all friends ' + allFriends)
})
let allUsers;
const displayAllUsers = async() => {
allUsers = await fetch('http://transcendance:8080/api/v2/user/all')
.then( x => x.json() );
console.log('got all users ' + allUsers)
};
let allFriends;
const displayAllFriends = async() => {
allFriends = await fetch('http://transcendance:8080/api/v2/network/myfriends')
.then( x => x.json() );
@@ -112,78 +140,140 @@
.then (x => console.log({...x}));
// should i then update requtestsMade with another fetch?
// maybe also check if the request went through?
}
// body: JSON.stringify({
// "requesterUsername": user.username,
// "addresseeUsername": set.friendUsername,
// "status": r
// "requesterId": user.username,
// "addresseeId": set.friendUsername,
};
</script>
<h1>Friendship page</h1>
{#if user && user.username}
<div>You are {user.username}</div>
{/if}
<!-- svelte-ignore a11y-click-events-have-key-events -->
<div class="top-grid">
<!-- <div>My friends obj</div> -->
<!-- <div>{myFriends}</div> -->
<!-- <br> -->
<Button on:click={displayAllUsers}>Get All Users</Button>
{#if allUsers !== undefined}
{#each allUsers as user}
<div>{user.username}</div>
{/each}
{/if}
<div class="all-users-sidebar">
<h3>All Users</h3>
{#if allUsers === undefined}
<div class="error">Failed to load all users</div>
{:else}
<!-- problem, i can't use user.id since Cherif doesn't want to expost that to the front...
is there something else i could use? -->
{#each allUsers as aUser }
<!-- <div class="a-user" on:click={() => displayAUser(aUser.username)}>{aUser.username}</div> -->
<div class="a-user" on:click={() => userToDisplay = aUser.username}>{aUser.username}</div>
<!-- i could make an indicator component? like green for connected or something?
i could use words but color them?
i could make it so if they're in a game -->
<div class="status a-user">{aUser.status}</div>
<br>
{/each}
{/if}
<br>
<Button on:click={displayAllFriends}>Get All Friends</Button>
{#if allFriends !== undefined}
<div>{allFriends}</div>
{#each allFriends as friend}
<div>{friend}{friend.username}</div>
{/each}
{/if}
<br>
<div>Make a Friend!</div>
<form on:submit|preventDefault={() => friendUserByUsername(set.friendUsername)}>
<input type="text" placeholder="friend's username" bind:value={set.friendUsername}>
<div class="error">{errors.friendRequest}</div>
<Button type="secondary">Send Friend Request</Button>
</form>
<br> <br>
<!-- here i want to list all the requests you and have an accept and a decline button -->
<!-- {#each requestsRecieved as request} -->
<br> <br>
<!-- I want to list all the requests made by this user -->
<Button on:click={displayRequestsMade}>Display Requests Made</Button>
{#if requestsMade !== undefined}
{#each requestsMade as requestMade}
<div>{requestMade}</div>
{/each}
{/if}
</div>
<!-- <h1>Friendship page</h1> -->
<div class="main-display">
<h1>Main Display</h1>
<!-- use an #await here too? -->
<!-- you can do better, like an on load sort of thing -->
{#if userToDisplay !== undefined}
<DisplayAUser aUsername={userToDisplay}/>
{/if}
<!-- {#if user && user.username}
<div>You are {user.username}</div>
{/if} -->
<!-- <Button on:click={displayAllUsers}>Get All Users</Button>
{#if allUsers !== undefined}
{#each allUsers as user}
<div>{user.username}</div>
{/each}
{/if}
<br> -->
<!-- <Button on:click={displayAllFriends}>Get All Friends</Button>
{#if allFriends !== undefined}
<div>{allFriends}</div>
{#each allFriends as friend}
<div>{friend}{friend.username}</div>
{/each}
{/if} -->
<!-- <br>
<div>Make a Friend!</div>
<form on:submit|preventDefault={() => friendUserByUsername(set.friendUsername)}>
<input type="text" placeholder="friend's username" bind:value={set.friendUsername}>
<div class="error">{errors.friendRequest}</div>
<Button type="secondary">Send Friend Request</Button>
</form> -->
<!-- <br> <br> -->
<!-- here i want to list all the requests you and have an accept and a decline button -->
<!-- {#each requestsRecieved as request} -->
<!-- <br> <br> -->
<!-- I want to list all the requests made by this user -->
<!-- <Button on:click={displayRequestsMade}>Display Requests Made</Button>
{#if requestsMade !== undefined}
{#each requestsMade as requestMade}
<div>{requestMade}</div>
{/each}
{/if} -->
</div>
</div>
<style>
/* ok so i want a 12 column grid with a sidebar */
div.top-grid{
display: grid;
grid-template-columns: repeat(12, 1fr);
/* max-height: calc(100vh - 30vh); */
height: 85vh;
/* margin: 0; */
}
div.all-users-sidebar{
grid-column: 1 / span 2;
background: white;
}
div.a-user{
/* yea i mean that seems fine... */
display: inline-block;
/* somehting about the buttons too, smaller ? */
}
div.status{
font-size: 0.6em;
font-weight: bold;
}
/* selector attributes to get only divs with .a-user */
/* you gotta be careful with Svelte cuz it tacks classes on to the end of basically all elems! */
div[class^="a-user"]:hover{
text-decoration: underline;
font-weight: bold;
cursor: pointer;
}
div.main-display{
grid-column: 3 / span 10;
}
.error{
font-size: 0.8em;
font-weight: bold;

View File

@@ -28,10 +28,11 @@
<style>
div {
/* this doesn't work, fucks up all my sub routes */
/* div {
max-width: 960px;
margin: 40px auto;
}
} */

View File

@@ -0,0 +1,33 @@
<script lang="ts">
import { onMount } from 'svelte';
import GenerateUserDisplay from './GenerateUserDisplay.svelte';
export let aUsername;
let user;
onMount( async() => {
console.log('Display aUser username: '+ aUsername)
// http://transcendance:8080/api/v2/user?username=NomDuUserATrouver
user = await fetch(`http://transcendance:8080/api/v2/user?username=${aUsername}`)
.then( (x) => x.json() );
console.log('Display a user: ' + user.username)
})
</script>
<!-- OHHHH i could use #await instead of if and have an nice loading page! -->
{#if user !== undefined}
<GenerateUserDisplay {user} primary={true}/>
{:else}
<h2>Sorry</h2>
<div>Failed to load user {aUsername}</div>
{/if}
<style>
</style>

View File

@@ -0,0 +1,251 @@
<script lang="ts">
import { onMount } from 'svelte';
export let user;
export let primary;
let rank = '';
let avatar;
onMount( async() => {
// using this for now cuz for some reason there is yet to be a way to fet another person's avatar
if (primary) {
await fetch("http://transcendance:8080/api/v2/user/avatar", {method: "GET"})
.then(response => {return response.blob()})
.then(data => {
const url = URL.createObjectURL(data);
avatar = url;
});
}
// tmp
// console.log('mounted Profile Display')
// console.log(user);
})
if (user.loseGame > user.winGame) {
rank = 'Bitch Ass Loser!'
} else if (user.loseGame === user.winGame) {
rank = 'Fine i guess...'
} else {
rank = 'Yea you da Boss!'
}
// Glittery Stars and such for Rank
let index = 0, interval = 1000;
const rand = (min, max) =>
Math.floor(Math.random() * (max - min + 1)) + min;
// it's unhappy that "star" isn't typeset, no idea what to do about it...
const animate = (star) => {
// the if seems to have fixed the type issue
if (star) {
star.style.setProperty("--star-left", `${rand(-10, 100)}%`);
star.style.setProperty("--star-top", `${rand(-40, 80)}%`);
star.style.animation = "none";
star.offsetHeight;
star.style.animation = "";
}
}
// This is the part i invented, it was kinda a fucking nightmare...
let stars = [];
for (let i = 0; i < 3; i++) {
setTimeout(() => {
animate(stars[i]);
setInterval(() => animate(stars[i]), 1000);
}, index++ * (interval / 3))
}
</script>
<!-- is this if excessive? -->
<div class="outer">
{#if user !== undefined}
<main>
<!-- <img class="icon" src="img/default_user_icon.png" alt="default user icon"> -->
<!-- <img class="icon" src="{user.image_url}" alt="default user icon"> -->
<img class="avatar" src="{avatar}" alt="default user icon">
<div class="username">{user.username}</div>
<div class="rank">Rank:
<span class="glitter">
<span bind:this={stars[0]} class="glitter-star">
<svg viewBox="0 0 512 512">
<path d="M512 255.1c0 11.34-7.406 20.86-18.44 23.64l-171.3 42.78l-42.78 171.1C276.7 504.6 267.2 512 255.9 512s-20.84-7.406-23.62-18.44l-42.66-171.2L18.47 279.6C7.406 276.8 0 267.3 0 255.1c0-11.34 7.406-20.83 18.44-23.61l171.2-42.78l42.78-171.1C235.2 7.406 244.7 0 256 0s20.84 7.406 23.62 18.44l42.78 171.2l171.2 42.78C504.6 235.2 512 244.6 512 255.1z" />
</svg>
</span>
<span bind:this={stars[1]} class="glitter-star">
<svg viewBox="0 0 512 512">
<path d="M512 255.1c0 11.34-7.406 20.86-18.44 23.64l-171.3 42.78l-42.78 171.1C276.7 504.6 267.2 512 255.9 512s-20.84-7.406-23.62-18.44l-42.66-171.2L18.47 279.6C7.406 276.8 0 267.3 0 255.1c0-11.34 7.406-20.83 18.44-23.61l171.2-42.78l42.78-171.1C235.2 7.406 244.7 0 256 0s20.84 7.406 23.62 18.44l42.78 171.2l171.2 42.78C504.6 235.2 512 244.6 512 255.1z" />
</svg>
</span>
<span bind:this={stars[2]} class="glitter-star">
<svg viewBox="0 0 512 512">
<path d="M512 255.1c0 11.34-7.406 20.86-18.44 23.64l-171.3 42.78l-42.78 171.1C276.7 504.6 267.2 512 255.9 512s-20.84-7.406-23.62-18.44l-42.66-171.2L18.47 279.6C7.406 276.8 0 267.3 0 255.1c0-11.34 7.406-20.83 18.44-23.61l171.2-42.78l42.78-171.1C235.2 7.406 244.7 0 256 0s20.84 7.406 23.62 18.44l42.78 171.2l171.2 42.78C504.6 235.2 512 244.6 512 255.1z" />
</svg>
</span>
<span class="glitter-text">{rank}</span>
</span>
</div>
<section class="main-stats">
<h4>Match Statistics</h4>
<p>Total: {user.stats.totalGame}</p>
<p>Victories: {user.stats.winGame}</p>
<p>Losses: {user.stats.loseGame}</p>
<p>Draws: {user.stats.drawGame}</p>
</section>
</main>
{/if}
</div>
<style>
div.outer{
max-width: 960px;
margin: 40px auto;
}
/* The main part */
main{
max-width: 960px;
margin: 40px auto;
text-align: center;
}
/* Normal CSS stuff */
.avatar{
max-width: 150px;
/* padding: 5px; */
}
/* The variable rich section */
section.main-stats{
max-width: 600px;
margin: 40px auto;
text-align: center;
/* i think i want to use a grid? */
display: grid;
grid-template-columns: repeat(3, 1fr);
/* not sure about this, maybe top should be larger? */
grid-template-rows: repeat(3, 1fr);
}
/* the stuff in the grid*/
section.main-stats h4{
grid-column: 1 / span 3;
}
div.username{
font-size: 1.5em;
font-weight: bold;
padding-bottom: 5px;
}
div.rank {
/* color: black; */
font-size: 1.2em;
font-weight: bold;
}
/* Glittery Star Stuff */
:root {
--purple: rgb(123, 31, 162);
--violet: rgb(103, 58, 183);
--pink: rgb(244, 143, 177);
/* make shit gold? */
}
@keyframes background-pan {
from {
background-position: 0% center;
}
to {
background-position: -200% center;
}
}
@keyframes scale {
from, to {
transform: scale(0);
}
50% {
transform: scale(1);
}
}
@keyframes rotate {
from {
transform: rotate(0deg);
}
to {
transform: rotate(180deg);
}
}
div > .glitter {
display: inline-block;
position: relative;
}
div > .glitter > .glitter-star {
--size: clamp(20px, 1.5vw, 30px);
animation: scale 700ms ease forwards;
display: block;
height: var(--size);
left: var(--star-left);
position: absolute;
top: var(--star-top);
width: var(--size);
}
div > .glitter > .glitter-star > svg {
animation: rotate 1000ms linear infinite;
display: block;
opacity: 0.7;
}
div > .glitter > .glitter-star > svg > path {
fill: var(--violet);
}
div > .glitter > .glitter-text {
animation: background-pan 3s linear infinite;
/* background-image: linear-gradient( */
background: linear-gradient(
to right,
var(--purple),
var(--violet),
var(--pink),
var(--purple)
);
background-size: 200%;
/* Keep these for Safari and chrome */
-webkit-background-clip: text;
-webkit-text-fill-color: transparent;
/* These are for Firefox */
background-clip: text;
color: transparent;
white-space: nowrap;
}
</style>