Files
endurain/frontend/app/src/components/Settings/SettingsIntegrationsZone.vue
João Vitória Silva 746cf47da6 BMI logic + fixes
[aux] added auxiliary scripts
[backend] added error logic to error printing
[backend] rollbacked changes from Datetime to Timestamp
[backend] added body composition sync from Garmin
[backend] added additional validations for empty .gpx files
[backend] add calculate BMI logic
[backend] add BMI calculation in migration
[backend] added Timezone logic to Strava activity import
[frontend] removed block that prevent deleting Strava or GC activity
[frontend] added new generic modal for single number input
[frontend] replaced modal that retrieves Strava and GC activities for number of days with new generic modal
[frontend] added shoes gear in add gear to walk and hike activities
[frontend] minor bug fixes
2024-12-10 17:35:56 +00:00

300 lines
13 KiB
Vue

<template>
<div class="col">
<!-- list zone -->
<ul class="list-group list-group-flush">
<!-- strava zone -->
<li class="list-group-item d-flex justify-content-between">
<div class="d-flex align-items-center">
<font-awesome-icon class="me-2" :icon="['fab', 'strava']" size="2x" />
<div class="ms-3">
<div class="fw-bold">
{{ $t("settingsIntegrationsZone.stravaIntegrationTitle") }}
</div>
{{ $t("settingsIntegrationsZone.stravaIntegrationBody") }}
</div>
</div>
<div class="d-flex align-items-center">
<!-- connect button -->
<a href="#" class="btn btn-primary" v-if="authStore.user.is_strava_linked == 0" @click="submitConnectStrava">{{ $t("settingsIntegrationsZone.buttonConnect") }}</a>
<!-- retrieve activities and other buttons -->
<div class="dropdown" v-else>
<button class="btn btn-secondary dropdown-toggle" type="button" data-bs-toggle="dropdown" aria-expanded="false">
{{ $t("settingsIntegrationsZone.buttonDropdownOptions") }}
</button>
<ul class="dropdown-menu">
<li>
<!-- retrieve strava activities by days -->
<a class="dropdown-item" href="#" role="button" data-bs-toggle="modal" data-bs-target="#retrieveStravaActivitiesByDaysModal">{{ $t("settingsIntegrationsZone.modalRetrieveActivitiesByDaysTitle") }}</a>
</li>
<li>
<!-- retrieve gear -->
<a href="#" class="dropdown-item" @click="submitRetrieveStravaGear">{{ $t("settingsIntegrationsZone.buttonRetrieveGear") }}</a>
</li>
<li>
<!-- unlink Strava -->
<a href="#" class="dropdown-item" role="button" data-bs-toggle="modal" data-bs-target="#unlinkStravaModal">{{ $t("settingsIntegrationsZone.buttonUnlink") }}</a>
</li>
</ul>
</div>
</div>
</li>
<!-- bulk import zone -->
<li class="list-group-item d-flex justify-content-between">
<div class="d-flex align-items-center">
<font-awesome-icon :icon="['fas', 'file-import']" size="2x" />
<div class="ms-3">
<div class="fw-bold">
{{ $t("settingsIntegrationsZone.bulkImportIntegrationTitle") }}
</div>
{{ $t("settingsIntegrationsZone.bulkImportIntegrationBody") }}
</div>
</div>
<div class="d-flex align-items-center">
<!-- import button -->
<a href="#" class="btn btn-primary" role="button" @click="submitBulkImport">{{ $t("settingsIntegrationsZone.buttonBulkImport") }}</a>
</div>
</li>
<!-- Garmin Connect zone -->
<li class="list-group-item d-flex justify-content-between">
<div class="d-flex align-items-center">
<!--<font-awesome-icon :icon="['fas', 'file-import']" size="2x" />-->
<img src="/src/assets/garminconnect/Garmin_Connect_app_1024x1024-02.png" alt="Garmin Connect logo" height="32" />
<div class="ms-3">
<div class="fw-bold">
{{ $t("settingsIntegrationsZone.garminConnectIntegrationTitle") }}
</div>
{{ $t("settingsIntegrationsZone.garminConnectIntegrationBody") }}
</div>
</div>
<div class="d-flex align-items-center">
<!-- connect button -->
<a href="#" class="btn btn-primary" v-if="authStore.user.is_garminconnect_linked == 0" data-bs-toggle="modal" data-bs-target="#garminConnectAuthModal">{{ $t("settingsIntegrationsZone.buttonConnect") }}</a>
<!-- retrieve activities and other buttons -->
<div class="dropdown" v-else>
<button class="btn btn-secondary dropdown-toggle" type="button" data-bs-toggle="dropdown" aria-expanded="false">
{{ $t("settingsIntegrationsZone.buttonDropdownOptions") }}
</button>
<ul class="dropdown-menu">
<li>
<!-- retrieve garmin connect activities by days -->
<a class="dropdown-item" href="#" role="button" data-bs-toggle="modal" data-bs-target="#retrieveGarminConnectActivitiesByDaysModal">{{ $t("settingsIntegrationsZone.modalRetrieveActivitiesByDaysTitle") }}</a>
</li>
<li>
<!-- retrieve gear -->
<a href="#" class="dropdown-item" @click="submitRetrieveGarminConnectGear">{{ $t("settingsIntegrationsZone.buttonRetrieveGear") }}</a>
</li>
<li>
<!-- unlink Garmin Connect -->
<a href="#" class="dropdown-item" role="button" data-bs-toggle="modal" data-bs-target="#unlinkGarminConnectModal">{{ $t("settingsIntegrationsZone.buttonUnlink") }}</a>
</li>
</ul>
</div>
</div>
</li>
</ul>
<!-- modal retrieve Strava activities by days -->
<ModalComponentNumberInput modalId="retrieveStravaActivitiesByDaysModal" :title="t('settingsIntegrationsZone.modalRetrieveActivitiesByDaysTitle')" :numberFieldLabel="`${t('settingsIntegrationsZone.modalRetrieveActivitiesByDaysLabel')}`" :actionButtonType="`success`" :actionButtonText="t('settingsIntegrationsZone.modalRetrieveButton')" @numberToEmitAction="submitRetrieveStravaActivities"/>
<!-- modal unlink Strava -->
<ModalComponent modalId="unlinkStravaModal" :title="t('settingsIntegrationsZone.modalUnlinkStravaTitle')" :body="`${t('settingsIntegrationsZone.modalUnlinkStravaBody')}`" :actionButtonType="`danger`" :actionButtonText="t('settingsIntegrationsZone.modalUnlinkStravaTitle')" @submitAction="buttonStravaUnlink"/>
<!-- modal garmin connect auth -->
<GarminConnectLoginModalComponent />
<!-- modal retrieve Garmin Connect activities by days -->
<ModalComponentNumberInput modalId="retrieveGarminConnectActivitiesByDaysModal" :title="t('settingsIntegrationsZone.modalRetrieveActivitiesByDaysTitle')" :numberFieldLabel="`${t('settingsIntegrationsZone.modalRetrieveActivitiesByDaysLabel')}`" :actionButtonType="`success`" :actionButtonText="t('settingsIntegrationsZone.modalRetrieveButton')" @numberToEmitAction="submitRetrieveGarminConnectActivities"/>
<!-- modal unlink Garmin Connect -->
<ModalComponent modalId="unlinkGarminConnectModal" :title="t('settingsIntegrationsZone.modalUnlinkGarminConnectTitle')" :body="`${t('settingsIntegrationsZone.modalUnlinkGarminConnectBody')}`" :actionButtonType="`danger`" :actionButtonText="t('settingsIntegrationsZone.modalUnlinkGarminConnectTitle')" @submitAction="buttonGarminConnectUnlink"/>
</div>
</template>
<script>
import { ref } from "vue";
import { useI18n } from "vue-i18n";
// Import Notivue push
import { push } from "notivue";
// Importing the stores
import { useAuthStore } from "@/stores/authStore";
// Importing the services
import { strava } from "@/services/stravaService";
import { activities } from "@/services/activitiesService";
import { garminConnect } from "@/services/garminConnectService";
// Import the components
import ModalComponent from "@/components/Modals/ModalComponent.vue";
import ModalComponentNumberInput from "@/components/Modals/ModalComponentNumberInput.vue";
import GarminConnectLoginModalComponent from "./SettingsIntegrations/GarminConnectLoginModalComponent.vue";
//import Modal from 'bootstrap/js/dist/modal';
export default {
components: {
ModalComponent,
ModalComponentNumberInput,
GarminConnectLoginModalComponent,
},
setup() {
const authStore = useAuthStore();
const { locale, t } = useI18n();
async function submitConnectStrava() {
const array = new Uint8Array(16);
window.crypto.getRandomValues(array);
const state = Array.from(array, (byte) =>
byte.toString(16).padStart(2, "0"),
).join("");
try {
await strava.setUniqueUserStateStravaLink(state);
strava.linkStrava(state);
} catch (error) {
// If there is an error, show the error alert.
push.error(
`${t("settingsIntegrationsZone.errorMessageUnableToLinkStrava")} - ${error}`,
);
}
}
async function submitRetrieveStravaActivities(daysToRetrieveStrava) {
try {
await strava.getStravaActivitiesLastDays(daysToRetrieveStrava);
// Show the loading alert.
push.info(
t(
"settingsIntegrationsZone.loadingMessageRetrievingStravaActivities",
),
);
} catch (error) {
// If there is an error, show the error alert.
push.error(
`${t("settingsIntegrationsZone.errorMessageUnableToGetStravaActivities")} - ${error}`,
);
}
}
async function submitRetrieveStravaGear() {
try {
await strava.getStravaGear();
// Show the loading alert.
push.success(
t("settingsIntegrationsZone.loadingMessageRetrievingStravaGear"),
);
} catch (error) {
// If there is an error, show the error alert.
push.error(
`${t("settingsIntegrationsZone.errorMessageUnableToGetStravaGear")} - ${error}`,
);
}
}
async function buttonStravaUnlink() {
// Set the loading message
const notification = push.promise(t('settingsIntegrationsZone.processingMessageUnlinkStrava'));
try {
await strava.unlinkStrava();
// Set the user object with the is_strava_linked property set to 0.
const user = authStore.user;
user.is_strava_linked = 0;
authStore.setUser(user, locale);
// Show the success alert.
notification.resolve(t("settingsIntegrationsZone.successMessageStravaUnlinked"));
} catch (error) {
// If there is an error, show the error alert.
notification.reject(
`${t("settingsIntegrationsZone.errorMessageUnableToUnlinkStrava")} - ${error}`,
);
}
}
async function submitBulkImport() {
try {
await activities.bulkImportActivities();
// Show the loading alert.
push.info(t("settingsIntegrationsZone.loadingMessageBulkImport"));
} catch (error) {
// If there is an error, show the error alert.
push.error(
`${t("settingsIntegrationsZone.errorMessageUnableToImportActivities")} - ${error}`,
);
}
}
async function submitRetrieveGarminConnectActivities(daysToRetrieveGarmin) {
try {
await garminConnect.getGarminConnectActivitiesLastDays(daysToRetrieveGarmin);
// Show the loading alert.
push.info(
t(
"settingsIntegrationsZone.loadingMessageRetrievingGarminConnectActivities",
),
);
} catch (error) {
// If there is an error, show the error alert.
push.error(
`${t("settingsIntegrationsZone.errorMessageUnableToGetGarminConnectActivities")} - ${error}`,
);
}
}
async function submitRetrieveGarminConnectGear() {
try {
await garminConnect.getGarminConnectGear();
// Show the loading alert.
push.success(
t("settingsIntegrationsZone.loadingMessageRetrievingGarminConnectGear"),
);
} catch (error) {
// If there is an error, show the error alert.
push.error(
`${t("settingsIntegrationsZone.errorMessageUnableToGetGarminConnectGear")} - ${error}`,
);
}
}
async function buttonGarminConnectUnlink() {
// Set the loading message
const notification = push.promise(t('settingsIntegrationsZone.processingMessageUnlinkGarminConnect'));
try {
await garminConnect.unlinkGarminConnect();
// Set the user object with the is_garminconnect_linked property set to 0.
const user = authStore.user;
user.is_garminconnect_linked = 0;
authStore.setUser(user, locale);
// Show the success alert.
notification.resolve(t("settingsIntegrationsZone.successMessageGarminConnectUnlinked"));
} catch (error) {
// If there is an error, show the error alert.
notification.reject(
`${t("settingsIntegrationsZone.errorMessageUnableToUnlinkGarminConnect")} - ${error}`,
);
}
}
return {
authStore,
t,
submitConnectStrava,
submitRetrieveStravaActivities,
submitRetrieveStravaGear,
buttonStravaUnlink,
submitBulkImport,
submitRetrieveGarminConnectActivities,
submitRetrieveGarminConnectGear,
buttonGarminConnectUnlink,
};
},
};
</script>