userpage init
This commit is contained in:
parent
6066c31319
commit
ef4a98cfd2
7 changed files with 1408 additions and 253 deletions
340
pages/api/fakePrices.ts
Normal file
340
pages/api/fakePrices.ts
Normal file
|
@ -0,0 +1,340 @@
|
|||
import type { NextApiRequest, NextApiResponse } from "next";
|
||||
|
||||
type Data = {
|
||||
[key: string]: any;
|
||||
};
|
||||
|
||||
export default async function handler(
|
||||
req: NextApiRequest,
|
||||
res: NextApiResponse<Data>
|
||||
) {
|
||||
const emote = req.query.emote ? (req.query.emote as string) : undefined;
|
||||
if (!emote) {
|
||||
res.status(200).json({ data: fakePrices });
|
||||
return;
|
||||
}
|
||||
res.status(200).json({ data: fakePrices[emote] });
|
||||
}
|
||||
|
||||
const fakePrices: { [key: string]: number } = {
|
||||
"3Head": 521,
|
||||
"4Health": 801,
|
||||
":3": 104,
|
||||
":(": 799,
|
||||
AAAA: 717,
|
||||
AAAAUUUUUUGHHHHHHH: 342,
|
||||
AINTNAURWAY: 195,
|
||||
AREYOUAFEMBOY: 135,
|
||||
AREYOUAGIRL: 494,
|
||||
AYAYAjam: 907,
|
||||
Adge: 646,
|
||||
AlienPls3: 460,
|
||||
Amonge: 608,
|
||||
AngelThump: 195,
|
||||
AnnyLebronJam: 967,
|
||||
Aware: 571,
|
||||
BAND: 472,
|
||||
BASED: 794,
|
||||
BEGGING: 365,
|
||||
BLUBBERS: 211,
|
||||
BLUBBERSWTF: 713,
|
||||
BOOBEST: 107,
|
||||
BOTHA: 472,
|
||||
BRUHgers: 536,
|
||||
Baby: 927,
|
||||
Binoculars: 441,
|
||||
Blindge: 426,
|
||||
BocchiPossessed: 545,
|
||||
Bruhgi: 779,
|
||||
CEASE: 708,
|
||||
COCKA: 656,
|
||||
CapybaraStare: 295,
|
||||
CatChest: 267,
|
||||
ChadMeeting: 454,
|
||||
Chatting: 330,
|
||||
ChugU: 661,
|
||||
Clueless: 888,
|
||||
Coldge: 314,
|
||||
Comfi: 187,
|
||||
Copege: 841,
|
||||
Corpa: 536,
|
||||
CumTime: 199,
|
||||
DIESOFAYAYA: 657,
|
||||
DIESOFCRINGE: 320,
|
||||
DONUT: 57,
|
||||
Danki: 864,
|
||||
Deadge: 322,
|
||||
Despairge: 437,
|
||||
Deutschge: 626,
|
||||
EDM: 572,
|
||||
FLASHBANG: 308,
|
||||
FeelsWeakMan: 88,
|
||||
Fishinge: 956,
|
||||
Flushed: 290,
|
||||
FluteTime: 557,
|
||||
GOODONE: 804,
|
||||
GachiPls: 415,
|
||||
Gambage: 876,
|
||||
Gayge: 434,
|
||||
GetOutOfMyHead: 338,
|
||||
GoodGirl: 761,
|
||||
GroupWankge: 540,
|
||||
GuysRefreshChatterinoIUploadedAnotherEmote: 677,
|
||||
HACKERMANS: 85,
|
||||
HUH: 582,
|
||||
HYPERS: 142,
|
||||
Homi: 745,
|
||||
HopOnBlueArchive: 386,
|
||||
IDC: 277,
|
||||
ILOST: 894,
|
||||
JIGACHAD: 865,
|
||||
Jamgie: 156,
|
||||
Jammies: 308,
|
||||
Joel: 586,
|
||||
KEKW: 356,
|
||||
KKool: 821,
|
||||
KoroneOkite: 90,
|
||||
LETHIMCOOK: 940,
|
||||
LICKA: 866,
|
||||
LUBBERS: 808,
|
||||
LULE: 244,
|
||||
Lagging: 314,
|
||||
LickAnnyThighs: 66,
|
||||
Life: 894,
|
||||
LoveForever: 21,
|
||||
MODS: 180,
|
||||
MYHEART: 122,
|
||||
MaN: 181,
|
||||
MadgeJuice: 926,
|
||||
MadgeTime: 481,
|
||||
Madgeclap: 534,
|
||||
Malding: 940,
|
||||
Maxwell: 656,
|
||||
MyHonestReaction: 314,
|
||||
NAUR: 93,
|
||||
NGOthis: 454,
|
||||
NOBOOBS: 855,
|
||||
NODDERS: 836,
|
||||
NOTED: 293,
|
||||
Naruga: 572,
|
||||
Naruge: 872,
|
||||
Nerdge: 46,
|
||||
NessieTwerk: 666,
|
||||
OFFLINECHAT: 780,
|
||||
OMEGA: 934,
|
||||
OMG: 631,
|
||||
"OhTheMiseryEverybodyWantsToBeMyEnemySpareTheSympathyEverybodyWantsToBeMyEnemy-y-y-y-y": 798,
|
||||
Okayeg: 485,
|
||||
OkaygeBusiness: 493,
|
||||
Oldge: 763,
|
||||
OrangexddRun: 96,
|
||||
PEPELEPSY: 122,
|
||||
PLEASE: 607,
|
||||
PagMan: 775,
|
||||
PantsGrab: 503,
|
||||
Party: 181,
|
||||
PeepoKittyHug: 360,
|
||||
PensiveWobble: 843,
|
||||
PepeClown: 384,
|
||||
PepeNPC: 131,
|
||||
Pepepains: 105,
|
||||
PepoG: 987,
|
||||
PogOanny: 14,
|
||||
PogTasty: 211,
|
||||
PogU: 245,
|
||||
Pogpega: 902,
|
||||
PokiShare: 274,
|
||||
Poorge: 789,
|
||||
PoroRoast: 199,
|
||||
Programming: 161,
|
||||
RAGEY: 322,
|
||||
RAVE: 67,
|
||||
RESETTING: 749,
|
||||
RIDING: 364,
|
||||
RIPBOZO: 638,
|
||||
Ratge: 981,
|
||||
SCHIZO: 457,
|
||||
SHITUP: 643,
|
||||
SNIFFA: 220,
|
||||
SPEED: 956,
|
||||
SadCat: 747,
|
||||
Sadeg: 313,
|
||||
SadgeCry: 869,
|
||||
SaguiPls: 363,
|
||||
Siti: 396,
|
||||
Smadge: 222,
|
||||
SmugCat: 447,
|
||||
SnowTime: 545,
|
||||
SoCute: 317,
|
||||
Spoopy: 281,
|
||||
Suske: 642,
|
||||
THESE: 401,
|
||||
THIS: 311,
|
||||
Tasty: 530,
|
||||
ThisStream: 497,
|
||||
TouchGrass: 608,
|
||||
TurtleRush: 608,
|
||||
UOHHH: 426,
|
||||
VIBE: 939,
|
||||
VIBEOFF: 36,
|
||||
VaN: 479,
|
||||
VeryBased: 456,
|
||||
ViolinTime: 406,
|
||||
WHAT: 941,
|
||||
WHOMEGALUL: 804,
|
||||
WakuWaku: 221,
|
||||
WeebRun: 582,
|
||||
WhoAsked: 459,
|
||||
Wickedgi: 870,
|
||||
Wigglecat: 649,
|
||||
Wokege: 377,
|
||||
YourMom: 939,
|
||||
amongnnE: 142,
|
||||
annE: 552,
|
||||
annie: 292,
|
||||
annyBlob: 471,
|
||||
annyBop: 749,
|
||||
annyCD: 673,
|
||||
annyCucumber: 689,
|
||||
annyDespair: 736,
|
||||
annyExcitedHug: 926,
|
||||
annyGAMBA: 885,
|
||||
annyGasm: 49,
|
||||
annyGlare: 462,
|
||||
annyHappy: 960,
|
||||
annyHug: 979,
|
||||
annyJam: 544,
|
||||
annyLava: 288,
|
||||
annyNODDERS: 730,
|
||||
annyNOW: 68,
|
||||
annyOffline: 241,
|
||||
annyPadoru: 453,
|
||||
annyPag: 377,
|
||||
annyPoggies: 729,
|
||||
annyPooPoo: 295,
|
||||
annySCHIZO: 766,
|
||||
annySmile: 467,
|
||||
annySussy: 695,
|
||||
annySwipe: 992,
|
||||
annyTalk: 951,
|
||||
annyThighs: 458,
|
||||
annyVibe: 914,
|
||||
annykiss: 308,
|
||||
annysilly: 996,
|
||||
annystare: 34,
|
||||
annytfCum: 27,
|
||||
anyaPls: 322,
|
||||
anyatf: 58,
|
||||
baseg: 551,
|
||||
borpaSpin: 793,
|
||||
burh: 716,
|
||||
catKISS: 88,
|
||||
catRAVE: 912,
|
||||
catbaby: 673,
|
||||
chatlookwhatannytaughtme: 515,
|
||||
danse: 213,
|
||||
deadass: 815,
|
||||
degen: 551,
|
||||
dejj: 843,
|
||||
donowall: 660,
|
||||
dvaAss: 871,
|
||||
elmoFire: 117,
|
||||
ewLeague: 240,
|
||||
ewOverwatch: 397,
|
||||
forsen: 482,
|
||||
forsenGa: 327,
|
||||
forsenGaPick: 149,
|
||||
forsenLaughingAtYou: 292,
|
||||
frenn: 575,
|
||||
golive: 103,
|
||||
guraFukkireta: 767,
|
||||
guraWiggle: 132,
|
||||
guraWink: 891,
|
||||
happ: 525,
|
||||
heCrazy: 437,
|
||||
hiThere: 54,
|
||||
hmmMeeting: 749,
|
||||
iAsked: 203,
|
||||
jupijej: 207,
|
||||
kiss0: 738,
|
||||
kok: 313,
|
||||
koklick: 990,
|
||||
koroneWink: 824,
|
||||
lebronJAM: 890,
|
||||
liccanny: 205,
|
||||
lobaPls: 436,
|
||||
majj: 813,
|
||||
meow: 757,
|
||||
monkaE: 376,
|
||||
monkaLaugh: 335,
|
||||
nekoNya: 948,
|
||||
nessieWalk: 672,
|
||||
nise: 658,
|
||||
nyanPls: 330,
|
||||
pL: 38,
|
||||
paapoHappy: 126,
|
||||
peepoCat: 673,
|
||||
peepoClap: 772,
|
||||
peepoFAT: 408,
|
||||
peepoFeet: 909,
|
||||
peepoFinger: 185,
|
||||
peepoFlower: 569,
|
||||
peepoFlute: 361,
|
||||
peepoHeadbang: 615,
|
||||
peepoHigh: 125,
|
||||
peepoLeaveToAnny: 711,
|
||||
peepoPag: 101,
|
||||
peepoPopcorn: 234,
|
||||
peepoRant: 628,
|
||||
peepoRiot: 874,
|
||||
peepoSnow: 90,
|
||||
peepoStuck: 188,
|
||||
peepoTalk: 452,
|
||||
pepeKneel: 87,
|
||||
pepePoint: 641,
|
||||
pepegaJAMMER: 603,
|
||||
plink: 892,
|
||||
poggcrazy: 319,
|
||||
pogs: 829,
|
||||
poroPls: 87,
|
||||
ppHop: 589,
|
||||
ppHopper: 843,
|
||||
ppPoof: 188,
|
||||
sadWankge: 300,
|
||||
sajj: 44,
|
||||
sitt: 450,
|
||||
soncic: 483,
|
||||
sonic: 464,
|
||||
squirrelJAM: 431,
|
||||
toffee1: 591,
|
||||
toffee2: 51,
|
||||
toffee3: 3,
|
||||
toffeeBlankies: 249,
|
||||
toffeeBop: 801,
|
||||
toffeeChat: 405,
|
||||
toffeeClap: 552,
|
||||
toffeeComfy: 383,
|
||||
toffeeConfused: 548,
|
||||
toffeeDinkDonk: 782,
|
||||
toffeePat: 235,
|
||||
toffeeTap: 815,
|
||||
vp: 113,
|
||||
wideVIBE: 972,
|
||||
wideannyBop: 866,
|
||||
widepeepoHappy: 969,
|
||||
widepeepoMASTURBATION77769420GANGSHITNOMOREFORTNITE19DOLLERFORTNITECARD: 846,
|
||||
xQchatting: 196,
|
||||
xdd666: 700,
|
||||
xddfdhjsd0f76ds5r26FDSFHD88hjdbsa67vr7xlLLhdsgfcxz632nkDFSGATVMVLN8CXFJJMVMMMM111111111111111111111: 866,
|
||||
xdding: 735,
|
||||
xqcCoomer: 397,
|
||||
xqcGoofy: 360,
|
||||
xqcRecord: 773,
|
||||
xqcTwerk: 531,
|
||||
yayAnny: 437,
|
||||
yoshiJAM: 137,
|
||||
zSpooky: 350,
|
||||
zyzzBass: 680,
|
||||
};
|
||||
|
||||
export { fakePrices };
|
|
@ -1,216 +0,0 @@
|
|||
import type { NextApiRequest, NextApiResponse } from "next";
|
||||
|
||||
type Data = {
|
||||
[key: string]: any;
|
||||
};
|
||||
|
||||
export default async function handler(
|
||||
req: NextApiRequest,
|
||||
res: NextApiResponse<Data>
|
||||
) {
|
||||
const sortBy = req.query.s ? (req.query.s as string) : undefined;
|
||||
const sortAsc = req.query.a ? (req.query.a as string) : undefined;
|
||||
|
||||
let data = fakeData;
|
||||
if (sortBy) {
|
||||
if (sortBy === "netWorth") {
|
||||
data = data.sort((a, b) => b.netWorth - a.netWorth);
|
||||
} else if (sortBy === "dailyChange") {
|
||||
data = data.sort((a, b) => b.dailyChange - a.dailyChange);
|
||||
} else if (sortBy === "dailyChangePercent") {
|
||||
data = data.sort((a, b) => b.dailyChangePercent - a.dailyChangePercent);
|
||||
} else if (sortBy === "shares") {
|
||||
data = data.sort((a, b) => b.shares - a.shares);
|
||||
} else if (sortBy === "points") {
|
||||
data = data.sort((a, b) => b.points - a.points);
|
||||
} else if (sortBy === "name") {
|
||||
data = data.sort((a, b) => a.name.localeCompare(b.name));
|
||||
}
|
||||
if (sortAsc === "true") {
|
||||
// slow but only needed for temporary fake data anyway
|
||||
data = data.reverse();
|
||||
}
|
||||
}
|
||||
// fake loading time
|
||||
await new Promise((resolve) =>
|
||||
setTimeout(resolve, 250 + Math.random() * 1000)
|
||||
);
|
||||
res.status(200).json({ data });
|
||||
}
|
||||
|
||||
interface fakeDataEntry {
|
||||
id: number;
|
||||
name: string;
|
||||
netWorth: number;
|
||||
points: number;
|
||||
shares: number;
|
||||
dailyChange: number;
|
||||
dailyChangePercent: number;
|
||||
}
|
||||
|
||||
const fakeData: fakeDataEntry[] = [
|
||||
{
|
||||
id: 4,
|
||||
name: "3zachm",
|
||||
netWorth: 10030, // stocks + points
|
||||
points: 70, /// uninvested points
|
||||
shares: 20,
|
||||
dailyChange: -500,
|
||||
dailyChangePercent: -0.0498504486540378863409770687936,
|
||||
},
|
||||
{
|
||||
id: 1,
|
||||
name: "ModulatingForce",
|
||||
netWorth: 142910,
|
||||
points: 10020,
|
||||
shares: 200,
|
||||
dailyChange: 5420,
|
||||
dailyChangePercent: 0.0379259673920649359736897347981,
|
||||
},
|
||||
{
|
||||
id: 2,
|
||||
name: "notohh",
|
||||
netWorth: 153495392,
|
||||
points: 10020,
|
||||
shares: 2432,
|
||||
dailyChange: 0,
|
||||
dailyChangePercent: 0,
|
||||
},
|
||||
{
|
||||
id: 3,
|
||||
name: "SecondSockSan",
|
||||
netWorth: 153495,
|
||||
points: 15020,
|
||||
shares: 20,
|
||||
dailyChange: -10432,
|
||||
dailyChangePercent: -0.06796312583471774324896576435715,
|
||||
},
|
||||
{
|
||||
id: 0,
|
||||
name: "e__n__t__e",
|
||||
netWorth: 429481824,
|
||||
points: 1002022,
|
||||
shares: 94214,
|
||||
dailyChange: 329444422,
|
||||
dailyChangePercent: 4.2932124926634939999741296760186,
|
||||
},
|
||||
{
|
||||
id: 5,
|
||||
name: "luckytohavefoundyou14252",
|
||||
netWorth: 8024,
|
||||
points: 423,
|
||||
shares: 4,
|
||||
dailyChange: 9,
|
||||
dailyChangePercent: 0.00112163509471585244267198404786,
|
||||
},
|
||||
{
|
||||
id: 6,
|
||||
name: "ZeroxZerich",
|
||||
netWorth: 842190,
|
||||
points: 88542,
|
||||
shares: 532,
|
||||
dailyChange: -10219,
|
||||
dailyChangePercent: -0.01213384153219582279533121979601,
|
||||
},
|
||||
{
|
||||
id: 7,
|
||||
name: "joeeyo",
|
||||
netWorth: 10000000,
|
||||
points: 9999979,
|
||||
shares: 1,
|
||||
dailyChange: 1,
|
||||
dailyChangePercent: 0.0000001,
|
||||
},
|
||||
{
|
||||
id: 8,
|
||||
name: "dd_maru",
|
||||
netWorth: 10328421,
|
||||
points: 328421,
|
||||
shares: 252,
|
||||
dailyChange: 85192,
|
||||
dailyChangePercent: 0.00824830823607984221402284047097,
|
||||
},
|
||||
{
|
||||
id: 9,
|
||||
name: "Goldeneye128",
|
||||
netWorth: 58292,
|
||||
points: 6521,
|
||||
shares: 63,
|
||||
dailyChange: -1942,
|
||||
dailyChangePercent: -0.03331503465312564331297605160228,
|
||||
},
|
||||
{
|
||||
id: 10,
|
||||
name: "lilpastatv",
|
||||
netWorth: 7328919,
|
||||
points: 40,
|
||||
shares: 93,
|
||||
dailyChange: 921821,
|
||||
dailyChangePercent: 0.12577857662228222197571019682439,
|
||||
},
|
||||
{
|
||||
id: 11,
|
||||
name: "domiswitch",
|
||||
netWorth: 43290,
|
||||
points: 5002,
|
||||
shares: 15,
|
||||
dailyChange: 2429,
|
||||
dailyChangePercent: 0.05610995610995610995610995610996,
|
||||
},
|
||||
{
|
||||
id: 12,
|
||||
name: "minosura",
|
||||
netWorth: 904328,
|
||||
points: 32901,
|
||||
shares: 83,
|
||||
dailyChange: 94821,
|
||||
dailyChangePercent: 0.10485244291894091524314186887943,
|
||||
},
|
||||
{
|
||||
id: 13,
|
||||
name: "scienceteam_member",
|
||||
netWorth: 34894,
|
||||
points: 958,
|
||||
shares: 5,
|
||||
dailyChange: -7964,
|
||||
dailyChangePercent: -0.22823408035765461110792686421734,
|
||||
},
|
||||
{
|
||||
id: 14,
|
||||
name: "witchdev",
|
||||
netWorth: 94382912,
|
||||
points: 8532,
|
||||
shares: 329,
|
||||
dailyChange: -421,
|
||||
dailyChangePercent: -0.0000044605531984433792422085896,
|
||||
},
|
||||
{
|
||||
id: 15,
|
||||
name: "justone123879",
|
||||
netWorth: 8889123,
|
||||
points: 86333,
|
||||
shares: 153,
|
||||
dailyChange: 53289,
|
||||
dailyChangePercent: 0.00599485461051669551653183334284,
|
||||
},
|
||||
{
|
||||
id: 16,
|
||||
name: "marcelr_",
|
||||
netWorth: 400329,
|
||||
points: 39291,
|
||||
shares: 52,
|
||||
dailyChange: 1329,
|
||||
dailyChangePercent: 0.00331976948959480827019776234047,
|
||||
},
|
||||
{
|
||||
id: 17,
|
||||
name: "fossabot",
|
||||
netWorth: 20005,
|
||||
points: 0,
|
||||
shares: 1,
|
||||
dailyChange: -31042,
|
||||
dailyChangePercent: -1.5517120719820044988752811797051,
|
||||
},
|
||||
];
|
||||
|
||||
export type { fakeDataEntry };
|
629
pages/api/fakeUsers.ts
Normal file
629
pages/api/fakeUsers.ts
Normal file
|
@ -0,0 +1,629 @@
|
|||
import type { NextApiRequest, NextApiResponse } from "next";
|
||||
import { createRedisInstance } from "../../misc/redis";
|
||||
import { getUserByName } from "../../misc/TwitchAPI";
|
||||
import { fakePrices } from "./fakePrices";
|
||||
|
||||
type Data = {
|
||||
[key: string]: any;
|
||||
};
|
||||
|
||||
export default async function handler(
|
||||
req: NextApiRequest,
|
||||
res: NextApiResponse<Data>
|
||||
) {
|
||||
const username = req.query.u ? (req.query.u as string) : undefined;
|
||||
const sortBy = req.query.s ? (req.query.s as string) : undefined;
|
||||
const sortAsc = req.query.a ? (req.query.a as string) : undefined;
|
||||
|
||||
const redis = createRedisInstance();
|
||||
|
||||
let data = fakeData;
|
||||
// calculate all net worths
|
||||
data = data.map((user) => {
|
||||
return {
|
||||
...user,
|
||||
net_worth:
|
||||
user.points +
|
||||
user.assets.reduce(
|
||||
(a, b) => a + b.count * (fakePrices[b.name] ?? 0),
|
||||
0
|
||||
),
|
||||
};
|
||||
});
|
||||
// calculate ranking based on net worth
|
||||
data = data.sort((a, b) => (b.net_worth ?? 0) - (a.net_worth ?? 0));
|
||||
data = data.map((user, i) => {
|
||||
return {
|
||||
...user,
|
||||
rank: i + 1,
|
||||
// calculate total assets held (shares)
|
||||
shares: user.assets.reduce((a, b) => a + b.count, 0),
|
||||
// sort users badges by priority
|
||||
badges: (user.badges ?? []).sort((a, b) => b.priority - a.priority ?? 0),
|
||||
// sort users assets by total value
|
||||
assets: user.assets.sort(
|
||||
(a, b) =>
|
||||
(fakePrices[b.name] ?? 0) * b.count -
|
||||
(fakePrices[a.name] ?? 0) * a.count
|
||||
),
|
||||
};
|
||||
});
|
||||
|
||||
// if username is specified, only return that user
|
||||
if (username) {
|
||||
// if user does not exist, return error
|
||||
data = data.filter((u) => u.name === username);
|
||||
if (data.length === 0) {
|
||||
res
|
||||
.status(404)
|
||||
.json({ error: { message: "User not found", code: 20000 } });
|
||||
return;
|
||||
}
|
||||
// get twitch data for user
|
||||
const twitchData = await getUserByName(redis, username);
|
||||
// if data is empty, user does not exist
|
||||
if (twitchData.data.length === 0) {
|
||||
// temp who cares
|
||||
twitchData.data[0] = {};
|
||||
twitchData.data[0].profile_image_url = "/img/logo.webp";
|
||||
}
|
||||
// add users profile picture url
|
||||
data = data.map((u) => {
|
||||
return {
|
||||
...u,
|
||||
avatar_url: twitchData.data[0].profile_image_url ?? "",
|
||||
};
|
||||
});
|
||||
res.status(200).json({ data: data[0] });
|
||||
return;
|
||||
}
|
||||
if (sortBy) {
|
||||
if (sortBy === "daily_change") {
|
||||
data = data.sort((a, b) => b.daily_change - a.daily_change);
|
||||
} else if (sortBy === "daily_change_percent") {
|
||||
data = data.sort(
|
||||
(a, b) => b.daily_change_percent - a.daily_change_percent
|
||||
);
|
||||
} else if (sortBy === "shares") {
|
||||
data = data.sort((a, b) => (b.shares ?? 0) - (a.shares ?? 0));
|
||||
} else if (sortBy === "points") {
|
||||
data = data.sort((a, b) => b.points - a.points);
|
||||
} else if (sortBy === "name") {
|
||||
data = data.sort((a, b) => a.name.localeCompare(b.name));
|
||||
}
|
||||
if (sortAsc === "true") {
|
||||
// slow but only needed for temporary fake data anyway
|
||||
data = data.reverse();
|
||||
}
|
||||
}
|
||||
// fake loading time
|
||||
await new Promise((resolve) =>
|
||||
setTimeout(resolve, 250 + Math.random() * 1000)
|
||||
);
|
||||
res.status(200).json({ data: data });
|
||||
}
|
||||
|
||||
interface asset {
|
||||
name: string;
|
||||
count: number;
|
||||
provider: "7tv" | "bttv" | "ffz" | "ttv";
|
||||
}
|
||||
interface fakeDataEntry {
|
||||
id: number;
|
||||
name: string;
|
||||
points: number;
|
||||
daily_change: number;
|
||||
daily_change_percent: number;
|
||||
assets: asset[];
|
||||
net_worth?: number;
|
||||
shares?: number;
|
||||
avatar_url?: string;
|
||||
badges?: badge[];
|
||||
}
|
||||
|
||||
interface badge {
|
||||
name: string;
|
||||
color: string;
|
||||
priority: number;
|
||||
}
|
||||
|
||||
const adminBadge: badge = {
|
||||
name: "Admin",
|
||||
color: "#CC3333",
|
||||
priority: 99999,
|
||||
};
|
||||
|
||||
const CEOBadge: badge = {
|
||||
name: "CEO",
|
||||
color: "#F97316",
|
||||
priority: 100000,
|
||||
};
|
||||
|
||||
const webDevBadge: badge = {
|
||||
name: "Web Dev",
|
||||
color: "#a855f7",
|
||||
priority: 50000,
|
||||
};
|
||||
|
||||
const botDevBadge: badge = {
|
||||
name: "Bot Dev",
|
||||
color: "#48b2f1",
|
||||
priority: 50001,
|
||||
};
|
||||
|
||||
const fakeData: fakeDataEntry[] = [
|
||||
{
|
||||
id: 4,
|
||||
name: "3zachm",
|
||||
points: 7420, // uninvested points
|
||||
daily_change: -500,
|
||||
daily_change_percent: -0.0498504486540378863409770687936,
|
||||
assets: [
|
||||
{
|
||||
name: "JIGACHAD",
|
||||
count: 420,
|
||||
provider: "7tv",
|
||||
},
|
||||
{
|
||||
name: "annykiss",
|
||||
count: 8,
|
||||
provider: "ttv",
|
||||
},
|
||||
{
|
||||
name: "HUH",
|
||||
count: 1,
|
||||
provider: "bttv",
|
||||
},
|
||||
{
|
||||
name: "widepeepoMASTURBATION77769420GANGSHITNOMOREFORTNITE19DOLLERFORTNITECARD",
|
||||
count: 1,
|
||||
provider: "ffz",
|
||||
},
|
||||
{
|
||||
name: "plink",
|
||||
count: 1,
|
||||
provider: "7tv",
|
||||
},
|
||||
],
|
||||
badges: [adminBadge, webDevBadge],
|
||||
},
|
||||
{
|
||||
id: 1,
|
||||
name: "ModulatingForce",
|
||||
points: 10020,
|
||||
daily_change: 5420,
|
||||
daily_change_percent: 0.0379259673920649359736897347981,
|
||||
assets: [
|
||||
{
|
||||
name: "OhTheMiseryEverybodyWantsToBeMyEnemySpareTheSympathyEverybodyWantsToBeMyEnemy-y-y-y-y",
|
||||
count: 39,
|
||||
provider: "7tv",
|
||||
},
|
||||
{
|
||||
name: "Clueless",
|
||||
count: 727,
|
||||
provider: "7tv",
|
||||
},
|
||||
],
|
||||
badges: [adminBadge, botDevBadge],
|
||||
},
|
||||
{
|
||||
id: 2,
|
||||
name: "notohh",
|
||||
points: 10020,
|
||||
daily_change: 0,
|
||||
daily_change_percent: 0,
|
||||
assets: [
|
||||
{
|
||||
name: "YourMom",
|
||||
count: 81,
|
||||
provider: "7tv",
|
||||
},
|
||||
{
|
||||
name: "CumTime",
|
||||
count: 92,
|
||||
provider: "7tv",
|
||||
},
|
||||
{
|
||||
name: "SNIFFA",
|
||||
count: 1219,
|
||||
provider: "7tv",
|
||||
},
|
||||
],
|
||||
badges: [adminBadge, botDevBadge],
|
||||
},
|
||||
{
|
||||
id: 3,
|
||||
name: "SecondSockSan",
|
||||
points: 15020,
|
||||
daily_change: -10432,
|
||||
daily_change_percent: -0.06796312583471774324896576435715,
|
||||
assets: [
|
||||
{
|
||||
name: "AYAYAjam",
|
||||
count: 46,
|
||||
provider: "7tv",
|
||||
},
|
||||
{
|
||||
name: "ThisStream",
|
||||
count: 210,
|
||||
provider: "7tv",
|
||||
},
|
||||
{
|
||||
name: "BAND",
|
||||
count: 91,
|
||||
provider: "7tv",
|
||||
},
|
||||
],
|
||||
badges: [CEOBadge, adminBadge],
|
||||
},
|
||||
{
|
||||
id: 0,
|
||||
name: "mzntori",
|
||||
points: 922022,
|
||||
daily_change: 329444422,
|
||||
daily_change_percent: 4.2932124926634939999741296760186,
|
||||
assets: [
|
||||
{
|
||||
name: "peepoSnow",
|
||||
count: 72,
|
||||
provider: "7tv",
|
||||
},
|
||||
{
|
||||
name: "golive",
|
||||
count: 90,
|
||||
provider: "7tv",
|
||||
},
|
||||
{
|
||||
name: "annyExcitedHug",
|
||||
count: 26,
|
||||
provider: "7tv",
|
||||
},
|
||||
{
|
||||
name: "AAAA",
|
||||
count: 65,
|
||||
provider: "7tv",
|
||||
},
|
||||
],
|
||||
badges: [adminBadge, botDevBadge],
|
||||
},
|
||||
{
|
||||
id: 5,
|
||||
name: "luckytohavefoundyou14252",
|
||||
points: 423,
|
||||
daily_change: 9,
|
||||
daily_change_percent: 0.00112163509471585244267198404786,
|
||||
assets: [
|
||||
{
|
||||
name: "HACKERMANS",
|
||||
count: 59,
|
||||
provider: "7tv",
|
||||
},
|
||||
{
|
||||
name: "THIS",
|
||||
count: 70,
|
||||
provider: "7tv",
|
||||
},
|
||||
{
|
||||
name: "lebronJAM",
|
||||
count: 66,
|
||||
provider: "7tv",
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
id: 6,
|
||||
name: "ZeroxZerich",
|
||||
points: 88542,
|
||||
daily_change: -10219,
|
||||
daily_change_percent: -0.01213384153219582279533121979601,
|
||||
assets: [
|
||||
{
|
||||
name: "WeebRun",
|
||||
count: 10,
|
||||
provider: "7tv",
|
||||
},
|
||||
{
|
||||
name: "BAND",
|
||||
count: 49,
|
||||
provider: "7tv",
|
||||
},
|
||||
{
|
||||
name: "SNIFFA",
|
||||
count: 78,
|
||||
provider: "7tv",
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
id: 7,
|
||||
name: "joeeyo",
|
||||
points: 99979,
|
||||
daily_change: 1,
|
||||
daily_change_percent: 0.0000001,
|
||||
assets: [
|
||||
{
|
||||
name: "Siti",
|
||||
count: 32,
|
||||
provider: "7tv",
|
||||
},
|
||||
{
|
||||
name: "peepoTalk",
|
||||
count: 73,
|
||||
provider: "7tv",
|
||||
},
|
||||
{
|
||||
name: "peepoSnow",
|
||||
count: 37,
|
||||
provider: "7tv",
|
||||
},
|
||||
{
|
||||
name: "MadgeJuice",
|
||||
count: 70,
|
||||
provider: "7tv",
|
||||
},
|
||||
{
|
||||
name: "xdd666",
|
||||
count: 53,
|
||||
provider: "7tv",
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
id: 8,
|
||||
name: "dd_maru",
|
||||
points: 208421,
|
||||
daily_change: 85192,
|
||||
daily_change_percent: 0.00824830823607984221402284047097,
|
||||
assets: [
|
||||
{
|
||||
name: "BocchiPossessed",
|
||||
count: 56,
|
||||
provider: "7tv",
|
||||
},
|
||||
{
|
||||
name: "toffeeConfused",
|
||||
count: 64,
|
||||
provider: "7tv",
|
||||
},
|
||||
{
|
||||
name: "ewLeague",
|
||||
count: 64,
|
||||
provider: "7tv",
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
id: 9,
|
||||
name: "Goldeneye128",
|
||||
points: 6521,
|
||||
daily_change: -1942,
|
||||
daily_change_percent: -0.03331503465312564331297605160228,
|
||||
assets: [
|
||||
{
|
||||
name: "PagMan",
|
||||
count: 52,
|
||||
provider: "7tv",
|
||||
},
|
||||
{
|
||||
name: "CapybaraStare",
|
||||
count: 47,
|
||||
provider: "7tv",
|
||||
},
|
||||
{
|
||||
name: "GroupWankge",
|
||||
count: 38,
|
||||
provider: "7tv",
|
||||
},
|
||||
{
|
||||
name: "annyCucumber",
|
||||
count: 90,
|
||||
provider: "7tv",
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
id: 10,
|
||||
name: "lilpastatv",
|
||||
points: 40,
|
||||
daily_change: 921821,
|
||||
daily_change_percent: 0.12577857662228222197571019682439,
|
||||
assets: [
|
||||
{
|
||||
name: "Wigglecat",
|
||||
count: 205,
|
||||
provider: "7tv",
|
||||
},
|
||||
{
|
||||
name: "guraWink",
|
||||
count: 5,
|
||||
provider: "7tv",
|
||||
},
|
||||
{
|
||||
name: "golive",
|
||||
count: 46,
|
||||
provider: "7tv",
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
id: 11,
|
||||
name: "domiswitch",
|
||||
points: 5002,
|
||||
daily_change: 2429,
|
||||
daily_change_percent: 0.05610995610995610995610995610996,
|
||||
assets: [
|
||||
{
|
||||
name: "peepoFlute",
|
||||
count: 81,
|
||||
provider: "7tv",
|
||||
},
|
||||
{
|
||||
name: "WhoAsked",
|
||||
count: 44,
|
||||
provider: "7tv",
|
||||
},
|
||||
{
|
||||
name: "pL",
|
||||
count: 24,
|
||||
provider: "7tv",
|
||||
},
|
||||
{
|
||||
name: "peepoSnow",
|
||||
count: 13,
|
||||
provider: "7tv",
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
id: 12,
|
||||
name: "minosura",
|
||||
points: 32901,
|
||||
daily_change: 94821,
|
||||
daily_change_percent: 0.10485244291894091524314186887943,
|
||||
assets: [
|
||||
{
|
||||
name: "Okayeg",
|
||||
count: 100,
|
||||
provider: "7tv",
|
||||
},
|
||||
{
|
||||
name: "burh",
|
||||
count: 100,
|
||||
provider: "7tv",
|
||||
},
|
||||
{
|
||||
name: "yoshiJAM",
|
||||
count: 67,
|
||||
provider: "7tv",
|
||||
},
|
||||
{
|
||||
name: "WhoAsked",
|
||||
count: 59,
|
||||
provider: "7tv",
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
id: 13,
|
||||
name: "scienceteam_member",
|
||||
points: 958,
|
||||
daily_change: -7964,
|
||||
daily_change_percent: -0.22823408035765461110792686421734,
|
||||
assets: [
|
||||
{
|
||||
name: "LULE",
|
||||
count: 43,
|
||||
provider: "7tv",
|
||||
},
|
||||
{
|
||||
name: "Madgeclap",
|
||||
count: 82,
|
||||
provider: "7tv",
|
||||
},
|
||||
{
|
||||
name: "PeepoKittyHug",
|
||||
count: 7,
|
||||
provider: "7tv",
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
id: 14,
|
||||
name: "witchdev",
|
||||
points: 8532,
|
||||
daily_change: -421,
|
||||
daily_change_percent: -0.0000044605531984433792422085896,
|
||||
assets: [
|
||||
{
|
||||
name: "SNIFFA",
|
||||
count: 76,
|
||||
provider: "7tv",
|
||||
},
|
||||
{
|
||||
name: "annyCD",
|
||||
count: 62,
|
||||
provider: "7tv",
|
||||
},
|
||||
{
|
||||
name: "anyatf",
|
||||
count: 24,
|
||||
provider: "7tv",
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
id: 15,
|
||||
name: "justone123879",
|
||||
points: 86333,
|
||||
daily_change: 53289,
|
||||
daily_change_percent: 0.00599485461051669551653183334284,
|
||||
assets: [
|
||||
{
|
||||
name: "Homi",
|
||||
count: 9,
|
||||
provider: "7tv",
|
||||
},
|
||||
{
|
||||
name: "wideVIBE",
|
||||
count: 61,
|
||||
provider: "7tv",
|
||||
},
|
||||
{
|
||||
name: "Lagging",
|
||||
count: 92,
|
||||
provider: "7tv",
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
id: 16,
|
||||
name: "marcelr_",
|
||||
points: 39291,
|
||||
daily_change: 1329,
|
||||
daily_change_percent: 0.00331976948959480827019776234047,
|
||||
assets: [
|
||||
{
|
||||
name: "peepoStuck",
|
||||
count: 91,
|
||||
provider: "7tv",
|
||||
},
|
||||
{
|
||||
name: "PokiShare",
|
||||
count: 13,
|
||||
provider: "7tv",
|
||||
},
|
||||
{
|
||||
name: "VeryBased",
|
||||
count: 7,
|
||||
provider: "7tv",
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
id: 17,
|
||||
name: "fossabot",
|
||||
points: 0,
|
||||
daily_change: -31042,
|
||||
daily_change_percent: -1.5517120719820044988752811797051,
|
||||
assets: [
|
||||
{
|
||||
name: "catbaby",
|
||||
count: 41,
|
||||
provider: "7tv",
|
||||
},
|
||||
{
|
||||
name: "peepoCat",
|
||||
count: 41,
|
||||
provider: "7tv",
|
||||
},
|
||||
{
|
||||
name: "plink",
|
||||
count: 32,
|
||||
provider: "7tv",
|
||||
},
|
||||
],
|
||||
},
|
||||
];
|
||||
|
||||
export type { fakeDataEntry };
|
|
@ -1,9 +1,10 @@
|
|||
import { m, Variants } from "framer-motion";
|
||||
import Head from "next/head";
|
||||
import Link from "next/link";
|
||||
import { ReactElement, useEffect, useState } from "react";
|
||||
import Loading from "../../components/common/Loading";
|
||||
import DashLayout from "../../layouts/DashLayout";
|
||||
import { fakeDataEntry } from "../api/fakeRanking";
|
||||
import { fakeDataEntry } from "../api/fakeUsers";
|
||||
|
||||
function Ranking() {
|
||||
const [sortBy, setSortBy] = useState("netWorth");
|
||||
|
@ -14,7 +15,7 @@ function Ranking() {
|
|||
useEffect(() => {
|
||||
setDataLoaded(false);
|
||||
// fetch data from api on change to sort method
|
||||
fetch(`/api/fakeRanking?s=${sortBy}&a=${sortAsc}`)
|
||||
fetch(`/api/fakeUsers?s=${sortBy}&a=${sortAsc}`)
|
||||
.then((res) => res.json())
|
||||
.then((data) => {
|
||||
setFakeData(data.data);
|
||||
|
@ -78,13 +79,13 @@ function Ranking() {
|
|||
<title>Ranking - toffee</title>
|
||||
</Head>
|
||||
<div className="flex w-full justify-center">
|
||||
<div className="ml-3 flex w-full flex-col items-center justify-start font-robotoMono font-semibold lg:ml-0">
|
||||
<div className="ml-3 flex w-full max-w-7xl flex-col items-center justify-start font-plusJakarta font-semibold lg:ml-0">
|
||||
{/* hidden if smaller than lg */}
|
||||
<m.h1
|
||||
className="hidden bg-gradient-to-tr from-purple-500 to-purple-100 bg-clip-text py-10 text-center font-plusJakarta text-5xl font-bold text-white text-transparent lg:block lg:text-6xl"
|
||||
className="hidden py-10 text-center text-5xl font-normal text-pink-300 lg:block lg:text-6xl"
|
||||
variants={headerVariants}
|
||||
>
|
||||
Top Investors
|
||||
top investors
|
||||
</m.h1>
|
||||
{/* TODO: responsive for extremely skinny displays (i.e. galaxy fold), or really for mobile entirely so info is not lost */}
|
||||
<m.div
|
||||
|
@ -162,39 +163,44 @@ function Ranking() {
|
|||
>
|
||||
{
|
||||
// generate table rows
|
||||
fakeData.map((entry: fakeDataEntry, index) => {
|
||||
// if daily change is negative, make it red
|
||||
let changeClass = " text-lime-500";
|
||||
if (entry.dailyChangePercent < 0) {
|
||||
changeClass = " text-red-500";
|
||||
fakeData.map(
|
||||
(entry: { [key: string]: any }, index: number) => {
|
||||
// if daily change is negative, make it red
|
||||
let changeClass = " text-lime-500";
|
||||
if (entry.daily_change_percent < 0) {
|
||||
changeClass = " text-red-500";
|
||||
}
|
||||
return (
|
||||
<m.div
|
||||
className="inline-grid w-full grid-flow-col grid-cols-[1fr_4fr_3fr_2fr] gap-2 border-b-2 border-zinc-700 px-5 py-2 text-right md:grid-cols-[0.5fr_4fr_repeat(3,_2fr)_1.5fr]"
|
||||
key={entry.id}
|
||||
variants={rankingDataLineVariants}
|
||||
>
|
||||
<h1 className="text-left md:text-center">
|
||||
{index + 1}
|
||||
</h1>
|
||||
<Link href={`/user/${entry.name}`}>
|
||||
<h1 className="overflow-hidden overflow-ellipsis whitespace-nowrap text-left">
|
||||
{entry.name}
|
||||
</h1>
|
||||
</Link>
|
||||
<h1>{entry.net_worth.toLocaleString("en-US")}</h1>
|
||||
<h1 className="hidden md:block">
|
||||
{entry.points.toLocaleString("en-US")}
|
||||
</h1>
|
||||
<h1 className="hidden md:block">
|
||||
{entry.shares.toLocaleString("en-US")}
|
||||
</h1>
|
||||
<h1 className={changeClass}>
|
||||
{(
|
||||
Math.round(entry.daily_change_percent * 1000) /
|
||||
10
|
||||
).toFixed(1) + "%"}
|
||||
</h1>
|
||||
</m.div>
|
||||
);
|
||||
}
|
||||
return (
|
||||
<m.div
|
||||
className="inline-grid w-full grid-flow-col grid-cols-[1fr_4fr_3fr_2fr] gap-2 border-b-2 border-zinc-700 px-5 py-2 text-right md:grid-cols-[0.5fr_4fr_repeat(3,_2fr)_1.5fr]"
|
||||
key={entry.id}
|
||||
variants={rankingDataLineVariants}
|
||||
>
|
||||
<h1 className="text-left md:text-center">
|
||||
{index + 1}
|
||||
</h1>
|
||||
<h1 className="overflow-hidden overflow-ellipsis whitespace-nowrap text-left">
|
||||
{entry.name}
|
||||
</h1>
|
||||
<h1>{entry.netWorth.toLocaleString("en-US")}</h1>
|
||||
<h1 className="hidden md:block">
|
||||
{entry.points.toLocaleString("en-US")}
|
||||
</h1>
|
||||
<h1 className="hidden md:block">
|
||||
{entry.shares.toLocaleString("en-US")}
|
||||
</h1>
|
||||
<h1 className={changeClass}>
|
||||
{(
|
||||
Math.round(entry.dailyChangePercent * 1000) / 10
|
||||
).toFixed(1) + "%"}
|
||||
</h1>
|
||||
</m.div>
|
||||
);
|
||||
})
|
||||
)
|
||||
}
|
||||
</m.div>
|
||||
)
|
||||
|
|
391
pages/user/[username]/index.tsx
Normal file
391
pages/user/[username]/index.tsx
Normal file
|
@ -0,0 +1,391 @@
|
|||
import { m } from "framer-motion";
|
||||
import Head from "next/head";
|
||||
import { useRouter } from "next/router";
|
||||
import { ReactElement, useEffect, useState } from "react";
|
||||
import DashLayout from "../../../layouts/DashLayout";
|
||||
import Image from "next/image";
|
||||
import Loading from "../../../components/common/Loading";
|
||||
|
||||
// TODO: Animations
|
||||
|
||||
function UserPage() {
|
||||
const [channelEmotes, setChannelEmotes] = useState<{ [key: string]: string }>(
|
||||
{}
|
||||
);
|
||||
const [userData, setUserData] = useState<{ [key: string]: any }>({});
|
||||
const [errorCode, setErrorCode] = useState<number | null>(null);
|
||||
const router = useRouter();
|
||||
const { username } = router.query;
|
||||
const title = username ? `${username} - toffee` : "toffee";
|
||||
|
||||
useEffect(() => {
|
||||
if (!router.isReady) return;
|
||||
fetch("/api/7tv/emotes?c=61ad997effa9aba101bcfddf")
|
||||
.then((res) => res.json())
|
||||
.then((data) => {
|
||||
// if error, return
|
||||
if (data.error) {
|
||||
setErrorCode(data.error.code);
|
||||
return;
|
||||
}
|
||||
// construct js object with emote names as keys and emote urls as values
|
||||
let emotes: { [key: string]: string } = {};
|
||||
data.channel.user.emote_sets[0].emotes.forEach((emote: any) => {
|
||||
let base_url = emote.data.host.url;
|
||||
// get the largest emote size, append it to the base url
|
||||
let largest = emote.data.host.files[emote.data.host.files.length - 1];
|
||||
emotes[emote.data.name] = `https:${base_url}/${largest.name}`;
|
||||
});
|
||||
setChannelEmotes(emotes);
|
||||
});
|
||||
fetch(`/api/fakeUsers?u=${username}`)
|
||||
.then((res) => res.json())
|
||||
.then((data) => {
|
||||
if (data.error) {
|
||||
setErrorCode(data.error.code);
|
||||
}
|
||||
setUserData(data.data);
|
||||
});
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, [router.isReady]);
|
||||
// if json is empty
|
||||
if (Object.keys(channelEmotes).length === 0 && errorCode !== 10000) {
|
||||
return (
|
||||
<div className="flex h-screen w-full items-center justify-center text-3xl">
|
||||
<Loading />
|
||||
</div>
|
||||
);
|
||||
}
|
||||
if (errorCode === 20000) {
|
||||
return (
|
||||
<m.div
|
||||
className="flex h-screen w-full items-center justify-center text-3xl"
|
||||
initial={{ opacity: 0, y: -50 }}
|
||||
animate={{ opacity: 1, y: 0, transition: { duration: 1.0 } }}
|
||||
exit={{ opacity: 0, y: -25 }}
|
||||
>
|
||||
<p>User not found :c</p>
|
||||
</m.div>
|
||||
);
|
||||
}
|
||||
if (!userData || Object.keys(userData).length === 0) {
|
||||
return (
|
||||
<div className="flex h-screen w-full items-center justify-center text-3xl">
|
||||
<Loading />
|
||||
</div>
|
||||
);
|
||||
}
|
||||
return (
|
||||
<>
|
||||
<Head>
|
||||
<title>{title}</title>
|
||||
<meta
|
||||
name="description"
|
||||
content={`${username}'s portfolio on toffee`}
|
||||
/>
|
||||
</Head>
|
||||
<div className="flex justify-center">
|
||||
<div className="mt-2 inline-grid w-[calc(100%-40px)] max-w-5xl grid-cols-10 gap-3 pt-12 pl-2 font-plusJakarta lg:pl-0 lg:pr-2">
|
||||
{/* User "banner" */}
|
||||
<div className="col-span-10 mb-2 rounded-2xl bg-zinc-800 bg-opacity-70 p-3">
|
||||
<div className="flex items-center justify-between p-4">
|
||||
<div className="flex flex-row items-center">
|
||||
<Image
|
||||
src={userData.avatar_url}
|
||||
alt="User avatar"
|
||||
width={140}
|
||||
height={140}
|
||||
className="fixed rounded-lg border-4"
|
||||
style={{
|
||||
borderColor: userData.badges[0]
|
||||
? userData.badges[0].color
|
||||
: "grey",
|
||||
// "glow" effect
|
||||
boxShadow: `0px 0px 20px 1px ${
|
||||
userData.badges[0]
|
||||
? userData.badges[0].color
|
||||
: "transparent"
|
||||
}`,
|
||||
}}
|
||||
/>
|
||||
<div className="ml-[154px] flex-col">
|
||||
<h1 className="text-4xl font-semibold text-white">
|
||||
{userData.name}
|
||||
</h1>
|
||||
{/* User's badges */}
|
||||
<div className="mt-1 flex flex-row text-sm">
|
||||
{userData.badges ? (
|
||||
userData.badges.map(
|
||||
(badge: {
|
||||
name: string;
|
||||
color: string;
|
||||
priority: number;
|
||||
}) => {
|
||||
return (
|
||||
<div
|
||||
style={{ backgroundColor: badge.color }}
|
||||
className="mr-1 rounded-md bg-purple-500 px-2"
|
||||
key={badge.name}
|
||||
>
|
||||
<span className="text-white">{badge.name}</span>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
)
|
||||
) : (
|
||||
<></>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
<h1>
|
||||
<span className="text-4xl font-semibold text-zinc-400">
|
||||
$
|
||||
</span>
|
||||
<span className="text-4xl text-white">
|
||||
{userData.net_worth.toLocaleString("en-US")}
|
||||
</span>
|
||||
</h1>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{/* Main Container */}
|
||||
<div className="col-span-7 inline-grid grid-cols-7 gap-3 rounded-2xl">
|
||||
{/* User's Rank/Graph */}
|
||||
<div className="col-span-7 rounded-2xl bg-zinc-800 bg-opacity-70">
|
||||
<div className="flex flex-row items-center justify-between p-5">
|
||||
<div className="flex-col">
|
||||
<h1 className="mb-1 text-center text-2xl font-medium text-white underline">
|
||||
Global Rank
|
||||
</h1>
|
||||
<div className="flex items-center text-3xl font-bold">
|
||||
<span className="text-zinc-400">#</span>
|
||||
<span className="text-white">
|
||||
{userData.rank.toLocaleString("en-US")}
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
<Image
|
||||
src="/img/well_drawn_rank_chart.webp"
|
||||
alt="Rank chart"
|
||||
width={497}
|
||||
height={100}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{/* User's Assets */}
|
||||
<div className="col-span-7 flex flex-col rounded-2xl bg-zinc-800 bg-opacity-70">
|
||||
{/* User's Assets Header */}
|
||||
<div className="h-11 w-full rounded-t-2xl bg-pink-400">
|
||||
<h1 className="m-1 text-center text-2xl font-bold">
|
||||
Top Assets
|
||||
</h1>
|
||||
</div>
|
||||
{/* User's Assets Body */}
|
||||
<div className="inline-grid grid-cols-4 items-center justify-start p-5">
|
||||
{errorCode === 20000 ? (
|
||||
<h1 className=" text-zinc-400">{`Could not load assets`}</h1>
|
||||
) : (
|
||||
userData.assets.map(
|
||||
(asset: {
|
||||
name: string;
|
||||
count: number;
|
||||
provider: string;
|
||||
}) => (
|
||||
<div
|
||||
className="m-2 mb-0 flex h-44 w-40 flex-col items-center rounded-xl bg-zinc-900 bg-opacity-80 p-2"
|
||||
key={asset.name}
|
||||
>
|
||||
<div className="mt-2 mb-2 h-24 w-24">
|
||||
<div className="flex h-full w-full items-center justify-center p-2">
|
||||
{
|
||||
// if error code is 10000, show placeholder image
|
||||
errorCode === 10000 ? (
|
||||
<h1 className="text-center text-zinc-400">{`404 :(`}</h1>
|
||||
) : (
|
||||
<Image
|
||||
src={channelEmotes[asset.name]}
|
||||
alt={asset.name}
|
||||
width={100}
|
||||
height={100}
|
||||
className="max-h-[100px]"
|
||||
/>
|
||||
)
|
||||
}
|
||||
{/* Fix asset count to bottom right of image */}
|
||||
<div className="relative rounded-full bg-zinc-900 bg-opacity-80 p-1">
|
||||
<p
|
||||
className="absolute -bottom-10 -right-2 -rotate-12 text-lg font-bold text-white"
|
||||
style={{ textShadow: "0px 0px 4px black" }}
|
||||
>
|
||||
x{asset.count}
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div className="flex w-full flex-row items-center justify-center">
|
||||
{
|
||||
// show provider logo (7tv, bttv, ffz, twitch)
|
||||
asset.provider === "7tv" ? (
|
||||
<div className="mr-1 pt-[1px] text-7tv ">
|
||||
<SevenTVLogo />
|
||||
</div>
|
||||
) : asset.provider === "bttv" ? (
|
||||
<div className="mr-1 pt-[1px] text-bttv">
|
||||
<BTTVLogo />
|
||||
</div>
|
||||
) : asset.provider === "ffz" ? (
|
||||
<div className="h-5 w-6 text-white">
|
||||
<FFZLogo />
|
||||
</div>
|
||||
) : (
|
||||
<div className="mr-1 w-4 pt-[1px] text-ttv">
|
||||
<TwitchLogo />
|
||||
</div>
|
||||
)
|
||||
}
|
||||
<p className="text-md max-w-[80%] overflow-hidden overflow-ellipsis whitespace-nowrap font-bold text-white">
|
||||
{asset.name}
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
)
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{/* Sidebar */}
|
||||
<div className="col-span-3 flex flex-col">
|
||||
<div className="center mb-3 inline-grid grid-cols-2 gap-3 rounded-2xl bg-zinc-800 bg-opacity-70 p-5 text-xl font-medium">
|
||||
{/* User's Stats, left side is label, right side is value */}
|
||||
<h1>Points</h1>
|
||||
<h1>{userData.points.toLocaleString("en-US")}</h1>
|
||||
<h1>Shares</h1>
|
||||
<h1>{userData.shares.toLocaleString("en-US")}</h1>
|
||||
<h1>Trades</h1>
|
||||
<h1>{(userData.trades ?? 0).toLocaleString("en-US")}</h1>
|
||||
<h1>Peak rank</h1>
|
||||
<h1>{(userData.peak_rank ?? 0).toLocaleString("en-US")}</h1>
|
||||
<h1>Joined</h1>
|
||||
<h1>
|
||||
{new Date(userData.joined ?? 0).toLocaleDateString("en-US", {
|
||||
year: "numeric",
|
||||
month: "short",
|
||||
})}
|
||||
</h1>
|
||||
</div>
|
||||
{/* User's Favorite Emote */}
|
||||
<div className="flex flex-col rounded-2xl bg-zinc-800 bg-opacity-70">
|
||||
<div className="h-11 w-full rounded-t-2xl bg-pink-400">
|
||||
<h1 className="m-1 text-center text-2xl font-bold">
|
||||
Favorite Emote
|
||||
</h1>
|
||||
</div>
|
||||
<div>
|
||||
<p className="m-5 text-lg text-zinc-400">
|
||||
This user has not yet set a favorite emote.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
const SevenTVLogo = () => {
|
||||
return (
|
||||
<svg viewBox="0 0 109.6 80.9" width="1em">
|
||||
<g>
|
||||
<path
|
||||
d="M84.1,22.2l5-8.7,2.7-4.6L86.8.2V0H60.1l5,8.7,5,8.7,2.8,4.8H84.1"
|
||||
fill="currentColor"
|
||||
></path>
|
||||
<path
|
||||
d="M29,80.6l5-8.7,5-8.7,5-8.7,5-8.7,5-8.7,5-8.7L62.7,22l-5-8.7-5-8.7L49.9.1H7.7l-5,8.7L0,13.4l5,8.7v.2h32l-5,8.7-5,8.7-5,8.7-5,8.7-5,8.7L8.5,72l5,8.7v.2H29"
|
||||
fill="currentColor"
|
||||
></path>
|
||||
<path
|
||||
d="M70.8,80.6H86.1l5-8.7,5-8.7,5-8.7,5-8.7,3.5-6-5-8.7v-.2H89.2l-5,8.7-5,8.7-.7,1.3-5-8.7-5-8.7-.7-1.3-5,8.7-5,8.7L55,53.1l5,8.7,5,8.7,5,8.7.8,1.4"
|
||||
fill="currentColor"
|
||||
></path>
|
||||
</g>
|
||||
</svg>
|
||||
);
|
||||
};
|
||||
|
||||
const FFZLogo = () => {
|
||||
return (
|
||||
<svg viewBox="0 0 396 396">
|
||||
<path
|
||||
d="m150.06,151.58c-.77-6.33.31-12.45,1.99-18.5,2.37-8.51,9.11-14.22,15.62-18.44,8.71-5.65,18.98-8.6,30.02-8.89,7.26-.19,12.89,3.13,18.17,6.2,3.98,2.32,7.8,6.66,10.25,11.43,2.99,5.83,5.92,11.51,7.05,18.18,1.17,6.9,4.69,13.3,9.05,18.55,4.61,5.55,5.63,11.86,5.53,18.1-.15,8.77,3.32,16.07,6.61,23.64.93,2.14,2.15,3.87,4.76,3.08,2.58-.77,4.04-2.69,3.78-5.44-.32-3.41-.64-6.86-1.43-10.18-1.01-4.18-1.54-8.31-1.45-12.65.19-9.37,6.06-15.83,12.06-21.43,5.81-5.44,9.29-4.23,15.15,1.48,7.52,7.32,14.31,15.22,18.49,24.91,3.86,8.94,7.62,17.97,10.54,27.24,1.79,5.7,2.26,11.9,2.71,17.92.35,4.7-2.69,8.43-6.01,11.17-12.05,9.97-24.04,20.06-38.64,26.39-3.06,1.32-5.93,3.65-8.27,5.9-4.3,4.13-8.7,4.8-14.22,3.81-6.67-1.2-12.21,2.2-17.76,5.37-10.83,6.19-21.98,11.44-34.99,10.56-2.65-.18-5.35-.19-7.99.05-9.67.89-18.35-1.86-26.44-6.91-5.06-3.16-10.74-5.27-15.39-9.12-.62-.51-1.58-.75-1.96-1.37-3.61-5.84-8.03-5.41-13.72-2.82-7.66,3.48-8.07,3.02-13.2-3.77-3.48-4.6-8.91-6.59-13.27-10.01-11.43-8.97-22.52-18.11-29.39-31.42-2.17-4.21-2.9-8.38-2.59-12.82.76-10.87,1-21.85,7.82-31.3,6.01-8.32,10.79-17.68,19.29-23.9,5.9-4.32,10.15-2.9,14.27,3.26,6.93,10.36,7.99,21.4,4.42,33.03-1.46,4.76-.62,9.52-.8,14.28-.09,2.23,2.26,4.61,3.36,4.24,2.47-.83,5.83.99,7.52-2.37,5.96-11.87,14.26-22.67,17.36-35.82,1.65-7.02,2.21-14.34,1.72-21.63Z"
|
||||
fill="currentColor"
|
||||
/>
|
||||
</svg>
|
||||
);
|
||||
};
|
||||
|
||||
const BTTVLogo = () => {
|
||||
return (
|
||||
<svg viewBox="0 0 300 300" height="1em">
|
||||
<path
|
||||
fill="transparent"
|
||||
d="M249.771 150A99.771 99.922 0 0 1 150 249.922 99.771 99.922 0 0 1 50.229 150 99.771 99.922 0 0 1 150 50.078 99.771 99.922 0 0 1 249.771 150Z"
|
||||
></path>
|
||||
<path
|
||||
fill="currentColor"
|
||||
d="M150 1.74C68.409 1.74 1.74 68.41 1.74 150S68.41 298.26 150 298.26h148.26V150.17h-.004c0-.057.004-.113.004-.17C298.26 68.409 231.59 1.74 150 1.74zm0 49c55.11 0 99.26 44.15 99.26 99.26 0 55.11-44.15 99.26-99.26 99.26-55.11 0-99.26-44.15-99.26-99.26 0-55.11 44.15-99.26 99.26-99.26z"
|
||||
></path>
|
||||
<path
|
||||
fill="currentColor"
|
||||
d="M161.388 70.076c-10.662 0-19.42 7.866-19.42 17.67 0 9.803 8.758 17.67 19.42 17.67 10.662 0 19.42-7.867 19.42-17.67 0-9.804-8.758-17.67-19.42-17.67zm45.346 24.554-.02.022-.004.002c-5.402 2.771-11.53 6.895-18.224 11.978l-.002.002-.004.002c-25.943 19.766-60.027 54.218-80.344 80.33h-.072l-1.352 1.768c-5.114 6.69-9.267 12.762-12.098 18.006l-.082.082.022.021v.002l.004.002.174.176.052-.053.102.053-.07.072c30.826 30.537 81.213 30.431 111.918-.273 30.783-30.784 30.8-81.352.04-112.152l-.005-.004zM87.837 142.216c-9.803 0-17.67 8.758-17.67 19.42 0 10.662 7.867 19.42 17.67 19.42 9.804 0 17.67-8.758 17.67-19.42 0-10.662-7.866-19.42-17.67-19.42z"
|
||||
></path>
|
||||
</svg>
|
||||
);
|
||||
};
|
||||
|
||||
const TwitchLogo = () => {
|
||||
return (
|
||||
<svg x="0px" y="0px" viewBox="0 0 2400 2800">
|
||||
<g>
|
||||
<polygon
|
||||
className="fill-white"
|
||||
points="2200,1300 1800,1700 1400,1700 1050,2050 1050,1700 600,1700 600,200 2200,200"
|
||||
/>
|
||||
<g>
|
||||
<g id="Layer_1-2">
|
||||
<path
|
||||
fill="currentColor"
|
||||
d="M500,0L0,500v1800h600v500l500-500h400l900-900V0H500z M2200,1300l-400,400h-400l-350,350v-350H600V200h1600 V1300z"
|
||||
/>
|
||||
<rect
|
||||
x="1700"
|
||||
y="550"
|
||||
fill="currentColor"
|
||||
width="200"
|
||||
height="600"
|
||||
/>
|
||||
<rect
|
||||
x="1150"
|
||||
y="550"
|
||||
fill="currentColor"
|
||||
width="200"
|
||||
height="600"
|
||||
/>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
||||
);
|
||||
};
|
||||
|
||||
UserPage.getLayout = function getLayout(page: ReactElement) {
|
||||
return <DashLayout>{page}</DashLayout>;
|
||||
};
|
||||
|
||||
export default UserPage;
|
BIN
public/img/well_drawn_rank_chart.webp
Normal file
BIN
public/img/well_drawn_rank_chart.webp
Normal file
Binary file not shown.
After Width: | Height: | Size: 14 KiB |
|
@ -13,6 +13,11 @@ module.exports = {
|
|||
robotoMono: ["Roboto Mono", "monospace"],
|
||||
minecraft: ["Minecraft", "Roboto", "sans-serif"],
|
||||
},
|
||||
colors: {
|
||||
"7tv": "#4fc2bc",
|
||||
bttv: "#d50014",
|
||||
ttv: "#9146FF",
|
||||
},
|
||||
},
|
||||
},
|
||||
plugins: [],
|
||||
|
|
Loading…
Reference in a new issue