Skip to content

Commit

Permalink
Added loading state to buttons
Browse files Browse the repository at this point in the history
  • Loading branch information
gastongaiduk committed Jan 4, 2025
1 parent 6f0b213 commit ad8129f
Show file tree
Hide file tree
Showing 8 changed files with 81 additions and 13 deletions.
37 changes: 33 additions & 4 deletions src/components/GameLeaderboards.vue
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,7 @@ async function refreshSubscriptionToGame() {
}
async function subscribe() {
loadingSubscription.value = true
let {error} = await supabase
.from('game_subscriptions')
.insert({game_id: props.id, user_id: user.user_id})
Expand All @@ -77,9 +78,11 @@ async function subscribe() {
await refreshSubscriptionToGame()
hideSubscribeModal()
loadingSubscription.value = false
}
async function unsubscribe() {
loadingSubscription.value = true
let {error} = await supabase
.from('game_subscriptions')
.delete()
Expand All @@ -91,16 +94,19 @@ async function unsubscribe() {
await refreshSubscriptionToGame()
hideUnsubscribeModal()
loadingSubscription.value = false
}
async function refreshLeaderboards() {
loadingRefresh.value = true;
try {
leaderboards.value = null;
games.setGameLeaderboards(Number(props.id), await repository.fetchLeaderboards(props.id));
leaderboards.value = games.getGameLeaderboards(Number(props.id));
} catch (error) {
console.error('Error fetching last played games:', error);
}
loadingRefresh.value = false;
}
const props = defineProps({
Expand All @@ -113,41 +119,59 @@ const props = defineProps({
const selectedGame = ref<Game | null>(null);
const leaderboards = ref<GameLeaderboards | null>(null);
const subscribedToGame = ref<boolean | null>(null);
const loadingSubscription = ref<boolean>(false);
const loadingRefresh = ref<boolean>(false);
onMounted(async () => {
if (!user.isSet()) {
await router.push("/login")
return;
}
loadingSubscription.value = true;
selectedGame.value = postStore.getSelectedGameLeaderboards();
if (games.hasGameLeaderboard(Number(props.id))) {
leaderboards.value = games.getGameLeaderboards(Number(props.id));
await refreshSubscriptionToGame()
loadingSubscription.value = false;
return;
}
await refreshLeaderboards();
await refreshSubscriptionToGame()
loadingSubscription.value = false;
});
</script>

<template>
<div class="leaderboard-container">
<button class="back-button" @click="goBack"><i class="fa fa-arrow-left" aria-hidden="true"></i> Back</button>
<Tooltip text="Refresh content" position="left" style="float: right">
<button class="refresh-button" @click="refreshLeaderboards"><i class="fa fa-refresh"></i></button>
<button class="refresh-button" @click="refreshLeaderboards" :disabled="loadingRefresh">
<i v-if="loadingRefresh" class="fa fa-spinner fa-spin"></i>
<i v-else class="fa fa-refresh"></i>
</button>
</Tooltip>
<h1 class="leaderboard-title">{{ selectedGame?.Title }}</h1>
<div v-if="leaderboards && leaderboards.Results.length" style="text-align: center">
<button v-if="!subscribedToGame" class="subscribe-button" @click="showSubscribeModal">Subscribe</button>
<button v-if="!subscribedToGame" class="subscribe-button" @click="showSubscribeModal" :disabled="loadingSubscription">
<i v-if="loadingSubscription" class="fa fa-spinner fa-spin"></i>
<span v-else>
Subscribe
</span>
</button>
<ConfirmModal :isVisible="isSubscribeModalVisible" @confirm="subscribe" @nope="hideSubscribeModal"
:title="'Subscribe to ' + selectedGame?.Title + '?'"
:text="'Receive updates when a friend beats any of your scores in ' + selectedGame?.Title + '? (no emails or push notifications are sent)'"
/>

<button v-if="subscribedToGame" class="unsubscribe-button" @click="showUnsubscribeModal">Unsubscribe</button>
<button v-if="subscribedToGame" class="unsubscribe-button" @click="showUnsubscribeModal" :disabled="loadingSubscription">
<i v-if="loadingSubscription" class="fa fa-spinner fa-spin"></i>
<span v-else>
Unsubscribe
</span>
</button>
<ConfirmModal :isVisible="isUnsubscribeModalVisible" @confirm="unsubscribe" @nope="hideUnsubscribeModal"
:title="'Unsubscribe from ' + selectedGame?.Title + '?'"
:text="'Don\'t receive updates for this game when a friend beats any of your scores in ' + selectedGame?.Title + '?'"
Expand Down Expand Up @@ -183,7 +207,7 @@ onMounted(async () => {
color: #e0e1dd;
padding: 20px;
border-radius: 15px;
box-shadow: 0px 0px 15px rgba(0, 0, 0, 0.5);
box-shadow: 0 0 15px rgba(0, 0, 0, 0.5);
font-family: 'Press Start 2P', cursive;
}
Expand Down Expand Up @@ -212,6 +236,11 @@ onMounted(async () => {
border-radius: 10px;
}
button:disabled {
cursor: not-allowed;
opacity: 0.6;
}
.unsubscribe-button {
background-color: #22223b;
color: #e0e1dd;
Expand Down
8 changes: 7 additions & 1 deletion src/components/Home.vue
Original file line number Diff line number Diff line change
Expand Up @@ -23,13 +23,15 @@ function selectGameLeaderboards(game: Game) {
}
async function refreshGames() {
loadingRefresh.value = true;
try {
lastPlayedGames.value = null;
games.setLastPlayedGames(await repository.fetchLastPlayedGames());
lastPlayedGames.value = games.lastPlayedGames;
} catch (error) {
console.error('Error fetching last played games:', error);
}
loadingRefresh.value = false;
}
async function updatesCount() {
Expand Down Expand Up @@ -62,6 +64,7 @@ async function updatesCount() {
const apiUrl = import.meta.env.VITE_API_URL;
const lastPlayedGames = ref<GameList | null>(null);
const updatesNumber = ref<number | null>(null);
const loadingRefresh = ref<boolean>(false);
onMounted(async () => {
if (!user.isLoggedIn()) {
Expand Down Expand Up @@ -89,7 +92,10 @@ onMounted(async () => {
<div class="retro-container">
<BurgerMenu :updates-number="updatesNumber ? updatesNumber : 0"></BurgerMenu>
<Tooltip text="Refresh content" position="left" style="float: right">
<button class="refresh-button" @click="refreshGames"><i class="fa fa-refresh"></i></button>
<button class="refresh-button" @click="refreshGames" :disabled="loadingRefresh">
<i v-if="loadingRefresh" class="fa fa-spinner fa-spin"></i>
<i v-else class="fa fa-refresh"></i>
</button>
</Tooltip>
<h1 class="retro-title">Welcome {{ user.username }}</h1>
<div v-if="games.lastPlayedGames">
Expand Down
13 changes: 9 additions & 4 deletions src/components/LeaderboardEntries.vue
Original file line number Diff line number Diff line change
Expand Up @@ -35,15 +35,18 @@ const props = defineProps({
const selectedGame = ref<Game | null>(null);
const selectedLeaderboard = ref<Leaderboard | null>(null);
const entries = ref<LeaderboardEntries | null>(null);
const loadingRefresh = ref<boolean>(false);
async function refreshScores() {
loadingRefresh.value = true;
try {
entries.value = null;
games.setLeaderboardEntries(Number(props.id), await repository.fetchLeaderboardEntries(props.id));
entries.value = games.getLeaderboardEntries(Number(props.id));
} catch (error) {
console.error('Error fetching last played games:', error);
}
loadingRefresh.value = false;
}
onMounted(async () => {
Expand Down Expand Up @@ -121,7 +124,10 @@ function isFriend(user: string) {
<div class="entries-container">
<button class="back-button" @click="goBack"><i class="fa fa-arrow-left" aria-hidden="true"></i> Back</button>
<Tooltip text="Refresh content" position="left" style="float: right">
<button class="refresh-button" @click="refreshScores"><i class="fa fa-refresh"></i></button>
<button class="refresh-button" @click="refreshScores" :disabled="loadingRefresh">
<i v-if="loadingRefresh" class="fa fa-spinner fa-spin"></i>
<i v-else class="fa fa-refresh"></i>
</button>
</Tooltip>
<h1 class="entries-title">{{ selectedLeaderboard?.Title }}</h1>
<h2 class="entries-title">{{ selectedGame?.Title }}</h2>
Expand Down Expand Up @@ -151,7 +157,7 @@ function isFriend(user: string) {
color: #e0e1dd;
padding: 20px;
border-radius: 15px;
box-shadow: 0px 0px 15px rgba(0, 0, 0, 0.5);
box-shadow: 0 0 15px rgba(0, 0, 0, 0.5);
font-family: 'Press Start 2P', cursive;
}
Expand Down Expand Up @@ -221,8 +227,7 @@ h2.entries-title {
}
.isMe {
border: solid #f5a623;
border-width: thick;
border: thick solid #f5a623;
}
.loading-text {
Expand Down
9 changes: 8 additions & 1 deletion src/components/Login.vue
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ const user = useUserStore();
const emailInput = ref("");
const passInput = ref("");
const loading = ref(false);
async function handleRACredentials() {
const options = {
Expand All @@ -31,13 +32,15 @@ async function handleRACredentials() {
}
async function handleSubmit() {
loading.value = true;
const {data, error} = await supabase.auth.signInWithPassword({
email: emailInput.value,
password: passInput.value,
})
if (error) {
alert(error.message);
loading.value = false;
return;
}
Expand All @@ -49,6 +52,7 @@ async function handleSubmit() {
onMounted(async () => {
if (user.isLoggedIn()) {
loading.value = true;
await handleRACredentials();
await router.push("/")
}
Expand All @@ -70,7 +74,10 @@ onMounted(async () => {
<span class="clickable link">
<a @click="router.push('sign-up')">Or sign-up <i class="fa fa-arrow-right"></i></a>
</span>
<button type="submit" class="form-button">Submit</button>
<button type="submit" class="form-button" :disabled="loading">
<i v-if="loading" class="fa fa-spinner fa-spin"></i>
<span v-else>Submit</span>
</button>
</div>
</form>
</div>
Expand Down
9 changes: 8 additions & 1 deletion src/components/RACredentials.vue
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,10 @@ const user = useUserStore();
const usernameInput = ref("");
const keyInput = ref("");
const loading = ref(false);
async function handleSubmit() {
loading.value = true;
const options = {
method: 'POST',
url: import.meta.env.VITE_SUPABASE_URL + '/functions/v1/set-ra-credentials',
Expand All @@ -34,10 +36,12 @@ async function handleSubmit() {
if (errorMessage.includes("duplicate key value violates unique constraint")) {
alert("Username already assigned to a user. Contact the administrator if you need assistance.");
loading.value = false;
return;
}
alert(error.response.data.error);
loading.value = false;
return;
}
Expand Down Expand Up @@ -69,7 +73,10 @@ onMounted(() => {
</label>
<input type="password" id="key" v-model="keyInput" class="form-input" required>
</div>
<button type="submit" class="form-button">Submit</button>
<button type="submit" class="form-button" :disabled="loading">
<i v-if="loading" class="fa fa-spinner fa-spin"></i>
<span v-else>Submit</span>
</button>
</form>
</div>
</template>
Expand Down
9 changes: 8 additions & 1 deletion src/components/SingUp.vue
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,13 @@ const user = useUserStore();
const emailInput = ref("");
const passInput = ref("");
const passConfirmInput = ref("");
const loading = ref(false);
async function handleSubmit() {
loading.value = true;
if (passInput.value !== passConfirmInput.value) {
alert("Passwords do not match");
loading.value = false;
return;
}
Expand All @@ -28,6 +31,7 @@ async function handleSubmit() {
if (error) {
console.log(error);
alert("Error, please try again later")
loading.value = false;
return;
}
Expand Down Expand Up @@ -64,7 +68,10 @@ onMounted(() => {
<span class="clickable link">
<a @click="router.push('login')">Or login <i class="fa fa-arrow-right"></i></a>
</span>
<button type="submit" class="form-button">Submit</button>
<button type="submit" class="form-button" :disabled="loading">
<i v-if="loading" class="fa fa-spinner fa-spin"></i>
<span v-else>Submit</span>
</button>
</div>
</form>
</div>
Expand Down
2 changes: 1 addition & 1 deletion src/repositories/GameRepository.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ class GameRepository {
public async fetchLastPlayedGames(): Promise<GameList> {
try {
const response = await axios.get(`${this.url}/API/API_GetUserRecentlyPlayedGames.php`, {
params: {y: this.user.key, u: this.user.username, c: 10}
params: {y: this.user.key, u: this.user.username, c: 20}
});
return response.data as GameList;
} catch (error) {
Expand Down
7 changes: 7 additions & 0 deletions src/router/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,13 @@ const routes: Array<RouteRecordRaw> = [
const router = createRouter({
history: createWebHashHistory(),
routes,
scrollBehavior(to, from, savedPosition) {
if (savedPosition) {
return savedPosition
} else {
return { top: 0 }
}
}
});

export default router;

0 comments on commit ad8129f

Please sign in to comment.