All checks were successful
Deploy Preprod / Build and Deploy to Preprod (push) Successful in 28s
Backend : - Blueprint pochet : champ hiddenProjects - Route API toggle-hidden-project.php - Controller site.php : retourne hiddenProjects + uuid dans projects Frontend : - Store user : hiddenProjects, visibleProjects, toggleHiddenProject() - Store projects : filtrage automatique des projets masqués - Store api : fonction toggleHiddenProject() - Account.vue : section projets avec cartes horizontales + boutons toggle - Affichage pour Pochet (avec toggle) et Client (sans toggle) - Section client masquée pour Pochet Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
444 lines
19 KiB
Vue
444 lines
19 KiB
Vue
<template>
|
|
<main class="flex flex-col items-stretch | w-full">
|
|
<header
|
|
v-if="user.name"
|
|
class="flex | bg-white rounded-2xl | p-8"
|
|
style="height: 3.5rem"
|
|
>
|
|
<h1 class="font-serif | px-8">{{ user.name }}</h1>
|
|
</header>
|
|
|
|
<div class="auto-grid" style="--min: 20rem">
|
|
<section
|
|
:class="{ 'is-editing': isEditingEmail }"
|
|
class="bg-white rounded-2xl px-16 py-24"
|
|
aria-labelledby="email-label"
|
|
>
|
|
<h2 class="sr-only" id="email-label">Email</h2>
|
|
<div
|
|
class="field | flow w-full"
|
|
role="group"
|
|
aria-labelledby="username"
|
|
>
|
|
<label for="username" class="text-grey-700">Email</label>
|
|
<input
|
|
v-if="isEditingEmail"
|
|
type="email"
|
|
v-model="email"
|
|
id="username"
|
|
placeholder="mail@exemple.com"
|
|
autocomplete="username"
|
|
class="w-full rounded-md border border-grey-200 px-16 py-12 mt-8"
|
|
:class="{ invalid: !isEmailValid }"
|
|
required
|
|
@keyup.escape="isEditingEmail = false"
|
|
@keyup.enter="isEmailValid ? updateEmail() : false"
|
|
/>
|
|
<input
|
|
v-else
|
|
type="email"
|
|
:value="user.email"
|
|
id="username"
|
|
class="w-full rounded-md border border-grey-200 px-16 py-12 mt-8"
|
|
disabled
|
|
/>
|
|
<button
|
|
v-if="isEditingEmail"
|
|
class="btn | w-full text-md"
|
|
@click="updateEmail"
|
|
:disabled="!isEmailValid"
|
|
>
|
|
{{ emailBtn.text }}
|
|
</button>
|
|
<button
|
|
v-else
|
|
@click="isEditingEmail = true"
|
|
class="btn | w-full text-md"
|
|
>
|
|
Modifier
|
|
</button>
|
|
<button
|
|
v-if="isEditingEmail"
|
|
class="btn btn--secondary | w-full text-md"
|
|
@click="isEditingEmail = false"
|
|
>
|
|
Annuler
|
|
</button>
|
|
</div>
|
|
</section>
|
|
|
|
<section
|
|
:class="{ 'is-editing': isEditingEmail }"
|
|
class="bg-white rounded-2xl px-16 py-24"
|
|
aria-labelledby="password-label"
|
|
>
|
|
<h2 class="sr-only" id="password-label">Mot de passe</h2>
|
|
<div class="flow">
|
|
<div class="field | w-full" role="group" aria-labelledby="password">
|
|
<label for="password" class="text-grey-700"
|
|
>Nouveau mot de passe</label
|
|
>
|
|
<input
|
|
:type="isPasswordVisible ? 'text' : 'password'"
|
|
v-model="password"
|
|
id="password"
|
|
placeholder="Minimum 8 caractères"
|
|
autocomplete="current-password"
|
|
autocapitalize="none"
|
|
autocorrect="off"
|
|
spellcheck="false"
|
|
class="w-full rounded-md border border-grey-200 px-16 py-12 mt-8"
|
|
:class="{ invalid: password.length < 8 }"
|
|
required
|
|
/>
|
|
<button
|
|
class="btn btn--white btn--icon"
|
|
type="button"
|
|
:aria-pressed="isPasswordVisible ? 'true' : 'false'"
|
|
aria-controls="password"
|
|
@click="isPasswordVisible = !isPasswordVisible"
|
|
:title="
|
|
isPasswordVisible
|
|
? 'Masquer le mot de passe'
|
|
: 'Afficher le mot de passe'
|
|
"
|
|
>
|
|
<svg
|
|
aria-hidden="true"
|
|
focusable="false"
|
|
xmlns="http://www.w3.org/2000/svg"
|
|
viewBox="0 0 24 24"
|
|
width="16"
|
|
height="16"
|
|
fill="currentColor"
|
|
>
|
|
<path
|
|
v-if="isPasswordVisible"
|
|
d="M12.0003 3C17.3924 3 21.8784 6.87976 22.8189 12C21.8784 17.1202 17.3924 21 12.0003 21C6.60812 21 2.12215 17.1202 1.18164 12C2.12215 6.87976 6.60812 3 12.0003 3ZM12.0003 19C16.2359 19 19.8603 16.052 20.7777 12C19.8603 7.94803 16.2359 5 12.0003 5C7.7646 5 4.14022 7.94803 3.22278 12C4.14022 16.052 7.7646 19 12.0003 19ZM12.0003 16.5C9.51498 16.5 7.50026 14.4853 7.50026 12C7.50026 9.51472 9.51498 7.5 12.0003 7.5C14.4855 7.5 16.5003 9.51472 16.5003 12C16.5003 14.4853 14.4855 16.5 12.0003 16.5ZM12.0003 14.5C13.381 14.5 14.5003 13.3807 14.5003 12C14.5003 10.6193 13.381 9.5 12.0003 9.5C10.6196 9.5 9.50026 10.6193 9.50026 12C9.50026 13.3807 10.6196 14.5 12.0003 14.5Z"
|
|
></path>
|
|
<path
|
|
v-else
|
|
d="M17.8827 19.2968C16.1814 20.3755 14.1638 21.0002 12.0003 21.0002C6.60812 21.0002 2.12215 17.1204 1.18164 12.0002C1.61832 9.62282 2.81932 7.5129 4.52047 5.93457L1.39366 2.80777L2.80788 1.39355L22.6069 21.1925L21.1927 22.6068L17.8827 19.2968ZM5.9356 7.3497C4.60673 8.56015 3.6378 10.1672 3.22278 12.0002C4.14022 16.0521 7.7646 19.0002 12.0003 19.0002C13.5997 19.0002 15.112 18.5798 16.4243 17.8384L14.396 15.8101C13.7023 16.2472 12.8808 16.5002 12.0003 16.5002C9.51498 16.5002 7.50026 14.4854 7.50026 12.0002C7.50026 11.1196 7.75317 10.2981 8.19031 9.60442L5.9356 7.3497ZM12.9139 14.328L9.67246 11.0866C9.5613 11.3696 9.50026 11.6777 9.50026 12.0002C9.50026 13.3809 10.6196 14.5002 12.0003 14.5002C12.3227 14.5002 12.6309 14.4391 12.9139 14.328ZM20.8068 16.5925L19.376 15.1617C20.0319 14.2268 20.5154 13.1586 20.7777 12.0002C19.8603 7.94818 16.2359 5.00016 12.0003 5.00016C11.1544 5.00016 10.3329 5.11773 9.55249 5.33818L7.97446 3.76015C9.22127 3.26959 10.5793 3.00016 12.0003 3.00016C17.3924 3.00016 21.8784 6.87992 22.8189 12.0002C22.5067 13.6998 21.8038 15.2628 20.8068 16.5925ZM11.7229 7.50857C11.8146 7.50299 11.9071 7.50016 12.0003 7.50016C14.4855 7.50016 16.5003 9.51488 16.5003 12.0002C16.5003 12.0933 16.4974 12.1858 16.4919 12.2775L11.7229 7.50857Z"
|
|
></path>
|
|
</svg>
|
|
<span class="sr-only">{{
|
|
isPasswordVisible
|
|
? 'Masquer le mot de passe'
|
|
: 'Afficher le mot de passe'
|
|
}}</span>
|
|
</button>
|
|
</div>
|
|
<div
|
|
class="field | w-full"
|
|
role="group"
|
|
aria-labelledby="password-confirm"
|
|
>
|
|
<label for="passwordConfirm" class="text-grey-700"
|
|
>Confirmez le nouveau mot de passe…</label
|
|
>
|
|
<input
|
|
:type="isPasswordVisible ? 'text' : 'password'"
|
|
v-model="passwordConfirm"
|
|
id="password-confirm"
|
|
placeholder="Minimum 8 caractères"
|
|
autocomplete="current-password"
|
|
autocapitalize="none"
|
|
autocorrect="off"
|
|
spellcheck="false"
|
|
class="w-full rounded-md border border-grey-200 px-16 py-12 mt-8"
|
|
:class="{ invalid: !isPasswordConfirmed }"
|
|
required
|
|
/>
|
|
<button
|
|
class="btn btn--white btn--icon"
|
|
type="button"
|
|
:aria-pressed="isPasswordVisible ? 'true' : 'false'"
|
|
aria-controls="password-confirm"
|
|
@click="isPasswordVisible = !isPasswordVisible"
|
|
:title="
|
|
isPasswordVisible
|
|
? 'Masquer le mot de passe'
|
|
: 'Afficher le mot de passe'
|
|
"
|
|
>
|
|
<svg
|
|
aria-hidden="true"
|
|
focusable="false"
|
|
xmlns="http://www.w3.org/2000/svg"
|
|
viewBox="0 0 24 24"
|
|
width="16"
|
|
height="16"
|
|
fill="currentColor"
|
|
>
|
|
<path
|
|
v-if="isPasswordVisible"
|
|
d="M12.0003 3C17.3924 3 21.8784 6.87976 22.8189 12C21.8784 17.1202 17.3924 21 12.0003 21C6.60812 21 2.12215 17.1202 1.18164 12C2.12215 6.87976 6.60812 3 12.0003 3ZM12.0003 19C16.2359 19 19.8603 16.052 20.7777 12C19.8603 7.94803 16.2359 5 12.0003 5C7.7646 5 4.14022 7.94803 3.22278 12C4.14022 16.052 7.7646 19 12.0003 19ZM12.0003 16.5C9.51498 16.5 7.50026 14.4853 7.50026 12C7.50026 9.51472 9.51498 7.5 12.0003 7.5C14.4855 7.5 16.5003 9.51472 16.5003 12C16.5003 14.4853 14.4855 16.5 12.0003 16.5ZM12.0003 14.5C13.381 14.5 14.5003 13.3807 14.5003 12C14.5003 10.6193 13.381 9.5 12.0003 9.5C10.6196 9.5 9.50026 10.6193 9.50026 12C9.50026 13.3807 10.6196 14.5 12.0003 14.5Z"
|
|
></path>
|
|
<path
|
|
v-else
|
|
d="M17.8827 19.2968C16.1814 20.3755 14.1638 21.0002 12.0003 21.0002C6.60812 21.0002 2.12215 17.1204 1.18164 12.0002C1.61832 9.62282 2.81932 7.5129 4.52047 5.93457L1.39366 2.80777L2.80788 1.39355L22.6069 21.1925L21.1927 22.6068L17.8827 19.2968ZM5.9356 7.3497C4.60673 8.56015 3.6378 10.1672 3.22278 12.0002C4.14022 16.0521 7.7646 19.0002 12.0003 19.0002C13.5997 19.0002 15.112 18.5798 16.4243 17.8384L14.396 15.8101C13.7023 16.2472 12.8808 16.5002 12.0003 16.5002C9.51498 16.5002 7.50026 14.4854 7.50026 12.0002C7.50026 11.1196 7.75317 10.2981 8.19031 9.60442L5.9356 7.3497ZM12.9139 14.328L9.67246 11.0866C9.5613 11.3696 9.50026 11.6777 9.50026 12.0002C9.50026 13.3809 10.6196 14.5002 12.0003 14.5002C12.3227 14.5002 12.6309 14.4391 12.9139 14.328ZM20.8068 16.5925L19.376 15.1617C20.0319 14.2268 20.5154 13.1586 20.7777 12.0002C19.8603 7.94818 16.2359 5.00016 12.0003 5.00016C11.1544 5.00016 10.3329 5.11773 9.55249 5.33818L7.97446 3.76015C9.22127 3.26959 10.5793 3.00016 12.0003 3.00016C17.3924 3.00016 21.8784 6.87992 22.8189 12.0002C22.5067 13.6998 21.8038 15.2628 20.8068 16.5925ZM11.7229 7.50857C11.8146 7.50299 11.9071 7.50016 12.0003 7.50016C14.4855 7.50016 16.5003 9.51488 16.5003 12.0002C16.5003 12.0933 16.4974 12.1858 16.4919 12.2775L11.7229 7.50857Z"
|
|
></path>
|
|
</svg>
|
|
<span class="sr-only">{{
|
|
isPasswordVisible
|
|
? 'Masquer le mot de passe'
|
|
: 'Afficher le mot de passe'
|
|
}}</span>
|
|
</button>
|
|
</div>
|
|
<button
|
|
class="btn | w-full text-md"
|
|
:class="'btn--' + passwordBtn.status"
|
|
:disabled="!isPasswordConfirmed ? true : undefined"
|
|
@click="updatePassword"
|
|
>
|
|
{{ passwordBtn.text }}
|
|
</button>
|
|
</div>
|
|
</section>
|
|
|
|
<section
|
|
v-if="user.role !== 'pochet'"
|
|
class="bg-white rounded-2xl px-16 py-24"
|
|
aria-labelledby="client-label"
|
|
>
|
|
<h2 id="client-label" class="text-grey-700 mb-16">
|
|
{{ user.client ? 'Client' : 'Pas de client associé' }}
|
|
</h2>
|
|
<div class="flex" style="--column-gap: 2rem">
|
|
<template v-if="user.client">
|
|
<img
|
|
:src="user.client.logo"
|
|
:alt="'logo' + user.client.name"
|
|
class="rounded-md"
|
|
width="72"
|
|
height="72"
|
|
/>
|
|
<p class="font-serif text-lg">{{ user.client.name }}</p>
|
|
</template>
|
|
</div>
|
|
</section>
|
|
|
|
<section
|
|
v-if="
|
|
user.hasOwnProperty('projects') &&
|
|
(user.role === 'pochet' || user.role === 'client')
|
|
"
|
|
class="bg-white rounded-2xl px-16 py-24"
|
|
aria-labelledby="projects-label"
|
|
>
|
|
<h2 id="projects-label" class="text-grey-700 mb-24">
|
|
{{ user.role === 'pochet' ? 'Projets managés' : 'Mes projets' }}
|
|
</h2>
|
|
|
|
<div class="projects-list flow" style="--flow-space: 1rem">
|
|
<div
|
|
v-for="project in user.role === 'pochet'
|
|
? visibleProjects
|
|
: allProjectsList"
|
|
:key="project.uuid"
|
|
class="project-card | flex items-center | bg-grey-100 rounded-lg px-16 py-12"
|
|
style="--column-gap: 1rem"
|
|
>
|
|
<button
|
|
v-if="user.role === 'pochet'"
|
|
@click="toggleProject(project.uuid)"
|
|
class="btn btn--sm btn--primary"
|
|
:title="'Masquer le projet'"
|
|
aria-label="Masquer le projet"
|
|
>
|
|
<svg
|
|
xmlns="http://www.w3.org/2000/svg"
|
|
viewBox="0 0 24 24"
|
|
width="16"
|
|
height="16"
|
|
fill="currentColor"
|
|
>
|
|
<path
|
|
d="M12.0003 3C17.3924 3 21.8784 6.87976 22.8189 12C21.8784 17.1202 17.3924 21 12.0003 21C6.60812 21 2.12215 17.1202 1.18164 12C2.12215 6.87976 6.60812 3 12.0003 3ZM12.0003 19C16.2359 19 19.8603 16.052 20.7777 12C19.8603 7.94803 16.2359 5 12.0003 5C7.7646 5 4.14022 7.94803 3.22278 12C4.14022 16.052 7.7646 19 12.0003 19ZM12.0003 16.5C9.51498 16.5 7.50026 14.4853 7.50026 12C7.50026 9.51472 9.51498 7.5 12.0003 7.5C14.4855 7.5 16.5003 9.51472 16.5003 12C16.5003 14.4853 14.4855 16.5 12.0003 16.5ZM12.0003 14.5C13.381 14.5 14.5003 13.3807 14.5003 12C14.5003 10.6193 13.381 9.5 12.0003 9.5C10.6196 9.5 9.50026 10.6193 9.50026 12C9.50026 13.3807 10.6196 14.5 12.0003 14.5Z"
|
|
></path>
|
|
</svg>
|
|
</button>
|
|
<div class="flex-1 | flex flex-col">
|
|
<p class="font-medium">{{ project.title }}</p>
|
|
<p class="text-sm text-grey-600">{{ project.step }}</p>
|
|
</div>
|
|
</div>
|
|
|
|
<template
|
|
v-if="user.role === 'pochet' && hiddenProjectsList.length > 0"
|
|
>
|
|
<h3 class="text-grey-700 mt-24 mb-12">Projets masqués</h3>
|
|
<div
|
|
v-for="project in hiddenProjectsList"
|
|
:key="project.uuid"
|
|
class="project-card | flex items-center | bg-grey-100 rounded-lg px-16 py-12"
|
|
style="--column-gap: 1rem; opacity: 0.5"
|
|
>
|
|
<button
|
|
@click="toggleProject(project.uuid)"
|
|
class="btn btn--sm btn--primary"
|
|
:title="'Afficher le projet'"
|
|
aria-label="Afficher le projet"
|
|
>
|
|
<svg
|
|
xmlns="http://www.w3.org/2000/svg"
|
|
viewBox="0 0 24 24"
|
|
width="16"
|
|
height="16"
|
|
fill="currentColor"
|
|
>
|
|
<path
|
|
d="M17.8827 19.2968C16.1814 20.3755 14.1638 21.0002 12.0003 21.0002C6.60812 21.0002 2.12215 17.1204 1.18164 12.0002C1.61832 9.62282 2.81932 7.5129 4.52047 5.93457L1.39366 2.80777L2.80788 1.39355L22.6069 21.1925L21.1927 22.6068L17.8827 19.2968ZM5.9356 7.3497C4.60673 8.56015 3.6378 10.1672 3.22278 12.0002C4.14022 16.0521 7.7646 19.0002 12.0003 19.0002C13.5997 19.0002 15.112 18.5798 16.4243 17.8384L14.396 15.8101C13.7023 16.2472 12.8808 16.5002 12.0003 16.5002C9.51498 16.5002 7.50026 14.4854 7.50026 12.0002C7.50026 11.1196 7.75317 10.2981 8.19031 9.60442L5.9356 7.3497ZM12.9139 14.328L9.67246 11.0866C9.5613 11.3696 9.50026 11.6777 9.50026 12.0002C9.50026 13.3809 10.6196 14.5002 12.0003 14.5002C12.3227 14.5002 12.6309 14.4391 12.9139 14.328ZM20.8068 16.5925L19.376 15.1617C20.0319 14.2268 20.5154 13.1586 20.7777 12.0002C19.8603 7.94818 16.2359 5.00016 12.0003 5.00016C11.1544 5.00016 10.3329 5.11773 9.55249 5.33818L7.97446 3.76015C9.22127 3.26959 10.5793 3.00016 12.0003 3.00016C17.3924 3.00016 21.8784 6.87992 22.8189 12.0002C22.5067 13.6998 21.8038 15.2628 20.8068 16.5925ZM11.7229 7.50857C11.8146 7.50299 11.9071 7.50016 12.0003 7.50016C14.4855 7.50016 16.5003 9.51488 16.5003 12.0002C16.5003 12.0933 16.4974 12.1858 16.4919 12.2775L11.7229 7.50857Z"
|
|
></path>
|
|
</svg>
|
|
</button>
|
|
<div class="flex-1 | flex flex-col">
|
|
<p class="font-medium">{{ project.title }}</p>
|
|
<p class="text-sm text-grey-600">{{ project.step }}</p>
|
|
</div>
|
|
</div>
|
|
</template>
|
|
</div>
|
|
</section>
|
|
|
|
<section
|
|
v-else-if="user.hasOwnProperty('projects')"
|
|
class="bg-white rounded-2xl px-16 py-24"
|
|
aria-labelledby="projects-label"
|
|
>
|
|
<h2 class="sr-only" id="projects-label">Projets</h2>
|
|
<p class="text-grey-700 mb-16">Nombre de projets</p>
|
|
<p class="text-xl">{{ Object.values(user.projects).length }}</p>
|
|
</section>
|
|
</div>
|
|
</main>
|
|
</template>
|
|
<script setup>
|
|
import { storeToRefs } from 'pinia';
|
|
import { useUserStore } from '../stores/user';
|
|
import { useApiStore } from '../stores/api';
|
|
import { computed, ref, watch } from 'vue';
|
|
|
|
const userStore = useUserStore();
|
|
const { user, visibleProjects } = storeToRefs(userStore);
|
|
const api = useApiStore();
|
|
|
|
const hiddenProjectsList = computed(() => {
|
|
if (!user.value?.projects || !user.value?.hiddenProjects) return [];
|
|
const projectsArray = Array.isArray(user.value.projects)
|
|
? user.value.projects
|
|
: Object.values(user.value.projects);
|
|
return projectsArray.filter((project) =>
|
|
user.value.hiddenProjects.includes(project.uuid)
|
|
);
|
|
});
|
|
|
|
const allProjectsList = computed(() => {
|
|
if (!user.value?.projects) return [];
|
|
return Array.isArray(user.value.projects)
|
|
? user.value.projects
|
|
: Object.values(user.value.projects);
|
|
});
|
|
|
|
async function toggleProject(projectUuid) {
|
|
try {
|
|
await api.toggleHiddenProject(projectUuid);
|
|
} catch (error) {
|
|
console.error('Erreur lors du masquage/affichage du projet:', error);
|
|
}
|
|
}
|
|
|
|
// Email
|
|
const email = ref('');
|
|
const emailBtn = ref({
|
|
text: 'Mettre à jour',
|
|
status: 'ready',
|
|
});
|
|
const isEditingEmail = ref(false);
|
|
const emailRegex = /^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$/;
|
|
const isEmailValid = computed(() => {
|
|
return emailRegex.test(email.value);
|
|
});
|
|
async function updateEmail() {
|
|
emailBtn.value.text = 'En cours…';
|
|
emailBtn.value.status = 'pending';
|
|
|
|
const headers = {
|
|
method: 'POST',
|
|
body: JSON.stringify({
|
|
email: email.value,
|
|
}),
|
|
};
|
|
const response = await fetch('update-email.json', headers);
|
|
const json = await response.json();
|
|
|
|
if (json.status === 'success') {
|
|
emailBtn.value.text = 'Mise à jour réussie';
|
|
emailBtn.value.status = 'succeed';
|
|
|
|
setTimeout(() => {
|
|
emailBtn.value.text = 'Mettre à jour';
|
|
emailBtn.value.status = 'ready';
|
|
isEditingEmail.value = false;
|
|
}, 1500);
|
|
} else {
|
|
console.log(json.message);
|
|
}
|
|
}
|
|
|
|
// Password
|
|
const password = ref('');
|
|
const passwordBtn = ref({
|
|
text: 'Mettre à jour',
|
|
status: 'ready',
|
|
});
|
|
const passwordConfirm = ref('');
|
|
const isPasswordVisible = ref(false);
|
|
const isPasswordConfirmed = computed(() => {
|
|
return (
|
|
passwordConfirm.value.length > 7 && passwordConfirm.value === password.value
|
|
);
|
|
});
|
|
async function updatePassword() {
|
|
passwordBtn.value.text = 'en cours…';
|
|
passwordBtn.value.status = 'pending';
|
|
|
|
const headers = {
|
|
method: 'POST',
|
|
body: JSON.stringify({
|
|
password: password.value,
|
|
}),
|
|
};
|
|
const response = await fetch('update-password.json', headers);
|
|
const json = await response.json();
|
|
|
|
if (json.status === 'success') {
|
|
password.value = '';
|
|
passwordConfirm.value = '';
|
|
passwordBtn.value.text = 'mise à jour réussie';
|
|
passwordBtn.value.status = 'succeed';
|
|
|
|
setTimeout(() => {
|
|
passwordBtn.value.text = 'Mettre à jour';
|
|
passwordBtn.value.status = 'ready';
|
|
}, 1500);
|
|
} else {
|
|
console.log(json.message);
|
|
}
|
|
}
|
|
</script>
|
|
|
|
<style scoped>
|
|
input.invalid:focus-visible {
|
|
outline: 2px solid #ef8d8d;
|
|
}
|
|
|
|
.btn--pending {
|
|
background-color: #ffdb88;
|
|
}
|
|
|
|
.btn--succeed {
|
|
background-color: rgb(182, 211, 255);
|
|
}
|
|
</style>
|