Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Staging #159

Merged
merged 41 commits into from
Apr 16, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
41 commits
Select commit Hold shift + click to select a range
c9fefd6
implementing tooltip for rank icons
AkinariHex Mar 20, 2024
4d63644
first design for tooltip
AkinariHex Mar 20, 2024
f3190fe
new elite-grandmaster rank icon
AkinariHex Mar 23, 2024
ce3d07e
display rank icon in player profile
AkinariHex Mar 23, 2024
fc99d5e
Merge pull request #139 from osu-tournament-rating/feature/126
hburn7 Mar 23, 2024
c9bc45c
Merge pull request #140 from osu-tournament-rating/feature/127
hburn7 Mar 23, 2024
cdf2f1b
refreshToken new expiration
AkinariHex Mar 23, 2024
47194bf
Merge pull request #141 from osu-tournament-rating/fix/refreshToken-E…
hburn7 Mar 23, 2024
70f44a6
fix leaderboard tiers filter with new api changes
AkinariHex Mar 24, 2024
191f602
removed line of code
AkinariHex Mar 24, 2024
36e231a
Merge pull request #142 from osu-tournament-rating/feature/138
myssto Mar 25, 2024
a8883a6
Rename roles to scopes
hburn7 Mar 26, 2024
ed4f877
Merge pull request #144 from osu-tournament-rating/hotfix/me-controll…
hburn7 Mar 27, 2024
1f48bdb
fix leaderboard params when changing page
AkinariHex Apr 1, 2024
abb9fe3
Merge pull request #145 from osu-tournament-rating/fix/leaderboard-pa…
hburn7 Apr 1, 2024
723cae3
dashboard user gamemode error handling
AkinariHex Apr 1, 2024
7c78f58
error message change
AkinariHex Apr 1, 2024
d3e3846
Merge pull request #146 from osu-tournament-rating/fix/manage-dashboa…
hburn7 Apr 1, 2024
b05c50d
create gamemode cookie on login
AkinariHex Apr 1, 2024
ecff811
Merge pull request #148 from osu-tournament-rating/fix/manage-dashboa…
hburn7 Apr 1, 2024
abb56e4
Use new submission endpoint
myssto Apr 4, 2024
9248a8c
fixing session naming that were blocking the submit
AkinariHex Apr 6, 2024
1815ef7
Fix query param
myssto Apr 7, 2024
0df8495
submission now shows error toast if needed
AkinariHex Apr 7, 2024
d2216c0
dark mode implementation
AkinariHex Apr 7, 2024
2b26e6e
dark mode color change
AkinariHex Apr 8, 2024
8d0a41b
Merge pull request #151 from osu-tournament-rating/hotfix/submit-endp…
hburn7 Apr 8, 2024
797b771
Merge pull request #152 from osu-tournament-rating/feature/dark-mode
hburn7 Apr 8, 2024
18b398c
fix dark mode user profile and homepage logo
AkinariHex Apr 9, 2024
10414a9
Merge pull request #153 from osu-tournament-rating/feature/dark-mode
hburn7 Apr 9, 2024
08ac1f1
init search bar design
AkinariHex Apr 10, 2024
867f6b2
navbar design done
AkinariHex Apr 11, 2024
0fb2dc3
search bar api request
AkinariHex Apr 12, 2024
e91e45a
search bar animations
AkinariHex Apr 13, 2024
56cdeb4
search bar litle animation improvement
AkinariHex Apr 13, 2024
e794d97
show player data correctly
AkinariHex Apr 13, 2024
cd6e840
switch theme with keybind
AkinariHex Apr 13, 2024
e4013f6
installed missing package
AkinariHex Apr 13, 2024
8da9ebd
Merge pull request #155 from osu-tournament-rating/fix/theme-switcher
hburn7 Apr 13, 2024
88a2c72
Merge pull request #156 from osu-tournament-rating/feature/search-bar
hburn7 Apr 15, 2024
6de09fe
Merge pull request #158 from osu-tournament-rating/develop
hburn7 Apr 16, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
156 changes: 89 additions & 67 deletions app/actions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,13 +25,13 @@ export async function getSession(onlyData: boolean = false) {
return {
isLogged: session?.isLogged,
id: session?.id,
userId: session?.userId,
playerId: session?.playerId,
osuId: session?.osuId,
osuCountry: session?.osuCountry,
osuPlayMode: session?.osuPlayMode,
osuPlayModeSelected: session?.osuPlayModeSelected,
username: session?.username,
roles: session?.roles,
scopes: session?.scopes,
accessToken: session?.accessToken,
};

Expand All @@ -40,7 +40,7 @@ export async function getSession(onlyData: boolean = false) {

export async function login(cookie: {
accessToken: string;
refreshToken: string;
refreshToken?: string;
accessExpiration?: number;
}) {
const session = await getSession();
Expand All @@ -56,12 +56,15 @@ export async function login(cookie: {

session.accessToken = cookie.accessToken;

await cookies().set('OTR-Refresh-Token', cookie.refreshToken, {
httpOnly: true,
path: '/',
sameSite: 'strict',
secure: process.env.NODE_ENV === 'production',
});
if (cookie?.refreshToken) {
await cookies().set('OTR-Refresh-Token', cookie.refreshToken, {
httpOnly: true,
path: '/',
sameSite: 'strict',
secure: process.env.NODE_ENV === 'production',
maxAge: 1209600,
});
}

const loggedUser = await getLoggedUser(cookie.accessToken);

Expand All @@ -72,21 +75,27 @@ export async function login(cookie: {
}

session.id = loggedUser.id;
session.userId = loggedUser.userId;
session.playerId = loggedUser.playerId;
session.osuId = loggedUser.osuId;
session.osuCountry = loggedUser.osuCountry;
session.osuPlayMode = loggedUser.osuPlayMode;
session.osuPlayModeSelected = loggedUser.osuPlayMode;
session.username = loggedUser.username;
session.roles = loggedUser.roles;
session.osuPlayModeSelected = loggedUser.osuPlayMode; // maybe to delete
session.username = loggedUser.osuUsername;
session.scopes = loggedUser.scopes;
session.isLogged = true;

await cookies().set('OTR-user-selected-osu-mode', loggedUser.osuPlayMode, {
httpOnly: true,
path: '/',
sameSite: 'strict',
secure: process.env.NODE_ENV === 'production',
maxAge: 1209600,
});

await session.save();

/* await changeOsuModeCookie(res.osuPlayMode); */
return NextResponse.redirect(
new URL('/', process.env.REACT_APP_ORIGIN_URL)
);
return NextResponse.redirect(new URL('/', process.env.REACT_APP_ORIGIN_URL));
}

export async function getLoggedUser(accessToken: string) {
Expand Down Expand Up @@ -169,7 +178,7 @@ export async function saveTournamentMatches(
const session = await getSession(true);

/* IF USER IS UNAUTHORIZED REDIRECT TO HOMEPAGE */
if (!session.userId) return redirect('/');
if (!session.id) return redirect('/');

try {
/* REGEX TO REMOVE ALL SPACES AND ENTERS */
Expand Down Expand Up @@ -199,15 +208,15 @@ export async function saveTournamentMatches(
rankRangeLowerBound: parseInt(formData.get('rankRestriction')),
teamSize: parseInt(formData.get('teamSize')),
mode: parseInt(formData.get('gameMode')),
submitterId: session?.userId ?? 0,
submitterId: session?.id ?? 0,
ids: matchIDs,
});

let isSubmissionVerified =
formData.get('verifierCheckBox') == 'on' ?? false;

await fetch(
`${process.env.REACT_APP_API_URL}/matches/batch?verified=${isSubmissionVerified}`,
let tournamentSubmit = await fetch(
`${process.env.REACT_APP_API_URL}/tournaments?verify=${isSubmissionVerified}`,
{
method: 'POST',
headers: {
Expand All @@ -218,32 +227,26 @@ export async function saveTournamentMatches(
credentials: 'include',
body: JSON.stringify(data),
}
)
.then((response) => {
if (response.status !== 200) {
throw new Error({
issues: [
{
path: ['serverError'],
message: response.body,
},
],
});
}
);

return {
status: 'success',
};
})
.then((data) => {
console.log(data);
})
.catch((error) => {
console.log(JSON.parse(error.message));
});
if (!tournamentSubmit?.ok) {
const errorMessage = await tournamentSubmit.text();

return {
error: {
status: tournamentSubmit.status,
text: tournamentSubmit.statusText,
message: errorMessage,
},
};
}

return {
status: 'success',
success: {
status: tournamentSubmit.status,
text: tournamentSubmit.statusText,
message: 'Tournament submitted successfully',
},
};
} catch (error) {
let errors = {};
Expand Down Expand Up @@ -292,7 +295,7 @@ export async function applyLeaderboardFilters(params: {}) {
let string = '';

params[key].forEach((value, index) => {
string += `${value}${index === 0 ? `&${key}=` : ''}`;
string += `${value}${index < params[key].length - 1 ? `&${key}=` : ''}`;
});

return (urlStringObject[key] = string);
Expand All @@ -312,8 +315,7 @@ export async function fetchLeaderboard(params: {}) {

/* MISSING MODE, PLAYERID */

const { type, page, rank, rating, matches, winrate, inclTier, exclTier } =
params;
const { type, page, rank, rating, matches, winrate, tiers } = params;

const tierFilters = {
bronze: 'bronze',
Expand Down Expand Up @@ -367,16 +369,10 @@ export async function fetchLeaderboard(params: {}) {
.sort(compareNumbers))
: undefined;

inclTier
? Array.isArray(inclTier)
? (paramsToProcess.inclTier = inclTier)
: (paramsToProcess.inclTier = Array(inclTier))
: undefined;

exclTier
? Array.isArray(exclTier)
? (paramsToProcess.exclTier = exclTier)
: (paramsToProcess.exclTier = Array(exclTier))
tiers
? Array.isArray(tiers)
? (paramsToProcess.tiers = tiers)
: (paramsToProcess.tiers = Array(tiers))
: undefined;

const queryCheck = await LeaderboardsQuerySchema.safeParse({
Expand Down Expand Up @@ -451,19 +447,12 @@ export async function fetchLeaderboard(params: {}) {
}

/* Check included tiers filter */
if (queryCheck.data.inclTier) {
queryCheck.data.inclTier.forEach((tier) => {
if (queryCheck.data.tiers) {
queryCheck.data.tiers.forEach((tier) => {
backendObject[tierFilters[tier]] = true;
});
}

/* Check included tiers filter */
if (queryCheck.data.exclTier) {
queryCheck.data.exclTier.forEach((tier) => {
backendObject[tierFilters[tier]] = false;
});
}

let backendString = new URLSearchParams(backendObject).toString();

let data = await fetch(
Expand Down Expand Up @@ -528,7 +517,7 @@ export async function fetchUserPage(player: string | number) {

let res = await fetch(
`${process.env.REACT_APP_API_URL}/stats/${player}${
session?.userId ? `?comparerId=${session?.userId}` : ''
session?.playerId ? `?comparerId=${session?.playerId}` : ''
}`,
{
headers: {
Expand Down Expand Up @@ -563,7 +552,9 @@ export async function paginationParamsToURL(params: {}) {
let string = `${index !== 0 ? '&' : ''}${key}=`;

params[key].forEach((value, index) => {
string += `${value}${index === 0 ? `&${key}=` : ''}`;
string += `${value}${
index < params[key].length - 1 ? `&${key}=` : ''
}`;
});

return (url += `${string}`);
Expand All @@ -577,3 +568,34 @@ export async function paginationParamsToURL(params: {}) {

return url;
}

export async function fetchSearchData(prevState: any, formData: FormData) {
const session = await getSession(true);

if (!session.id) return redirect('/');

let searchText = formData.get('search');

let searchData = await fetch(
`${process.env.REACT_APP_API_URL}/search?searchKey=${searchText}`,
{
method: 'GET',
headers: {
'Content-Type': 'application/json',
'Access-Control-Allow-Origin': `${process.env.REACT_APP_ORIGIN_URL}`,
Authorization: `Bearer ${session.accessToken}`,
},
}
);

if (!searchData?.ok) {
throw new Error('Error from server on search!');
}

searchData = await searchData.json();

return {
status: 'success',
search: searchData,
};
}
3 changes: 2 additions & 1 deletion app/auth/route.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,9 @@ export async function GET(request: Request) {
const refreshToken = searchParams.get('refreshToken');
const accessToken = searchParams.get('accessToken');

// Refresh session if refreshToken is set
if (refreshToken && accessToken) {
return await login({ accessToken, refreshToken });
return await login({ accessToken });
}

if (code) {
Expand Down
47 changes: 47 additions & 0 deletions app/dashboard/error.module.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
.errorDiv {
position: relative;
min-height: 60dvh;
height: 70dvh;
max-height: 70dvh;
margin: var(--main-padding);
margin-top: 0;
}

.errorDiv .content {
height: 100%;
width: 100%;
position: absolute;
display: flex;
flex-flow: column;
align-items: center;
justify-content: center;
padding: var(--internal-gap);
gap: var(--internal-gap);
z-index: 2;
}

.errorDiv img {
z-index: 1;
}

.errorDiv h1 {
font-size: 4rem;
}

.errorDiv span {
font-size: 3.5rem;
letter-spacing: -2%;
text-align: center;
max-width: 40vw;
}

.errorDiv button {
margin-top: 1.3rem;
padding: 1rem 3rem;
width: fit-content;
font-weight: 500;
cursor: pointer;
border-radius: 0.4rem;
font-size: 1rem;
transition: background-color 0.2s ease-out;
}
57 changes: 57 additions & 0 deletions app/dashboard/error.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
'use client';

import backgroundError from '@/public/images/error-background.svg';
import Image from 'next/image';
import { useEffect } from 'react';
import Balancer from 'react-wrap-balancer';
import styles from './error.module.css';

const errors = {
'4': {
title: 'No data',
message: "You don't have any data for the selected ruleset",
reloadBtn: true,
},
'404': {
title: '404',
message: "We don't have that page",
reloadBtn: false,
},
};

export default function Error({
error,
reset,
}: {
error: Error & { digest?: string };
reset: () => void;
}) {
useEffect(() => {
// Log the error to an error reporting service
console.error(error);
}, [error]);

let errorContent = !isNaN(error.message)
? errors[error.message]
: errors['404'];

return (
<div className={styles.errorDiv}>
<Image src={backgroundError} alt="Error background" fill />
<div className={styles.content}>
<h1>{errorContent.title}</h1>
<span>{errorContent.message}</span>
{errorContent.reloadBtn && (
<button
onClick={
// Attempt to recover by trying to re-render the segment
() => reset()
}
>
Try again
</button>
)}
</div>
</div>
);
}
Loading
Loading