Merge branch 'develop' into phillip/chat-skill-merge
3257
website/client/package-lock.json
generated
@@ -19,10 +19,10 @@
|
||||
"@storybook/addon-notes": "5.3.21",
|
||||
"@storybook/addons": "6.5.9",
|
||||
"@storybook/vue": "6.5.14",
|
||||
"@vue/cli-plugin-babel": "^4.5.15",
|
||||
"@vue/cli-plugin-babel": "^5.0.8",
|
||||
"@vue/cli-plugin-eslint": "^4.5.19",
|
||||
"@vue/cli-plugin-router": "^5.0.8",
|
||||
"@vue/cli-plugin-unit-mocha": "^4.5.15",
|
||||
"@vue/cli-plugin-unit-mocha": "^5.0.8",
|
||||
"@vue/cli-service": "^4.5.15",
|
||||
"@vue/test-utils": "1.0.0-beta.29",
|
||||
"amplitude-js": "^8.21.3",
|
||||
@@ -32,30 +32,30 @@
|
||||
"bootstrap": "^4.6.0",
|
||||
"bootstrap-vue": "^2.23.1",
|
||||
"chai": "^4.3.7",
|
||||
"core-js": "^3.26.1",
|
||||
"dompurify": "^2.4.1",
|
||||
"core-js": "^3.31.0",
|
||||
"dompurify": "^3.0.3",
|
||||
"eslint": "^6.8.0",
|
||||
"eslint-config-habitrpg": "^6.2.0",
|
||||
"eslint-plugin-mocha": "^5.3.0",
|
||||
"eslint-plugin-vue": "^6.2.2",
|
||||
"habitica-markdown": "^3.0.0",
|
||||
"hellojs": "^1.19.5",
|
||||
"hellojs": "^1.20.0",
|
||||
"inspectpack": "^4.7.1",
|
||||
"intro.js": "^6.0.0",
|
||||
"jquery": "^3.6.1",
|
||||
"intro.js": "^7.0.1",
|
||||
"jquery": "^3.7.0",
|
||||
"lodash": "^4.17.21",
|
||||
"moment": "^2.29.4",
|
||||
"nconf": "^0.12.0",
|
||||
"sass": "^1.34.0",
|
||||
"sass": "^1.63.4",
|
||||
"sass-loader": "^8.0.2",
|
||||
"smartbanner.js": "^1.19.1",
|
||||
"stopword": "^2.0.5",
|
||||
"smartbanner.js": "^1.19.2",
|
||||
"stopword": "^2.0.8",
|
||||
"svg-inline-loader": "^0.8.2",
|
||||
"svg-url-loader": "^7.1.1",
|
||||
"svgo": "^1.3.2",
|
||||
"svgo-loader": "^2.2.1",
|
||||
"uuid": "^8.3.2",
|
||||
"validator": "^13.7.0",
|
||||
"uuid": "^9.0.0",
|
||||
"validator": "^13.9.0",
|
||||
"vue": "^2.7.10",
|
||||
"vue-cli-plugin-storybook": "2.1.0",
|
||||
"vue-mugen-scroll": "^0.2.6",
|
||||
@@ -66,6 +66,6 @@
|
||||
"webpack": "^4.46.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@babel/plugin-proposal-optional-chaining": "^7.18.9"
|
||||
"@babel/plugin-proposal-optional-chaining": "^7.21.0"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -35,6 +35,8 @@
|
||||
<sub-canceled-modal v-if="isUserLoaded" />
|
||||
<bug-report-modal v-if="isUserLoaded" />
|
||||
<bug-report-success-modal v-if="isUserLoaded" />
|
||||
<external-link-modal />
|
||||
<birthday-modal />
|
||||
<snackbars />
|
||||
<router-view v-if="!isUserLoggedIn || isStaticPage" />
|
||||
<template v-else>
|
||||
@@ -42,6 +44,7 @@
|
||||
<damage-paused-banner />
|
||||
<gems-promo-banner />
|
||||
<gift-promo-banner />
|
||||
<birthday-banner />
|
||||
<notifications-display />
|
||||
<app-menu />
|
||||
<div
|
||||
@@ -153,11 +156,13 @@
|
||||
import axios from 'axios';
|
||||
import { loadProgressBar } from 'axios-progress-bar';
|
||||
|
||||
import birthdayModal from '@/components/news/birthdayModal';
|
||||
import AppMenu from './components/header/menu';
|
||||
import AppHeader from './components/header/index';
|
||||
import DamagePausedBanner from './components/header/banners/damagePaused';
|
||||
import GemsPromoBanner from './components/header/banners/gemsPromo';
|
||||
import GiftPromoBanner from './components/header/banners/giftPromo';
|
||||
import BirthdayBanner from './components/header/banners/birthdayBanner';
|
||||
import AppFooter from './components/appFooter';
|
||||
import notificationsDisplay from './components/notifications';
|
||||
import snackbars from './components/snackbars/notifications';
|
||||
@@ -171,6 +176,7 @@ import amazonPaymentsModal from '@/components/payments/amazonModal';
|
||||
import paymentsSuccessModal from '@/components/payments/successModal';
|
||||
import subCancelModalConfirm from '@/components/payments/cancelModalConfirm';
|
||||
import subCanceledModal from '@/components/payments/canceledModal';
|
||||
import externalLinkModal from '@/components/externalLinkModal.vue';
|
||||
|
||||
import spellsMixin from '@/mixins/spells';
|
||||
import {
|
||||
@@ -191,9 +197,11 @@ export default {
|
||||
AppMenu,
|
||||
AppHeader,
|
||||
AppFooter,
|
||||
birthdayModal,
|
||||
DamagePausedBanner,
|
||||
GemsPromoBanner,
|
||||
GiftPromoBanner,
|
||||
BirthdayBanner,
|
||||
notificationsDisplay,
|
||||
snackbars,
|
||||
BuyModal,
|
||||
@@ -204,6 +212,7 @@ export default {
|
||||
subCanceledModal,
|
||||
bugReportModal,
|
||||
bugReportSuccessModal,
|
||||
externalLinkModal,
|
||||
},
|
||||
mixins: [notifications, spellsMixin],
|
||||
data () {
|
||||
|
||||
@@ -156,6 +156,12 @@
|
||||
height: 99px;
|
||||
}
|
||||
|
||||
.Pet-Gryphatrice-Jubilant {
|
||||
background: url("https://habitica-assets.s3.amazonaws.com/mobileApp/images/Pet-Gryphatrice-Jubilant.gif") no-repeat;
|
||||
width: 81px;
|
||||
height: 96px;
|
||||
}
|
||||
|
||||
.Mount_Head_Gryphon-Gryphatrice, .Mount_Body_Gryphon-Gryphatrice {
|
||||
width: 135px;
|
||||
height: 135px;
|
||||
|
||||
BIN
website/client/src/assets/images/10-birthday.png
Normal file
|
After Width: | Height: | Size: 22 KiB |
|
After Width: | Height: | Size: 29 KiB |
|
Before Width: | Height: | Size: 7.4 KiB After Width: | Height: | Size: 8.5 KiB |
BIN
website/client/src/assets/images/fancy-divider.png
Normal file
|
After Width: | Height: | Size: 332 B |
BIN
website/client/src/assets/images/glitter.png
Normal file
|
After Width: | Height: | Size: 358 B |
BIN
website/client/src/assets/images/habitica-hero-goober.webp
Normal file
|
After Width: | Height: | Size: 850 B |
BIN
website/client/src/assets/images/robes.webp
Normal file
|
After Width: | Height: | Size: 1.2 KiB |
@@ -19,8 +19,12 @@
|
||||
top: -16px !important;
|
||||
}
|
||||
|
||||
.Pet.Pet-FlyingPig-Veggie, .Pet.Pet-FlyingPig-Dessert, .Pet.Pet-FlyingPig-VirtualPet {
|
||||
top: -28px !important;
|
||||
$foolPets: Veggie, Dessert, VirtualPet, TeaShop;
|
||||
|
||||
@each $foolPet in $foolPets {
|
||||
.Pet.Pet-FlyingPig-#{$foolPet} {
|
||||
top: -28px !important;
|
||||
}
|
||||
}
|
||||
|
||||
.Pet[class*="Virtual"] {
|
||||
|
||||
@@ -24,9 +24,9 @@
|
||||
}
|
||||
}
|
||||
|
||||
.icon-16 {
|
||||
width: 16px;
|
||||
height: 16px;
|
||||
.icon-10 {
|
||||
width: 10px;
|
||||
height: 10px;
|
||||
}
|
||||
|
||||
.icon-12 {
|
||||
@@ -34,21 +34,26 @@
|
||||
height: 12px;
|
||||
}
|
||||
|
||||
.icon-16 {
|
||||
width: 16px;
|
||||
height: 16px;
|
||||
}
|
||||
|
||||
.icon-24 {
|
||||
width: 24px;
|
||||
height: 24px;
|
||||
}
|
||||
|
||||
.icon-32 {
|
||||
width: 32px;
|
||||
height: 32px;
|
||||
}
|
||||
|
||||
.icon-48 {
|
||||
width: 48px;
|
||||
height: 48px;
|
||||
}
|
||||
|
||||
.icon-10 {
|
||||
width: 10px;
|
||||
height: 10px;
|
||||
}
|
||||
|
||||
.inline {
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
@@ -50,10 +50,7 @@ h3.markdown {
|
||||
}
|
||||
|
||||
a {
|
||||
color: $blue-10;
|
||||
|
||||
&:hover, &:active, &:focus {
|
||||
color: $blue-10;
|
||||
text-decoration: underline;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -26,19 +26,17 @@ a:not([href]), a:not([href]):hover {
|
||||
|
||||
a, a:not([href]):not([tabindex]) {
|
||||
cursor: pointer;
|
||||
color: $purple-300;
|
||||
|
||||
&.standard-link {
|
||||
color: $blue-10;
|
||||
&:hover, &:active, &:focus {
|
||||
text-decoration: underline;
|
||||
color: $purple-300;
|
||||
}
|
||||
|
||||
&:hover, &:active, &:focus {
|
||||
text-decoration: underline;
|
||||
}
|
||||
|
||||
&[disabled="disabled"] {
|
||||
color: $gray-300;
|
||||
text-decoration: none;
|
||||
cursor: default;
|
||||
}
|
||||
&[disabled="disabled"] {
|
||||
color: $gray-300;
|
||||
text-decoration: none;
|
||||
cursor: default;
|
||||
}
|
||||
|
||||
&.small-link {
|
||||
|
||||
61
website/client/src/assets/svg/10th-birthday-linear.svg
Normal file
@@ -0,0 +1,61 @@
|
||||
<svg width="199" height="24" viewBox="0 0 199 24" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<g filter="url(#c19w6aye5a)" fill="#fff">
|
||||
<path d="M56.47 18.83V6.003L56 3.662l.47-1.405h8.942c1.773 0 3.193.344 4.26 1.03 1.066.687 1.6 1.733 1.6 3.137 0 .765-.142 1.397-.424 1.896a4.175 4.175 0 0 1-1.035 1.24 4.14 4.14 0 0 1 1.505.703c.471.327.855.772 1.154 1.334.297.546.447 1.225.447 2.036 0 1.639-.487 2.918-1.46 3.839-.956.905-2.502 1.358-4.635 1.358H56.471zm5.177-10.136h2.777c.533 0 .918-.078 1.153-.234.235-.171.353-.429.353-.772 0-.359-.173-.609-.518-.75-.345-.155-.753-.233-1.223-.233h-2.542v1.99zm0 5.688h4c.628 0 1.067-.093 1.318-.28a.974.974 0 0 0 .377-.796c0-.75-.486-1.124-1.46-1.124h-4.235v2.2zM75.515 18.83V6.003l-.236-2.341.236-1.405h5.2V18.83h-5.2zM84 18.83V6.026l-.471-2.364.47-1.405h8.472c1.27 0 2.36.203 3.27.61.91.405 1.608 1.06 2.095 1.965.486.89.73 2.068.73 3.535 0 1.357-.228 2.473-.683 3.347a4.552 4.552 0 0 1-2 1.99l.4.327 1.623 2.2 1.341 1.194v1.405h-6.235l-2.588-4.284h-1.248v.515l.236 2.34-.236 1.429H84zm5.176-8.66h1.365c.55 0 1.02-.024 1.412-.071.408-.047.722-.187.941-.421.22-.25.33-.648.33-1.194 0-.578-.118-.991-.353-1.24-.236-.25-.565-.399-.989-.446a9.614 9.614 0 0 0-1.435-.093h-1.506l.235 3.464zM104.666 18.83V6.728l-4.706.234V2.257h14.707v4.705l-4.824-.234v8.357l.259 2.34-.259 1.405h-5.177zM116.785 18.83V6.026l-.235-2.34.235-1.429h5.177v6.344h4.918V2.257h5.177v8.802l.235 1.615v6.156h-5.412v-5.946h-4.918v1.639l.235 4.307h-5.412zM135.588 18.83V6.026l-.471-2.34.471-1.429h7.977c1.114 0 2.188.11 3.223.328 1.051.203 1.985.593 2.801 1.17.831.578 1.49 1.405 1.976 2.482.486 1.076.73 2.473.73 4.19 0 1.716-.251 3.128-.753 4.236-.487 1.092-1.146 1.943-1.977 2.552a7.477 7.477 0 0 1-2.8 1.264 14.463 14.463 0 0 1-3.2.35h-7.977zm5.224-4.448h1.788c.926 0 1.702-.101 2.33-.304a2.498 2.498 0 0 0 1.458-1.147c.33-.577.495-1.412.495-2.504 0-1.108-.173-1.92-.518-2.435-.33-.53-.816-.874-1.459-1.03-.628-.171-1.396-.257-2.306-.257h-1.788v7.677zM153.013 18.83l1.13-3.956V11.9l1.741-.702 3.294-8.918h7.083l4.024 10.486 1.812 3.324v2.739h-5.106l-1.177-3.488h-6.377l-1.012 3.488h-5.412zm7.977-7.584h3.53l-1.553-4.658h-.494l-1.483 4.658zM176.04 18.83v-6.788l-5.835-8.38V2.257h5.906l2.353 4.822h.47l2.33-4.822h5.883v1.405l-6.001 8.52.141 2.364v4.284h-5.247zM191.923 12.72l-2.07-8.847L192.676 2l2.8 1.896-2.141 8.824h-1.412zm.518 7.28-3.059-3.043 3.059-3.043 3.059 3.043L192.441 20z"/>
|
||||
</g>
|
||||
<g filter="url(#s1alkvv8kb)">
|
||||
<path d="M5.87 18.825V7.601H3V3.17l8.228-.937.239 1.406-.24 2.344v12.841H5.87z" fill="url(#xidihnl5xc)"/>
|
||||
<path d="M21.258 19.06a9.043 9.043 0 0 1-2.87-.446 6.484 6.484 0 0 1-2.369-1.453c-.67-.671-1.195-1.546-1.578-2.624-.383-1.094-.574-2.43-.574-4.007 0-1.562.191-2.883.574-3.96.382-1.094.909-1.977 1.578-2.648a6.092 6.092 0 0 1 2.368-1.453A8.63 8.63 0 0 1 21.257 2c1.356 0 2.584.281 3.684.844 1.116.562 2.001 1.468 2.655 2.718.67 1.234 1.004 2.89 1.004 4.968s-.335 3.741-1.004 4.991c-.654 1.25-1.539 2.156-2.655 2.718-1.1.547-2.328.82-3.683.82zm0-5.039c.701 0 1.187-.25 1.459-.75.27-.5.406-1.413.406-2.741 0-1.313-.136-2.219-.407-2.719-.27-.515-.757-.773-1.459-.773-.685 0-1.18.258-1.483.773-.287.516-.43 1.422-.43 2.719 0 1.312.143 2.226.43 2.742.303.5.798.75 1.483.75z" fill="url(#9hqzmmkygd)"/>
|
||||
<path d="M32.721 12.014V4.745l-2.87.14V2.06h8.97v2.826l-2.943-.141v5.02l.158 1.405-.158.844h-3.157z" fill="url(#bzq8gpt5ve)"/>
|
||||
<path d="M40.543 12.014v-7.69l-.144-1.407.144-.857H43.7v3.81h3V2.06h3.156v5.286l.144.97v3.698h-3.3V8.443h-3v.984l.143 2.587h-3.3z" fill="url(#4t6arxwa4f)"/>
|
||||
</g>
|
||||
<defs>
|
||||
<linearGradient id="xidihnl5xc" x1="3" y1="2" x2="29.822" y2="35.308" gradientUnits="userSpaceOnUse">
|
||||
<stop stop-color="#6133B4"/>
|
||||
<stop offset="1" stop-color="#4F2A93"/>
|
||||
</linearGradient>
|
||||
<linearGradient id="9hqzmmkygd" x1="3" y1="2" x2="29.822" y2="35.308" gradientUnits="userSpaceOnUse">
|
||||
<stop stop-color="#6133B4"/>
|
||||
<stop offset="1" stop-color="#4F2A93"/>
|
||||
</linearGradient>
|
||||
<linearGradient id="bzq8gpt5ve" x1="3" y1="2" x2="29.822" y2="35.308" gradientUnits="userSpaceOnUse">
|
||||
<stop stop-color="#6133B4"/>
|
||||
<stop offset="1" stop-color="#4F2A93"/>
|
||||
</linearGradient>
|
||||
<linearGradient id="4t6arxwa4f" x1="3" y1="2" x2="29.822" y2="35.308" gradientUnits="userSpaceOnUse">
|
||||
<stop stop-color="#6133B4"/>
|
||||
<stop offset="1" stop-color="#4F2A93"/>
|
||||
</linearGradient>
|
||||
<filter id="c19w6aye5a" x="53" y="0" width="145.5" height="24" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB">
|
||||
<feFlood flood-opacity="0" result="BackgroundImageFix"/>
|
||||
<feColorMatrix in="SourceAlpha" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0" result="hardAlpha"/>
|
||||
<feOffset dy="1"/>
|
||||
<feGaussianBlur stdDeviation="1.5"/>
|
||||
<feComposite in2="hardAlpha" operator="out"/>
|
||||
<feColorMatrix values="0 0 0 0 0.101961 0 0 0 0 0.0941176 0 0 0 0 0.113725 0 0 0 0.12 0"/>
|
||||
<feBlend in2="BackgroundImageFix" result="effect1_dropShadow_45_799"/>
|
||||
<feColorMatrix in="SourceAlpha" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0" result="hardAlpha"/>
|
||||
<feOffset dy="1"/>
|
||||
<feGaussianBlur stdDeviation="1"/>
|
||||
<feComposite in2="hardAlpha" operator="out"/>
|
||||
<feColorMatrix values="0 0 0 0 0.101961 0 0 0 0 0.0941176 0 0 0 0 0.113725 0 0 0 0.24 0"/>
|
||||
<feBlend in2="effect1_dropShadow_45_799" result="effect2_dropShadow_45_799"/>
|
||||
<feBlend in="SourceGraphic" in2="effect2_dropShadow_45_799" result="shape"/>
|
||||
</filter>
|
||||
<filter id="s1alkvv8kb" x="0" y="0" width="53" height="23.059" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB">
|
||||
<feFlood flood-opacity="0" result="BackgroundImageFix"/>
|
||||
<feColorMatrix in="SourceAlpha" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0" result="hardAlpha"/>
|
||||
<feOffset dy="1"/>
|
||||
<feGaussianBlur stdDeviation="1.5"/>
|
||||
<feComposite in2="hardAlpha" operator="out"/>
|
||||
<feColorMatrix values="0 0 0 0 0.101961 0 0 0 0 0.0941176 0 0 0 0 0.113725 0 0 0 0.12 0"/>
|
||||
<feBlend in2="BackgroundImageFix" result="effect1_dropShadow_45_799"/>
|
||||
<feColorMatrix in="SourceAlpha" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0" result="hardAlpha"/>
|
||||
<feOffset dy="1"/>
|
||||
<feGaussianBlur stdDeviation="1"/>
|
||||
<feComposite in2="hardAlpha" operator="out"/>
|
||||
<feColorMatrix values="0 0 0 0 0.101961 0 0 0 0 0.0941176 0 0 0 0 0.113725 0 0 0 0.24 0"/>
|
||||
<feBlend in2="effect1_dropShadow_45_799" result="effect2_dropShadow_45_799"/>
|
||||
<feBlend in="SourceGraphic" in2="effect2_dropShadow_45_799" result="shape"/>
|
||||
</filter>
|
||||
</defs>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 6.8 KiB |
22
website/client/src/assets/svg/birthday-gems.svg
Normal file
@@ -0,0 +1,22 @@
|
||||
<svg width="58" height="48" viewBox="0 0 58 48" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="m16.853 4.36 7.959-1.453-2.71 7.556-2.708 7.557-5.25-6.103-5.25-6.103 7.959-1.453z" fill="#5DDEAB"/>
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M32.771 1.454 40.731 0l-2.71 7.556-2.709 7.556-5.25-6.102-5.25-6.103 7.96-1.453z" fill="#5DDEAB"/>
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="m43.272 13.659-7.96 1.453 2.71-7.556L40.73 0l5.25 6.103 5.25 6.102-7.96 1.454z" fill="#38C38D"/>
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="m27.353 16.566-7.96 1.453 2.71-7.556 2.709-7.556 5.25 6.103 5.25 6.102-7.96 1.454zM11.434 19.473l-7.959 1.453 2.71-7.556 2.708-7.556 5.25 6.103 5.25 6.102-7.959 1.454z" fill="#B0F1D7"/>
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="m3.475 20.926 28.05 18.662L19.394 18.02 3.475 20.926z" fill="#38C38D"/>
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M51.249 12.202 31.525 39.588l3.805-24.48 15.919-2.906z" fill="#B0F1D7"/>
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="m19.394 18.02 12.131 21.568 3.787-24.476-15.918 2.907z" fill="#5DDEAB"/>
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="m51.904 26.44-3.832-.897 1.132 3.736 1.132 3.737 2.7-2.84 2.7-2.84-3.832-.896zM44.24 24.647l-3.832-.897 1.132 3.736 1.132 3.736 2.7-2.84 2.7-2.839-3.832-.896z" fill="#87E3E1"/>
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="m38.84 30.326 3.832.896-1.132-3.736-1.132-3.736-2.7 2.84-2.7 2.839 3.832.897zM46.504 32.12l3.832.896-1.132-3.736-1.132-3.737-2.7 2.84-2.7 2.84 3.832.896z" fill="#C0FBFA"/>
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M54.168 33.912 58 34.81l-1.132-3.736-1.133-3.736-2.7 2.84-2.7 2.839 3.833.896z" fill="#5EC5C2"/>
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="m58 34.81-14.084 8.395 6.42-10.19L58 34.81z" fill="#C0FBFA"/>
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="m35 29.427 8.916 13.779-1.252-11.986L35 29.427z" fill="#5EC5C2"/>
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="m50.336 33.016-6.42 10.19-1.244-11.984 7.664 1.794z" fill="#87E3E1"/>
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="m16.877 22.666-5.078 1.971 4.262 3.372 4.262 3.37.816-5.341.816-5.343-5.078 1.971zM6.721 26.609l-5.078 1.97 4.262 3.372 4.262 3.371.816-5.342.816-5.343-5.078 1.972z" fill="#7BE3CF"/>
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="m5.09 37.294 5.077-1.972-4.262-3.371-4.261-3.371-.817 5.342-.816 5.343 5.078-1.971z" fill="#C5F3EA"/>
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="m15.245 33.351 5.078-1.971-4.262-3.371-4.262-3.371-.816 5.342-.816 5.342 5.078-1.97z" fill="#C5F3EA"/>
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="m25.4 29.41 5.078-1.972-4.262-3.371-4.261-3.372-.816 5.343-.816 5.342 5.078-1.97z" fill="#41C7AF"/>
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M30.478 27.438 21.117 48l-.794-16.62 10.155-3.942z" fill="#C5F3EA"/>
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="m0 39.269 21.117 8.73-10.961-12.672L0 39.269z" fill="#41C7AF"/>
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M20.323 31.38 21.117 48l-10.95-12.678 10.156-3.942z" fill="#7BE3CF"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 3.1 KiB |
22
website/client/src/assets/svg/confetti.svg
Normal file
@@ -0,0 +1,22 @@
|
||||
<svg width="518" height="152" viewBox="0 0 518 152" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M144.48 65.487v5.042h-1.772v-5.042h1.772zm1.621 6.671h5.013v1.782h-5.013v-1.782zm-10.027 0h5.013v1.782h-5.013v-1.782zm8.406 3.412v5.041h-1.772V75.57h1.772z" fill="#36205D" style="mix-blend-mode:multiply" opacity=".5"/>
|
||||
<path opacity=".92" fill-rule="evenodd" clip-rule="evenodd" d="m9.504 29.894 2.707-4.715 1.658.962-2.707 4.715-1.658-.962zm2.066-7.12-4.689-2.722.958-1.667 4.688 2.723-.957 1.667zm9.378 5.445-4.689-2.722.957-1.667 4.69 2.722-.958 1.667zm-6.03-7.755 2.707-4.715 1.658.962-2.707 4.715-1.658-.962z" fill="#fff"/>
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="m60.85 11.508.708-3.662 1.288.251-.708 3.662-1.288-.252zm-.24-5.076-3.642-.712.25-1.295 3.642.712-.25 1.295zm7.283 1.423-3.642-.711.25-1.295 3.642.712-.25 1.294zm-5.627-3.671.708-3.662 1.287.251-.708 3.662-1.287-.251z" fill="#36205D" style="mix-blend-mode:multiply" opacity=".81"/>
|
||||
<path opacity=".76" fill-rule="evenodd" clip-rule="evenodd" d="m107.034 22.162.493 5.675-1.995.175-.494-5.674 1.996-.176zm2.477 7.349 5.643-.497.175 2.007-5.644.496-.174-2.006zm-11.287.993 5.644-.497.174 2.007-5.643.496-.175-2.006zm9.797 3.008.494 5.675-1.996.175-.493-5.675 1.995-.175z" fill="#fff"/>
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="m16.191 92.492-5.006 1.636-.575-1.78 5.006-1.636.575 1.78zm-6.098 3.792 1.626 5.034-1.77.578-1.626-5.034 1.77-.578zM6.839 86.215l1.627 5.035-1.77.578-1.627-5.034 1.77-.579zm-.66 9.549-5.006 1.635-.576-1.78 5.007-1.635.575 1.78z" fill="#36205D" style="mix-blend-mode:multiply" opacity=".91"/>
|
||||
<path opacity=".92" fill-rule="evenodd" clip-rule="evenodd" d="m35.176 59.176 5.102-1.97.692 1.814-5.101 1.97-.693-1.814zm6.118-4.264-1.958-5.13 1.803-.696 1.958 5.13-1.803.696zm3.916 10.26-1.958-5.13 1.804-.696 1.958 5.13-1.804.696zm.17-9.935 5.1-1.969.693 1.814-5.101 1.969-.693-1.814z" fill="#fff"/>
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="m95.733 86.583-4.383 2.649-.931-1.559 4.383-2.648.93 1.558zm-4.949 4.93 2.634 4.407-1.55.936-2.633-4.407 1.55-.937zm-5.267-8.816 2.633 4.408-1.55.936-2.633-4.408 1.55-.936zm1.45 9.183-4.384 2.648-.93-1.558 4.382-2.648.931 1.558z" fill="#36205D" style="mix-blend-mode:multiply"/>
|
||||
<path opacity=".98" fill-rule="evenodd" clip-rule="evenodd" d="m24.804 132.406-2.1-3.015 1.06-.746 2.1 3.014-1.06.747zm-3.747-3.307-2.998 2.111-.742-1.066 2.998-2.111.742 1.066zm5.996-4.222-2.998 2.111-.742-1.066 2.998-2.11.742 1.065zm-6.447 1.5-2.1-3.015 1.06-.746 2.1 3.014-1.06.747z" fill="#fff"/>
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="m60.65 142.295-1.594 3.144-1.105-.567 1.593-3.144 1.105.567zm-1.098 4.678 3.126 1.602-.563 1.112-3.127-1.602.564-1.112zm-6.254-3.204 3.127 1.602-.563 1.112-3.127-1.603.563-1.111zm4.165 4.814-1.593 3.144-1.106-.566 1.593-3.144 1.106.566z" fill="#36205D" style="mix-blend-mode:multiply" opacity=".82"/>
|
||||
<path opacity=".71" fill-rule="evenodd" clip-rule="evenodd" d="m110.507 140.233 2.321-4.582 1.611.826-2.321 4.581-1.611-.825zm1.599-6.817-4.556-2.335.821-1.62 4.556 2.335-.821 1.62zm9.112 4.669-4.556-2.335.821-1.62 4.556 2.335-.821 1.62zm-6.068-7.015 2.321-4.582 1.611.825-2.321 4.582-1.611-.825z" fill="#fff"/>
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M373.52 65.487v5.042h1.772v-5.042h-1.772zm-1.621 6.671h-5.013v1.782h5.013v-1.782zm10.027 0h-5.013v1.782h5.013v-1.782zm-8.406 3.412v5.041h1.772V75.57h-1.772z" fill="#36205D" style="mix-blend-mode:multiply" opacity=".5"/>
|
||||
<path opacity=".92" fill-rule="evenodd" clip-rule="evenodd" d="m508.496 29.894-2.707-4.715-1.658.962 2.707 4.715 1.658-.962zm-2.066-7.12 4.689-2.722-.958-1.667-4.689 2.723.958 1.667zm-9.378 5.445 4.689-2.722-.957-1.667-4.689 2.722.957 1.667zm6.03-7.755-2.707-4.715-1.658.962 2.707 4.715 1.658-.962z" fill="#fff"/>
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="m457.15 11.508-.708-3.662-1.287.251.707 3.662 1.288-.252zm.24-5.076 3.642-.712-.25-1.295-3.642.712.25 1.295zm-7.283 1.423 3.642-.711-.251-1.295-3.641.712.25 1.294zm5.627-3.671-.708-3.662-1.287.251.708 3.662 1.287-.251z" fill="#36205D" style="mix-blend-mode:multiply" opacity=".81"/>
|
||||
<path opacity=".76" fill-rule="evenodd" clip-rule="evenodd" d="m410.966 22.162-.493 5.675 1.995.175.494-5.674-1.996-.176zm-2.477 7.349-5.643-.497-.175 2.007 5.644.496.174-2.006zm11.287.993-5.644-.497-.174 2.007 5.643.496.175-2.006zm-9.797 3.008-.494 5.675 1.996.175.493-5.675-1.995-.175z" fill="#fff"/>
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="m501.809 92.492 5.006 1.636.575-1.78-5.006-1.636-.575 1.78zm6.098 3.792-1.626 5.034 1.77.578 1.626-5.034-1.77-.578zm3.254-10.069-1.627 5.035 1.77.578 1.627-5.034-1.77-.579zm.66 9.549 5.006 1.635.576-1.78-5.007-1.635-.575 1.78z" fill="#36205D" style="mix-blend-mode:multiply" opacity=".91"/>
|
||||
<path opacity=".92" fill-rule="evenodd" clip-rule="evenodd" d="m482.824 59.176-5.102-1.97-.692 1.814 5.101 1.97.693-1.814zm-6.118-4.264 1.958-5.13-1.803-.696-1.958 5.13 1.803.696zm-3.916 10.26 1.958-5.13-1.804-.696-1.958 5.13 1.804.696zm-.169-9.935-5.102-1.969-.692 1.814 5.101 1.969.693-1.814z" fill="#fff"/>
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="m422.267 86.583 4.383 2.649.932-1.559-4.384-2.648-.931 1.558zm4.949 4.93-2.634 4.407 1.55.936 2.634-4.407-1.55-.937zm5.267-8.816-2.633 4.408 1.549.936 2.634-4.408-1.55-.936zm-1.449 9.183 4.383 2.648.931-1.558-4.383-2.648-.931 1.558z" fill="#36205D" style="mix-blend-mode:multiply"/>
|
||||
<path opacity=".98" fill-rule="evenodd" clip-rule="evenodd" d="m493.196 132.406 2.099-3.015-1.06-.746-2.099 3.014 1.06.747zm3.747-3.307 2.998 2.111.742-1.066-2.998-2.111-.742 1.066zm-5.996-4.222 2.998 2.111.742-1.066-2.998-2.11-.742 1.065zm6.447 1.5 2.1-3.015-1.06-.746-2.099 3.014 1.059.747z" fill="#fff"/>
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="m457.351 142.295 1.593 3.144 1.105-.567-1.593-3.144-1.105.567zm1.097 4.678-3.126 1.602.563 1.112 3.127-1.602-.564-1.112zm6.254-3.204-3.127 1.602.563 1.112 3.127-1.603-.563-1.111zm-4.165 4.814 1.593 3.144 1.106-.566-1.593-3.144-1.106.566z" fill="#36205D" style="mix-blend-mode:multiply" opacity=".82"/>
|
||||
<path opacity=".71" fill-rule="evenodd" clip-rule="evenodd" d="m407.493 140.233-2.321-4.582-1.611.826 2.321 4.581 1.611-.825zm-1.599-6.817 4.556-2.335-.821-1.62-4.556 2.335.821 1.62zm-9.112 4.669 4.556-2.335-.821-1.62-4.556 2.335.821 1.62zm6.068-7.015-2.321-4.582-1.611.825 2.321 4.582 1.611-.825z" fill="#fff"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 6.4 KiB |
3
website/client/src/assets/svg/cross.svg
Normal file
@@ -0,0 +1,3 @@
|
||||
<svg width="12" height="12" viewBox="0 0 12 12" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M1.26512 0L4.84341 3.57829L3.57829 4.84341L0 1.26512L1.26512 0ZM7.15659 3.57829L10.7349 5.33207e-08L12 1.26512L8.42171 4.84341L7.15659 3.57829ZM5.33207e-08 10.7349L3.57829 7.15659L4.84341 8.42171L1.26512 12L5.33207e-08 10.7349ZM8.42171 7.15659L12 10.7349L10.7349 12L7.15659 8.42171L8.42171 7.15659Z" fill="#FFB445"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 469 B |
4
website/client/src/assets/svg/divider.svg
Normal file
@@ -0,0 +1,4 @@
|
||||
<svg width="138" height="12" viewBox="0 0 138 12" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="m127.265 0 3.578 3.578-1.265 1.265L126 1.265 127.265 0zm5.892 3.578L136.735 0 138 1.265l-3.578 3.578-1.265-1.265zM126 10.735l3.578-3.578 1.265 1.265L127.265 12 126 10.735zm8.422-3.578L138 10.735 136.735 12l-3.578-3.578 1.265-1.265z" fill="#FFB445"/>
|
||||
<path d="M114.445 4.555 112.5 1l-1.945 3.555L107.914 6h-3.828l-1.349-.737L101.5 3l-1.237 2.263L98.914 6H0v1h98.914l1.349.737L101.5 10l1.237-2.263L104.086 7h3.828l2.641 1.445L112.5 12l1.945-3.555L118 6.5l-3.555-1.945z" fill="#36205D"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 647 B |
37
website/client/src/assets/svg/gifts-birthday.svg
Normal file
@@ -0,0 +1,37 @@
|
||||
<svg width="85" height="32" viewBox="0 0 85 32" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="m4.93 12.255 2.466-.63-1.983-1.597-.63-2.468-1.595 1.986-2.465.63 1.983 1.597.63 2.468 1.595-1.986zM80.034 7.698l2.465-.63-1.983-1.597-.63-2.468-1.594 1.985-2.466.631 1.983 1.596.63 2.469 1.595-1.986zM42.27 7.427l2.929.487-1.368-2.638.487-2.932-2.635 1.37-2.928-.488 1.367 2.638-.486 2.932 2.634-1.37zM78.215 26.355l2.694 2.064.033-3.396 2.063-2.697-3.393-.034-2.694-2.065-.033 3.397-2.062 2.697 3.392.034zM38.321 28.092l2.092.348-.977-1.885.347-2.094-1.881.978-2.092-.348.977 1.884-.348 2.095 1.882-.978zM12.17 30.035l.916 1.915.981-1.882 1.913-.916-1.88-.982-.915-1.916-.981 1.882-1.913.917 1.88.982z" fill="#fff" fill-opacity=".5"/>
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="m24.878 12.01 6.73-1.805 2.524 9.433-6.73 1.806-2.524-9.433z" fill="#F9F9F9"/>
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="m18.148 13.816 6.73-1.805 2.524 9.433-6.73 1.805-2.524-9.433z" fill="#E1E0E3"/>
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="m23.532 12.372 1.346-.361 2.524 9.433-1.346.36-2.524-9.432z" fill="#6133B4"/>
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="m24.878 12.01 1.346-.36 2.524 9.433-1.346.36-2.524-9.432z" fill="#9A62FF"/>
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="m25.696 20.457 1.345-.36.361 1.347-1.346.36-.36-1.347zM23.532 12.372l1.346-.361.36 1.347-1.346.361-.36-1.347z" fill="#4F2A93"/>
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="m18.148 13.816 5.384-1.444.36 1.348-5.383 1.444-.36-1.348zM20.312 21.902l5.384-1.445.36 1.348-5.383 1.444-.36-1.347zM26.224 11.65l5.383-1.445.36 1.348-5.383 1.444-.36-1.347zM28.387 19.735l5.384-1.444.36 1.347-5.383 1.445-.36-1.348z" fill="#BDA8FF" fill-opacity=".3"/>
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="m27.041 20.096 1.346-.36.361 1.347-1.346.36-.36-1.347zM24.878 12.01l1.346-.36.36 1.347-1.346.361-.36-1.347z" fill="#6133B4"/>
|
||||
<path clip-rule="evenodd" d="M24.735 4.954c-.335-1.183-1.148-2.301-2.285-2.51-1.138-.21-1.923.616-1.7 1.476.221.86 1 1.122 3.498 2.183.71.302.823.034.487-1.149z" stroke="#6133B4" stroke-width="1.5"/>
|
||||
<path clip-rule="evenodd" d="M27.66 5.365c.648-1.044 1.737-1.895 2.888-1.782 1.151.112 1.678 1.123 1.228 1.889-.45.765-1.27.802-3.964 1.133-.765.094-.8-.195-.152-1.24z" stroke="#9A62FF" stroke-width="1.5"/>
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M26.319 4.294c-2.24-.315-1.259 2.44-.36 2.566.898.126 2.6-2.25.36-2.566z" fill="#4F2A93"/>
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="m26.016 6.454 8.279 1.165-.582 4.145-8.279-1.165.582-4.145z" fill="#F9F9F9"/>
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="m17.737 5.29 8.279 1.164-.582 4.145-8.279-1.165.582-4.145z" fill="#E1E0E3"/>
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="m23.256 6.066 5.52.777-.582 4.144-5.52-.776.582-4.145z" fill="#9A62FF"/>
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="m23.256 6.066 2.76.388-.582 4.145-2.76-.388.582-4.145z" fill="#6133B4"/>
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="m26.016 6.454 2.76.389-.195 1.381-2.76-.388.195-1.382z" fill="#6133B4"/>
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="m23.256 6.066 2.76.388-.194 1.382-2.76-.388.194-1.382z" fill="#4F2A93"/>
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="m17.349 8.053 5.52.776-.195 1.382-5.519-.777.194-1.381zM28.388 9.606l5.519.776-.194 1.382-5.52-.777.195-1.381z" fill="#BDA8FF" fill-opacity=".3"/>
|
||||
<path clip-rule="evenodd" d="M56.55 9.16c-.624-1.413-1.83-2.662-3.282-2.724-1.452-.062-2.285 1.104-1.858 2.135.426 1.031 1.441 1.22 4.734 2.104.935.25 1.03-.102.406-1.515z" stroke="#6133B4" stroke-width="1.5"/>
|
||||
<path clip-rule="evenodd" d="M60.26 9.16c.624-1.413 1.83-2.662 3.283-2.724 1.451-.062 2.284 1.104 1.857 2.135-.426 1.031-1.44 1.22-4.734 2.104-.935.25-1.03-.102-.406-1.515z" stroke="#9A62FF" stroke-width="1.5"/>
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M58.405 8.061c-2.842 0-1.14 3.256 0 3.256s2.842-3.256 0-3.256z" fill="#4F2A93"/>
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M58.405 10.802H68.91v5.259H58.405v-5.259z" fill="#F9F9F9"/>
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M47.901 10.802h10.504v5.259H47.901v-5.259z" fill="#E1E0E3"/>
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M54.904 10.802h7.002v5.259h-7.002v-5.259z" fill="#9A62FF"/>
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M54.904 10.802h3.501v5.259h-3.501v-5.259zM58.405 10.802h3.501v1.753h-3.5v-1.753z" fill="#6133B4"/>
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M54.904 10.802h3.501v1.753h-3.501v-1.753z" fill="#4F2A93"/>
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M58.405 16.06h8.753v12.27h-8.753V16.06z" fill="#F9F9F9"/>
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M49.652 16.06h8.753v12.27h-8.753V16.06z" fill="#E1E0E3"/>
|
||||
<path fill="#6133B4" d="M56.654 16.061h1.751v12.27h-1.751z"/>
|
||||
<path fill="#9A62FF" d="M58.405 16.061h1.751v12.27h-1.751z"/>
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M56.654 26.578h1.751v1.753h-1.75v-1.753zM56.654 16.06h1.751v1.754h-1.75V16.06z" fill="#4F2A93"/>
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M49.652 16.06h7.002v1.754h-7.002V16.06z" fill="#BDA8FF" fill-opacity=".3"/>
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M47.901 14.308h7.003v1.753H47.9v-1.753zM49.652 26.578h7.002v1.753h-7.002v-1.753zM60.156 16.06h7.002v1.754h-7.002V16.06z" fill="#BDA8FF" fill-opacity=".3"/>
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M61.906 14.308h7.003v1.753h-7.003v-1.753zM60.156 26.578h7.002v1.753h-7.002v-1.753z" fill="#BDA8FF" fill-opacity=".3"/>
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M58.405 26.578h1.75v1.753h-1.75v-1.753zM58.405 16.06h1.75v1.754h-1.75V16.06z" fill="#6133B4"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 5.7 KiB |
@@ -0,0 +1,9 @@
|
||||
<svg width="68" height="68" viewBox="0 0 68 68" fill="none" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
|
||||
<path fill="url(#sxizdfpdya)" d="M0 0h68v68H0z"/>
|
||||
<defs>
|
||||
<pattern id="sxizdfpdya" patternContentUnits="objectBoundingBox" width="1" height="1">
|
||||
<use xlink:href="#pomapjzcdb" transform="scale(.0147)"/>
|
||||
</pattern>
|
||||
<image id="pomapjzcdb" width="68" height="68" xlink:href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAEQAAABECAYAAAA4E5OyAAAABmJLR0QA/wD/AP+gvaeTAAAACXBIWXMAAAsTAAALEwEAmpwYAAAAB3RJTUUH5gwJFx8lKwafmAAABjRJREFUeNrtm39MVWUYx78IV5BfF3Qg8kNppNIoyhKWZmUBlpRNpC3Uac7EUUGrscxM+AOHia1foKmDHOHItkbhLGnpzGVBimtlozmVTeByCRDhwgXll/THc17de3zvuedernDd3uefc895f5/zuc/3ed57DyBNmjRpzpuH+sLvR8fGAODR0nS+YmAgAMCQNQMAMJKwkys//+tUAMDQDTrPzNgIACj58iAAoLH5LADgx/Kzwols/zyba3+jny9n7WNmJ3LXffzoONUHTrVPyvDg7sEUyQRvXrYKrvX2AgCmK2RUxL9OT35oDzWs38bVf3XlNe78sfindE3gam/TpCw87fwPwuuSEL2EXMg6DgBY/HW6+E4OdQAA4lZ4CYnotVgBAEvShuiIRwAAXxV/y9Xbve+jSSHj2SfIl1RLQpwkRO1LmDEimJV+Qyqy+709wvZx/3wBAFhk3QQAONlYqKoxpGuijLDfvnduodmnTwIAUrM2ataThDhKSEp9FH2o38/5iopCuuO1/drqceAy+YiSAPI5m+rE9UvLcjTnweKfJWk7nVtppb5qkhB7hLAI01Y8wdSjyzLM9aCOJ9qrI+jDZTqkNlwBAByLixZOpMtk4uIeZrVrqkgVhtYL4x9m830iXXJDJCH2CGGqwXKB4gKxevw9eBgA0HDwIgAg94UdAICZL1JSkd5H5w2VVB4ZHg8A6IkkEoKMREKPhVTM/AHFPdNLxHFP6TnKdTIX8vOp7a8AABxWcpnVwZ9pLvjSlRYAwNzoKEmIS1TGlnqc2H1aWO5n8qSIFGsAAKdazVx53pR5pDog1SkMuF8z7rnD1yi+a4bRICy39vUBAPwDAhSVe5uy3Scp283+iUjE8ymSEJcQolaPVxZkkldPJRKiYmZqtl+3iy9vaWwk1agcJTUKJ18S9TI5gSu59ASjP07R9F0PW1YLV1BlzSMfhh1SZSaEkHe25ZMK1LQBANpa2wEAyTELxjUw64dZFOYJs21bxkjxcdAL1qzdCgBYXrlLEuJSlWFPdGlmuOIL6Lz/L4pITeZmIicnnH/SVV5cOfM9rJ9TpUyF5rl0YZXtebpISTr6viTEpXHIgy9NAwD4+voCAA4da+YIamn05OqbzKNc+bqMhwAAAwMDCiHudUMkIc4Swr7zakvf7698omNoaKiKqA6uXG+/kpB7jRCmBsEhscoVyikWrpoFAPAYJZ8wcqvjQQBAeKgRADDmST7n3HdXlRoGpV+KXFcVxWiO391F+zCY7dxC9baXhOglxPIL/UhqNlOEunKfNwAgInKYU5kLJ9Sbqjds9Ej15iYZOJVhVlfM9k3oERqf8ZE+xK0JYZElix96/iQ1iFRtXcYm+3E+5OaUafwdv3md8yEWi0WoMrcjVjKjiyNXSYirCWE5hzqrPVPA5ybZR4xc+d6VlzlfkKbakj20voMrj00f4fZNWI4k4xB3J4R9p5dmQjM3OX7AU3Of4+cy7XI/Ve7Dxk3eEiMJuSciVZbd3jZSjfkgdVi2KUyzvb1ydf+Tnf1KQvQSYisLTcyYodlh8ub7uPjDXnt1xGpr3M7OrnEtVG97SYg9QrYVPQcAWDywXZXdQslF9HXMIlZbpDBrrTOofAhlv7W+bwjr118sI082SL/wfZpfJ33IhBJiDAxWvtx0iFg0zMcR9bwqtGFM1cOAQ0NGLBLXvzUPdRbe2y1Vxi1UpiFsr/LpE+76rIQR7jzI3yD0Hepsl1mPdVilMrbGhSY51zt7JSFuEameKZjOZbfrKnxdOoGqLCuX/U62SUIcJaS8ZQN3fmItX74hqpwj6M1q/h9BJataOQLKW14TD9Sib8JMZT7MrZOEuAUhDhO0AuMiwJb919k0LjIu/UH7MMuXSUIcsjveuYt7IH7MHSdq7FkOAAgJpm3/t/Lpf6v23rlj/7Pt7DYJ28t37hwlJDHh8TEA6LcOCJ8QM3an7e5DKE/mDrUIquHO/fzF8Y2X6WnhdTb+lqJsISHs/R1b47P2R/7NkYQ4pDJhIXPoCXp3c/sOIR7OvW1gi6QRPyJimnegMLtlqhI+JwgAYG7qEZL37uatuubB+rltVqkyExKH3G1TkzHefhixhkBJiDRp0qTddfsfGCIUXNZsU4gAAAAASUVORK5CYII="/>
|
||||
</defs>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 2.7 KiB |
1
website/client/src/assets/svg/new-close.svg
Normal file
@@ -0,0 +1 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?><svg id="a" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16"><rect width="16" height="16" fill="none"/><g id="b"><g id="c"><g id="d"><polygon id="e" points="12.2 2 14 3.8 9.8 8 14 12.2 12.2 14 8 9.8 3.8 14 2 12.2 6.2 8 2 3.8 3.8 2 8 6.2 12.2 2"/></g></g></g></svg>
|
||||
|
After Width: | Height: | Size: 308 B |
5
website/client/src/assets/svg/stripe.svg
Normal file
@@ -0,0 +1,5 @@
|
||||
<svg width="48" height="20" viewBox="0 0 48 20" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M48 10.334c0-3.418-1.653-6.115-4.813-6.115-3.174 0-5.094 2.697-5.094 6.088 0 4.019 2.267 6.048 5.52 6.048 1.587 0 2.787-.36 3.694-.868v-2.67c-.907.454-1.947.735-3.267.735-1.293 0-2.44-.454-2.587-2.03h6.52c0-.173.027-.868.027-1.188zm-6.587-1.268c0-1.51.92-2.137 1.76-2.137.813 0 1.68.628 1.68 2.136h-3.44zM32.947 4.22c-1.307 0-2.147.613-2.614 1.04l-.173-.827h-2.933V20l3.333-.707.013-3.779c.48.347 1.187.841 2.36.841 2.387 0 4.56-1.922 4.56-6.155-.013-3.871-2.213-5.98-4.546-5.98zm-.8 9.198c-.787 0-1.254-.28-1.574-.627l-.013-4.954c.347-.387.827-.654 1.587-.654 1.213 0 2.053 1.362 2.053 3.11 0 1.79-.827 3.125-2.053 3.125zM22.64 3.431l3.346-.72V0L22.64.708V3.43z" fill="#635BFF"/>
|
||||
<path fill="#635BFF" d="M22.64 4.446h3.347v11.682H22.64z"/>
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="m19.053 5.434-.213-.988h-2.88v11.682h3.333V8.211c.787-1.028 2.12-.841 2.534-.694V4.446c-.427-.16-1.987-.454-2.774.988zM12.387 1.549l-3.254.694-.013 10.694c0 1.976 1.48 3.431 3.453 3.431 1.094 0 1.894-.2 2.334-.44v-2.71c-.427.173-2.534.787-2.534-1.189V7.29h2.534V4.447h-2.534l.014-2.897zM3.373 7.837c0-.52.427-.72 1.134-.72 1.013 0 2.293.306 3.306.854V4.833a8.783 8.783 0 0 0-3.306-.614C1.8 4.22 0 5.634 0 7.997c0 3.685 5.067 3.098 5.067 4.687 0 .614-.534.814-1.28.814-1.107 0-2.52-.454-3.64-1.068v3.178a9.233 9.233 0 0 0 3.64.76c2.773 0 4.68-1.375 4.68-3.764-.014-3.98-5.094-3.271-5.094-4.767z" fill="#635BFF"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 1.5 KiB |
1
website/client/src/assets/svg/sync-2.svg
Normal file
@@ -0,0 +1 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?><svg id="a" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16"><path id="b" d="m10,6h6V0h-2v2.72C12.49.99,10.3,0,8,0,3.59,0,0,3.59,0,8s3.59,8,8,8c2.69,0,5.2-1.35,6.68-3.6l-1.67-1.1c-1.11,1.69-2.99,2.71-5.01,2.7-3.31,0-6-2.69-6-6s2.69-6,6-6c1.72,0,3.33.74,4.46,2h-2.46v2Z" fill-rule="evenodd"/></svg>
|
||||
|
After Width: | Height: | Size: 341 B |
@@ -22,6 +22,10 @@
|
||||
Account created:
|
||||
<strong>{{ hero.auth.timestamps.created | formatDate }}</strong>
|
||||
</div>
|
||||
<div v-if="hero.flags.thirdPartyTools">
|
||||
User has employed <strong>third party tools</strong>. Last known usage:
|
||||
<strong>{{ hero.flags.thirdPartyTools | formatDate }}</strong>
|
||||
</div>
|
||||
<div v-if="cronError">
|
||||
"lastCron" value:
|
||||
<strong>{{ hero.lastCron | formatDate }}</strong>
|
||||
|
||||
@@ -17,10 +17,18 @@
|
||||
Payment schedule ("basic-earned" is monthly):
|
||||
<strong>{{ hero.purchased.plan.planId }}</strong>
|
||||
</div>
|
||||
<div v-if="hero.purchased.plan.planId == 'group_plan_auto'">
|
||||
Group plan ID:
|
||||
<strong>{{ hero.purchased.plan.owner }}</strong>
|
||||
</div>
|
||||
<div v-if="hero.purchased.plan.dateCreated">
|
||||
Creation date:
|
||||
<strong>{{ dateFormat(hero.purchased.plan.dateCreated) }}</strong>
|
||||
</div>
|
||||
<div v-if="hero.purchased.plan.dateCurrentTypeCreated">
|
||||
Start date for current subscription type:
|
||||
<strong>{{ dateFormat(hero.purchased.plan.dateCurrentTypeCreated) }}</strong>
|
||||
</div>
|
||||
<div>
|
||||
Termination date:
|
||||
<strong
|
||||
@@ -43,42 +51,66 @@
|
||||
</label>
|
||||
</div>
|
||||
<div>
|
||||
Months until renewal:
|
||||
Perk offset months:
|
||||
<strong>{{ hero.purchased.plan.consecutive.offset }}</strong>
|
||||
</div>
|
||||
<div>
|
||||
Next Mystic Hourglass:
|
||||
<strong>{{ nextHourglassDate }}</strong>
|
||||
</div>
|
||||
<div class="form-inline">
|
||||
<label>
|
||||
Mystic Hourglasses:
|
||||
<input
|
||||
v-model="hero.purchased.plan.consecutive.trinkets"
|
||||
class="form-control"
|
||||
type="number"
|
||||
min="0"
|
||||
step="1"
|
||||
>
|
||||
</label>
|
||||
</div>
|
||||
<div>
|
||||
Gem cap:
|
||||
<strong>{{ hero.purchased.plan.consecutive.gemCapExtra + 25 }}</strong>
|
||||
</div>
|
||||
<div class="form-inline">
|
||||
<label>
|
||||
Gems bought this month:
|
||||
<input
|
||||
v-model="hero.purchased.plan.gemsBought"
|
||||
class="form-control"
|
||||
type="number"
|
||||
min="0"
|
||||
:max="hero.purchased.plan.consecutive.gemCapExtra + 25"
|
||||
step="1"
|
||||
>
|
||||
</label>
|
||||
</div>
|
||||
<div class="form-inline">
|
||||
Perk month count:
|
||||
<input
|
||||
v-model="hero.purchased.plan.perkMonthCount"
|
||||
class="form-control"
|
||||
type="number"
|
||||
min="0"
|
||||
max="2"
|
||||
step="1"
|
||||
>
|
||||
</div>
|
||||
<div>
|
||||
Next Mystic Hourglass:
|
||||
<strong>{{ nextHourglassDate }}</strong>
|
||||
</div>
|
||||
<div class="form-inline">
|
||||
<label>
|
||||
Mystic Hourglasses:
|
||||
<input
|
||||
v-model="hero.purchased.plan.consecutive.trinkets"
|
||||
class="form-control"
|
||||
type="number"
|
||||
min="0"
|
||||
step="1"
|
||||
>
|
||||
</label>
|
||||
</div>
|
||||
<div class="form-inline">
|
||||
<label>
|
||||
Gem cap increase:
|
||||
<input
|
||||
v-model="hero.purchased.plan.consecutive.gemCapExtra"
|
||||
class="form-control"
|
||||
type="number"
|
||||
min="0"
|
||||
max="25"
|
||||
step="5"
|
||||
>
|
||||
</label>
|
||||
</div>
|
||||
<div>
|
||||
Total Gem cap:
|
||||
<strong>{{ Number(hero.purchased.plan.consecutive.gemCapExtra) + 25 }}</strong>
|
||||
</div>
|
||||
<div class="form-inline">
|
||||
<label>
|
||||
Gems bought this month:
|
||||
<input
|
||||
v-model="hero.purchased.plan.gemsBought"
|
||||
class="form-control"
|
||||
type="number"
|
||||
min="0"
|
||||
:max="hero.purchased.plan.consecutive.gemCapExtra + 25"
|
||||
step="1"
|
||||
>
|
||||
</label>
|
||||
</div>
|
||||
<div
|
||||
v-if="hero.purchased.plan.extraMonths > 0"
|
||||
>
|
||||
@@ -136,14 +168,7 @@ export default {
|
||||
nextHourglassDate () {
|
||||
const currentPlanContext = getPlanContext(this.hero, new Date());
|
||||
|
||||
return currentPlanContext.nextHourglassDate.format('MMMM');
|
||||
},
|
||||
},
|
||||
watch: {
|
||||
'hero.purchased.plan.consecutive.count' () { // eslint-disable-line object-shorthand
|
||||
this.hero.purchased.plan.consecutive.gemCapExtra = Math.min(
|
||||
Math.floor(this.hero.purchased.plan.consecutive.count / 3) * 5, 25,
|
||||
);
|
||||
return currentPlanContext.nextHourglassDate.format('MMMM YYYY');
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
|
||||
@@ -86,6 +86,13 @@
|
||||
>{{ $t('companyContribute') }}
|
||||
</a>
|
||||
</li>
|
||||
<li>
|
||||
<a
|
||||
href="https://translate.habitica.com/"
|
||||
target="_blank"
|
||||
>{{ $t('translateHabitica') }}
|
||||
</a>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
<!-- Support -->
|
||||
@@ -101,6 +108,7 @@
|
||||
v-if="user"
|
||||
>
|
||||
<a
|
||||
href=""
|
||||
target="_blank"
|
||||
@click.prevent="openBugReportModal()"
|
||||
>
|
||||
@@ -205,7 +213,7 @@
|
||||
</a>
|
||||
<a
|
||||
class="social-circle"
|
||||
href="https://twitter.com/habitica"
|
||||
href="https://twitter.com/habitica/"
|
||||
target="_blank"
|
||||
>
|
||||
<div
|
||||
@@ -215,7 +223,7 @@
|
||||
</a>
|
||||
<a
|
||||
class="social-circle"
|
||||
href="https://www.facebook.com/Habitica"
|
||||
href="https://www.facebook.com/Habitica/"
|
||||
target="_blank"
|
||||
>
|
||||
<div
|
||||
@@ -224,7 +232,7 @@
|
||||
></div>
|
||||
</a><a
|
||||
class="social-circle"
|
||||
href="https://www.tumblr.com/Habitica"
|
||||
href="http://blog.habitrpg.com/"
|
||||
target="_blank"
|
||||
>
|
||||
<div
|
||||
@@ -472,10 +480,6 @@ footer {
|
||||
color: $purple-300;
|
||||
text-decoration: underline;
|
||||
}
|
||||
a:not([href]):not([class]):hover { // needed to make "report a bug"'s hover state correct
|
||||
color: $purple-300;
|
||||
text-decoration: underline;
|
||||
}
|
||||
|
||||
column-gap: 1.5rem;
|
||||
display: grid;
|
||||
@@ -578,6 +582,7 @@ h3 {
|
||||
.text{
|
||||
display: inline-block;
|
||||
vertical-align: bottom;
|
||||
text-overflow: hidden;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -674,11 +679,6 @@ h3 {
|
||||
|
||||
footer {
|
||||
padding: 24px 16px;
|
||||
a:not([href]):not([class]):hover { // needed to make "report a bug"'s hover state correct
|
||||
color: $purple-300;
|
||||
text-decoration: underline;
|
||||
}
|
||||
|
||||
column-gap: 1.5rem;
|
||||
display: grid;
|
||||
grid-template-areas:
|
||||
@@ -718,10 +718,6 @@ h3 {
|
||||
@media (max-width: 1024px) and (min-width: 768px) {
|
||||
footer {
|
||||
padding: 24px 24px;
|
||||
a:not([href]):not([class]):hover { // needed to make "report a bug"'s hover state correct
|
||||
color: $purple-300;
|
||||
text-decoration: underline;
|
||||
}
|
||||
}
|
||||
|
||||
.desktop {
|
||||
@@ -814,7 +810,7 @@ export default {
|
||||
...mapState({ user: 'user.data' }),
|
||||
...mapState(['isUserLoaded']),
|
||||
getDataDisplayToolUrl () {
|
||||
const base = 'https://oldgods.net/habitrpg/habitrpg_user_data_display.html';
|
||||
const base = 'https://tools.habitica.com/';
|
||||
if (!this.user) return null;
|
||||
return `${base}?uuid=${this.user._id}`;
|
||||
},
|
||||
|
||||
@@ -244,7 +244,7 @@ export default {
|
||||
petClass () {
|
||||
if (some(
|
||||
this.currentEventList,
|
||||
event => moment().isBetween(event.start, event.end) && event.aprilFools && event.aprilFools === 'virtual',
|
||||
event => moment().isBetween(event.start, event.end) && event.aprilFools && event.aprilFools === 'teaShop',
|
||||
)) {
|
||||
return this.foolPet(this.member.items.currentPet);
|
||||
}
|
||||
|
||||
@@ -159,7 +159,6 @@ label {
|
||||
}
|
||||
|
||||
.cancel-link {
|
||||
color: $blue-10;
|
||||
line-height: 1.71;
|
||||
}
|
||||
|
||||
|
||||
@@ -107,7 +107,6 @@ label {
|
||||
}
|
||||
|
||||
.cancel-link {
|
||||
color: $blue-10;
|
||||
line-height: 1.71;
|
||||
}
|
||||
|
||||
|
||||
@@ -322,6 +322,7 @@ import omit from 'lodash/omit';
|
||||
import { v4 as uuid } from 'uuid';
|
||||
|
||||
import { userStateMixin } from '../../mixins/userState';
|
||||
import externalLinks from '../../mixins/externalLinks';
|
||||
import memberSearchDropdown from '@/components/members/memberSearchDropdown';
|
||||
import closeChallengeModal from './closeChallengeModal';
|
||||
import Column from '../tasks/column';
|
||||
@@ -358,7 +359,7 @@ export default {
|
||||
userLink,
|
||||
groupLink,
|
||||
},
|
||||
mixins: [challengeMemberSearchMixin, userStateMixin],
|
||||
mixins: [challengeMemberSearchMixin, externalLinks, userStateMixin],
|
||||
props: ['challengeId'],
|
||||
data () {
|
||||
return {
|
||||
@@ -414,6 +415,10 @@ export default {
|
||||
mounted () {
|
||||
if (!this.searchId) this.searchId = this.challengeId;
|
||||
if (!this.challenge._id) this.loadChallenge();
|
||||
this.handleExternalLinks();
|
||||
},
|
||||
updated () {
|
||||
this.handleExternalLinks();
|
||||
},
|
||||
async beforeRouteUpdate (to, from, next) {
|
||||
this.searchId = to.params.challengeId;
|
||||
|
||||
@@ -120,6 +120,7 @@ import { mapState } from '@/libs/store';
|
||||
import Sidebar from './sidebar';
|
||||
import ChallengeItem from './challengeItem';
|
||||
import challengeModal from './challengeModal';
|
||||
import externalLinks from '@/mixins/externalLinks';
|
||||
import challengeUtilities from '@/mixins/challengeUtilities';
|
||||
|
||||
import positiveIcon from '@/assets/svg/positive.svg';
|
||||
@@ -131,7 +132,7 @@ export default {
|
||||
challengeModal,
|
||||
MugenScroll,
|
||||
},
|
||||
mixins: [challengeUtilities],
|
||||
mixins: [challengeUtilities, externalLinks],
|
||||
data () {
|
||||
return {
|
||||
loading: true,
|
||||
@@ -177,6 +178,10 @@ export default {
|
||||
section: this.$t('challenges'),
|
||||
});
|
||||
this.loadChallenges();
|
||||
this.handleExternalLinks();
|
||||
},
|
||||
updated () {
|
||||
this.handleExternalLinks();
|
||||
},
|
||||
methods: {
|
||||
updateSearch (eventData) {
|
||||
|
||||
@@ -81,6 +81,8 @@ import challengeModal from './challengeModal';
|
||||
import { mapState } from '@/libs/store';
|
||||
import markdownDirective from '@/directives/markdown';
|
||||
|
||||
import externalLinks from '../../mixins/externalLinks';
|
||||
|
||||
import challengeItem from './challengeItem';
|
||||
import challengeIcon from '@/assets/svg/challenge.svg';
|
||||
|
||||
@@ -92,6 +94,7 @@ export default {
|
||||
directives: {
|
||||
markdown: markdownDirective,
|
||||
},
|
||||
mixins: [externalLinks],
|
||||
props: ['group'],
|
||||
data () {
|
||||
return {
|
||||
@@ -118,6 +121,10 @@ export default {
|
||||
},
|
||||
mounted () {
|
||||
this.loadChallenges();
|
||||
this.handleExternalLinks();
|
||||
},
|
||||
updated () {
|
||||
this.handleExternalLinks();
|
||||
},
|
||||
methods: {
|
||||
async loadChallenges () {
|
||||
|
||||
@@ -145,6 +145,7 @@ import Sidebar from './sidebar';
|
||||
import ChallengeItem from './challengeItem';
|
||||
import challengeModal from './challengeModal';
|
||||
import challengeUtilities from '@/mixins/challengeUtilities';
|
||||
import externalLinks from '@/mixins/externalLinks';
|
||||
|
||||
import challengeIcon from '@/assets/svg/challenge.svg';
|
||||
import positiveIcon from '@/assets/svg/positive.svg';
|
||||
@@ -156,7 +157,7 @@ export default {
|
||||
challengeModal,
|
||||
MugenScroll,
|
||||
},
|
||||
mixins: [challengeUtilities],
|
||||
mixins: [challengeUtilities, externalLinks],
|
||||
data () {
|
||||
return {
|
||||
icons: Object.freeze({
|
||||
@@ -203,6 +204,10 @@ export default {
|
||||
section: this.$t('challenges'),
|
||||
});
|
||||
this.loadChallenges();
|
||||
this.handleExternalLinks();
|
||||
},
|
||||
updated () {
|
||||
this.handleExternalLinks();
|
||||
},
|
||||
methods: {
|
||||
updateSearch (eventData) {
|
||||
|
||||
@@ -77,7 +77,6 @@
|
||||
}
|
||||
|
||||
a.cancel-link {
|
||||
color: $blue-10;
|
||||
margin-right: .5em;
|
||||
}
|
||||
|
||||
|
||||
@@ -121,7 +121,7 @@
|
||||
v-if="editing"
|
||||
class="menu-container col-2"
|
||||
:class="{active: activeTopPage === 'backgrounds'}"
|
||||
@click="changeTopPage('backgrounds', '2022')"
|
||||
@click="changeTopPage('backgrounds', '2023')"
|
||||
>
|
||||
<div class="menu-item">
|
||||
<div
|
||||
@@ -183,10 +183,8 @@
|
||||
<div
|
||||
v-for="bg in backgroundShopSets[0].items"
|
||||
:key="bg.key"
|
||||
:id="bg.key"
|
||||
class="col-2"
|
||||
:popover-title="bg.text"
|
||||
:popover="bg.notes"
|
||||
popover-trigger="mouseenter"
|
||||
@click="unlock('background.' + bg.key)"
|
||||
>
|
||||
<div
|
||||
@@ -195,55 +193,99 @@
|
||||
>
|
||||
<div class="small-rectangle"></div>
|
||||
</div>
|
||||
<b-popover
|
||||
:target="bg.key"
|
||||
triggers="hover focus"
|
||||
placement="bottom"
|
||||
:prevent-overflow="false"
|
||||
:content="bg.notes"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
v-if="!filterBackgrounds"
|
||||
class="row text-center title-row"
|
||||
>
|
||||
<strong>{{ backgroundShopSets[1].text }}</strong>
|
||||
</div>
|
||||
<div
|
||||
v-if="!filterBackgrounds"
|
||||
class="row title-row"
|
||||
v-if="!filterBackgrounds && user.purchased.background.birthday_bash"
|
||||
>
|
||||
<div
|
||||
v-for="bg in backgroundShopSets[1].items"
|
||||
:key="bg.key"
|
||||
class="col-4 text-center customize-option background-button"
|
||||
:popover-title="bg.text"
|
||||
:popover="bg.notes"
|
||||
popover-trigger="mouseenter"
|
||||
@click="!user.purchased.background[bg.key]
|
||||
? backgroundSelected(bg) : unlock('background.' + bg.key)"
|
||||
class="row text-center title-row"
|
||||
>
|
||||
<strong>{{ backgroundShopSets[2].text }}</strong>
|
||||
</div>
|
||||
<div
|
||||
class="row title-row"
|
||||
>
|
||||
<div
|
||||
class="background"
|
||||
:class="[`background_${bg.key}`, backgroundLockedStatus(bg.key)]"
|
||||
></div>
|
||||
<i
|
||||
v-if="!user.purchased.background[bg.key]"
|
||||
class="glyphicon glyphicon-lock"
|
||||
></i>
|
||||
<div
|
||||
v-if="!user.purchased.background[bg.key]"
|
||||
class="purchase-background single d-flex align-items-center justify-content-center"
|
||||
v-for="bg in backgroundShopSets[2].items"
|
||||
:key="bg.key"
|
||||
:id="bg.key"
|
||||
class="col-4 text-center customize-option background-button"
|
||||
@click="unlock('background.' + bg.key)"
|
||||
>
|
||||
<div
|
||||
class="svg-icon hourglass"
|
||||
v-html="icons.hourglass"
|
||||
class="background"
|
||||
:class="`background_${bg.key}`"
|
||||
></div>
|
||||
<span class="price">1</span>
|
||||
</div>
|
||||
<span
|
||||
v-if="!user.purchased.background[bg.key]"
|
||||
class="badge-top"
|
||||
@click.stop.prevent="togglePinned(bg)"
|
||||
>
|
||||
<pin-badge
|
||||
:pinned="isBackgroundPinned(bg)"
|
||||
<b-popover
|
||||
:target="bg.key"
|
||||
triggers="hover focus"
|
||||
placement="bottom"
|
||||
:prevent-overflow="false"
|
||||
:content="bg.notes"
|
||||
/>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div v-if="!filterBackgrounds">
|
||||
<div
|
||||
class="row text-center title-row"
|
||||
>
|
||||
<strong>{{ backgroundShopSets[1].text }}</strong>
|
||||
</div>
|
||||
<div
|
||||
class="row title-row"
|
||||
>
|
||||
<div
|
||||
v-for="bg in backgroundShopSets[1].items"
|
||||
:key="bg.key"
|
||||
:id="bg.key"
|
||||
class="col-4 text-center customize-option background-button"
|
||||
@click="!user.purchased.background[bg.key]
|
||||
? backgroundSelected(bg) : unlock('background.' + bg.key)"
|
||||
>
|
||||
<div
|
||||
class="background"
|
||||
:class="[`background_${bg.key}`, backgroundLockedStatus(bg.key)]"
|
||||
></div>
|
||||
<i
|
||||
v-if="!user.purchased.background[bg.key]"
|
||||
class="glyphicon glyphicon-lock"
|
||||
></i>
|
||||
<div
|
||||
v-if="!user.purchased.background[bg.key]"
|
||||
class="purchase-background single d-flex align-items-center justify-content-center"
|
||||
>
|
||||
<div
|
||||
class="svg-icon hourglass"
|
||||
v-html="icons.hourglass"
|
||||
></div>
|
||||
<span class="price">1</span>
|
||||
</div>
|
||||
<span
|
||||
v-if="!user.purchased.background[bg.key]"
|
||||
class="badge-top"
|
||||
@click.stop.prevent="togglePinned(bg)"
|
||||
>
|
||||
<pin-badge
|
||||
:pinned="isBackgroundPinned(bg)"
|
||||
/>
|
||||
</span>
|
||||
<b-popover
|
||||
:target="bg.key"
|
||||
triggers="hover focus"
|
||||
placement="bottom"
|
||||
:prevent-overflow="false"
|
||||
:content="bg.notes"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<sub-menu
|
||||
@@ -275,10 +317,8 @@
|
||||
<div
|
||||
v-for="bg in set.items"
|
||||
:key="bg.key"
|
||||
:id="bg.key"
|
||||
class="col-4 text-center customize-option background-button"
|
||||
:popover-title="bg.text"
|
||||
:popover="bg.notes"
|
||||
popover-trigger="mouseenter"
|
||||
@click="!user.purchased.background[bg.key]
|
||||
? backgroundSelected(bg) : unlock('background.' + bg.key)"
|
||||
>
|
||||
@@ -309,6 +349,13 @@
|
||||
:pinned="isBackgroundPinned(bg)"
|
||||
/>
|
||||
</span>
|
||||
<b-popover
|
||||
:target="bg.key"
|
||||
triggers="hover focus"
|
||||
placement="bottom"
|
||||
:prevent-overflow="false"
|
||||
:content="bg.notes"
|
||||
/>
|
||||
</div>
|
||||
<div
|
||||
v-if="!ownsSet('background', set.items) && set.identifier !== 'incentiveBackgrounds'"
|
||||
@@ -331,16 +378,21 @@
|
||||
<div
|
||||
v-for="(bg) in ownedBackgrounds"
|
||||
:key="bg.key"
|
||||
:id="bg.key"
|
||||
class="col-4 text-center customize-option background-button"
|
||||
:popover-title="bg.text"
|
||||
:popover="bg.notes"
|
||||
popover-trigger="mouseenter"
|
||||
@click="unlock('background.' + bg.key)"
|
||||
>
|
||||
<div
|
||||
class="background"
|
||||
:class="[`background_${bg.key}`, backgroundLockedStatus(bg.key)]"
|
||||
></div>
|
||||
<b-popover
|
||||
:target="bg.key"
|
||||
triggers="hover focus"
|
||||
placement="bottom"
|
||||
:prevent-overflow="false"
|
||||
:content="bg.notes"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -1185,7 +1237,7 @@ export default {
|
||||
},
|
||||
],
|
||||
|
||||
bgSubMenuItems: ['2022', '2021', '2020', '2019', '2018', '2017', '2016', '2015', '2014'].map(y => ({
|
||||
bgSubMenuItems: ['2023', '2022', '2021', '2020', '2019', '2018', '2017', '2016', '2015', '2014'].map(y => ({
|
||||
id: y,
|
||||
label: y,
|
||||
})),
|
||||
@@ -1214,6 +1266,7 @@ export default {
|
||||
2020: [],
|
||||
2021: [],
|
||||
2022: [],
|
||||
2023: [],
|
||||
};
|
||||
|
||||
// Hack to force update for now until we restructure the data
|
||||
|
||||
209
website/client/src/components/externalLinkModal.vue
Normal file
@@ -0,0 +1,209 @@
|
||||
<template>
|
||||
<b-modal
|
||||
id="external-link-modal"
|
||||
size="md"
|
||||
>
|
||||
<!-- HEADER -->
|
||||
<div slot="modal-header">
|
||||
<div
|
||||
class="modal-close"
|
||||
@click="close()"
|
||||
>
|
||||
<div
|
||||
class="icon-close"
|
||||
v-html="icons.close"
|
||||
>
|
||||
</div>
|
||||
</div>
|
||||
<div class="exclamation-container d-flex align-items-center justify-content-center">
|
||||
<div
|
||||
v-once
|
||||
class="svg-icon svg-exclamation"
|
||||
v-html="icons.exclamation"
|
||||
></div>
|
||||
</div>
|
||||
<h2>
|
||||
{{ $t('leaveHabitica') }}
|
||||
</h2>
|
||||
</div>
|
||||
|
||||
<!-- BODY -->
|
||||
<div
|
||||
class="row leave-warning-text"
|
||||
v-html="$t('leaveHabiticaText')"
|
||||
>
|
||||
</div>
|
||||
<div
|
||||
class="skip-modal"
|
||||
>
|
||||
{{ $t('skipExternalLinkModal') }}
|
||||
</div>
|
||||
|
||||
<!-- FOOTER -->
|
||||
<div slot="modal-footer">
|
||||
<button
|
||||
v-once
|
||||
class="btn btn-primary"
|
||||
@click="proceed()"
|
||||
>
|
||||
{{ $t('continue') }}
|
||||
</button>
|
||||
<div
|
||||
v-once
|
||||
class="close-link justify-content-center"
|
||||
@click="close()"
|
||||
>
|
||||
{{ $t('cancel') }}
|
||||
</div>
|
||||
</div>
|
||||
</b-modal>
|
||||
</template>
|
||||
|
||||
<style lang="scss">
|
||||
@import '~@/assets/scss/colors.scss';
|
||||
|
||||
#external-link-modal {
|
||||
&.modal {
|
||||
display: flex !important;
|
||||
}
|
||||
|
||||
.modal-md {
|
||||
max-width: 448px;
|
||||
min-width: 330px;
|
||||
margin: auto;
|
||||
|
||||
.modal-close {
|
||||
position: absolute;
|
||||
right: 12px;
|
||||
top: 12px;
|
||||
cursor: pointer;
|
||||
|
||||
.icon-close {
|
||||
width: 16px;
|
||||
height: 16px;
|
||||
vertical-align: middle;
|
||||
|
||||
& svg {
|
||||
fill: $yellow-1;
|
||||
opacity: 0.75;
|
||||
}
|
||||
& :hover {
|
||||
fill: $yellow-1;
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.modal-content {
|
||||
background: transparent;
|
||||
}
|
||||
|
||||
.modal-header {
|
||||
justify-content: center;
|
||||
padding-top: 32px;
|
||||
padding-bottom: 0px;
|
||||
background: $yellow-100;
|
||||
border-top-right-radius: 8px;
|
||||
border-top-left-radius: 8px;
|
||||
border-bottom: none;
|
||||
|
||||
.exclamation-container {
|
||||
width: 64px;
|
||||
height: 64px;
|
||||
border-radius: 50%;
|
||||
background: $yellow-1;
|
||||
margin: 0 auto;
|
||||
margin-bottom: 16px;
|
||||
}
|
||||
|
||||
.svg-exclamation {
|
||||
width: 8px;
|
||||
color: $white;
|
||||
}
|
||||
|
||||
h2 {
|
||||
color: $yellow-1;
|
||||
margin-bottom: 16px;
|
||||
}
|
||||
}
|
||||
|
||||
.modal-body {
|
||||
padding: 16px 44px 20px 44px;
|
||||
background: $white;
|
||||
|
||||
.leave-warning-text {
|
||||
font-size: 0.875rem;
|
||||
line-height: 1.71;
|
||||
text-align: center;
|
||||
margin-top:24px;
|
||||
}
|
||||
|
||||
.skip-modal {
|
||||
color: $gray-100;
|
||||
font-size: 0.75rem;
|
||||
text-align: center;
|
||||
line-height: 1.33;
|
||||
margin-top: 16px;
|
||||
// padding-bottom: 24px;
|
||||
}
|
||||
}
|
||||
|
||||
.modal-footer {
|
||||
background: $white;
|
||||
border-bottom-right-radius: 8px;
|
||||
border-bottom-left-radius: 8px;
|
||||
justify-content: center;
|
||||
border-top: none;
|
||||
padding-top: 0;
|
||||
}
|
||||
.close-link {
|
||||
color: $purple-300;
|
||||
line-height: 1.71;
|
||||
font-size: 0.875rem;
|
||||
cursor: pointer;
|
||||
margin-top:16px;
|
||||
margin-bottom: 8px;
|
||||
text-align: center;
|
||||
|
||||
&:hover {
|
||||
text-decoration: underline;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
<script>
|
||||
import exclamationIcon from '@/assets/svg/exclamation.svg';
|
||||
import closeIcon from '@/assets/svg/new-close.svg';
|
||||
|
||||
export default {
|
||||
data () {
|
||||
return {
|
||||
icons: Object.freeze({
|
||||
close: closeIcon,
|
||||
exclamation: exclamationIcon,
|
||||
}),
|
||||
url: '',
|
||||
};
|
||||
},
|
||||
mounted () {
|
||||
this.$root.$on('habitica:external-link', url => {
|
||||
this.url = url;
|
||||
this.$root.$emit('bv::show::modal', 'external-link-modal');
|
||||
});
|
||||
},
|
||||
beforeDestroy () {
|
||||
this.$root.$off('habitica:external-link');
|
||||
},
|
||||
methods: {
|
||||
close () {
|
||||
this.$root.$emit('bv::hide::modal', 'external-link-modal');
|
||||
},
|
||||
proceed () {
|
||||
window.open(this.url, '_blank').focus();
|
||||
this.close();
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
@@ -87,6 +87,8 @@
|
||||
<script>
|
||||
import debounce from 'lodash/debounce';
|
||||
|
||||
import externalLinks from '../../mixins/externalLinks';
|
||||
|
||||
import autocomplete from '../chat/autoComplete';
|
||||
import communityGuidelines from './communityGuidelines';
|
||||
import chatMessage from '../chat/chatMessages';
|
||||
@@ -103,6 +105,7 @@ export default {
|
||||
communityGuidelines,
|
||||
chatMessage,
|
||||
},
|
||||
mixins: [externalLinks],
|
||||
props: ['label', 'group', 'placeholder'],
|
||||
data () {
|
||||
return {
|
||||
@@ -132,6 +135,10 @@ export default {
|
||||
},
|
||||
mounted () {
|
||||
this.textbox = this.$refs['user-entry'];
|
||||
this.handleExternalLinks();
|
||||
},
|
||||
updated () {
|
||||
this.handleExternalLinks();
|
||||
},
|
||||
methods: {
|
||||
// https://medium.com/@_jh3y/how-to-where-s-the-caret-getting-the-xy-position-of-the-caret-a24ba372990a
|
||||
|
||||
@@ -11,9 +11,12 @@
|
||||
<div class="quest_screen"></div>
|
||||
<div class="row heading">
|
||||
<div class="col-12 text-center pr-5 pl-5">
|
||||
<h2 v-once>
|
||||
<h1
|
||||
v-once
|
||||
class="mb-2"
|
||||
>
|
||||
{{ $t('playInPartyTitle') }}
|
||||
</h2>
|
||||
</h1>
|
||||
<p
|
||||
v-once
|
||||
class="mb-4"
|
||||
@@ -22,67 +25,91 @@
|
||||
</p>
|
||||
<button
|
||||
v-once
|
||||
class="btn btn-primary"
|
||||
class="btn btn-primary px-4 mb-2"
|
||||
@click="createParty()"
|
||||
>
|
||||
{{ $t('createParty') }}
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
<close-x
|
||||
@close="close()"
|
||||
/>
|
||||
</div>
|
||||
<div class="row grey-row">
|
||||
<div class="col-12 text-center">
|
||||
<div class="col-12 text-center px-0">
|
||||
<div class="join-party"></div>
|
||||
<h2 v-once>
|
||||
{{ $t('wantToJoinPartyTitle') }}
|
||||
</h2>
|
||||
<p v-html="$t('wantToJoinPartyDescription')"></p>
|
||||
<div
|
||||
class="form-group"
|
||||
@click="copyUsername"
|
||||
<h1
|
||||
v-once
|
||||
class="mb-2"
|
||||
>
|
||||
<div class="d-flex align-items-center">
|
||||
<label
|
||||
v-once
|
||||
class="mr-3"
|
||||
>{{ $t('username') }}</label>
|
||||
<div class="flex-grow-1">
|
||||
<div class="input-group-prepend input-group-text">
|
||||
@
|
||||
<div class="text">
|
||||
{{ user.auth.local.username }}
|
||||
</div>
|
||||
<div
|
||||
class="svg-icon copy-icon"
|
||||
v-html="icons.copy"
|
||||
></div>
|
||||
<div
|
||||
v-once
|
||||
class="small"
|
||||
>
|
||||
{{ $t('copy') }}
|
||||
</div>
|
||||
</div>
|
||||
{{ $t('wantToJoinPartyTitle') }}
|
||||
</h1>
|
||||
<p
|
||||
v-once
|
||||
class="mb-4"
|
||||
v-html="$t('partyFinderDescription')"
|
||||
>
|
||||
</p>
|
||||
<div
|
||||
v-if="seeking"
|
||||
>
|
||||
<div
|
||||
class="green-bar mb-3"
|
||||
>
|
||||
{{ $t('currentlyLookingForParty') }}
|
||||
</div>
|
||||
<div class="d-flex justify-content-center">
|
||||
<div
|
||||
class="red-link"
|
||||
@click="seekParty()"
|
||||
>
|
||||
{{ $t('leave') }}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<button
|
||||
v-else
|
||||
class="btn btn-primary px-4 mt-2 mb-1"
|
||||
@click="seekParty()"
|
||||
>
|
||||
{{ $t('lookForParty') }}
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</b-modal>
|
||||
</template>
|
||||
|
||||
<style>
|
||||
#create-party-modal .modal-body {
|
||||
padding: 0rem 0.75rem;
|
||||
}
|
||||
<style lang="scss">
|
||||
#create-party-modal {
|
||||
display: flex !important;
|
||||
overflow-y: hidden;
|
||||
|
||||
#create-party-modal .modal-dialog {
|
||||
width: 35.75rem;
|
||||
}
|
||||
@media (max-height: 770px) {
|
||||
overflow-y: auto;
|
||||
}
|
||||
|
||||
#create-party-modal .modal-header {
|
||||
padding: 0;
|
||||
border-bottom: 0px;
|
||||
.modal-body {
|
||||
padding: 0rem 0.75rem;
|
||||
}
|
||||
|
||||
.modal-content {
|
||||
border-radius: 8px;
|
||||
}
|
||||
|
||||
.modal-dialog {
|
||||
width: 566px;
|
||||
margin: auto;
|
||||
|
||||
@media (max-height: 826px) {
|
||||
margin-top: 56px;
|
||||
}
|
||||
}
|
||||
|
||||
.modal-header {
|
||||
padding: 0;
|
||||
border-bottom: 0px;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -107,15 +134,27 @@
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.green-bar {
|
||||
height: 32px;
|
||||
font-size: 14px;
|
||||
font-weight: bold;
|
||||
line-height: 1.71;
|
||||
text-align: center;
|
||||
color: $green-1;
|
||||
background-color: $green-100;
|
||||
border-radius: 2px;
|
||||
padding: 4px 0px 4px 0px;
|
||||
}
|
||||
|
||||
.grey-row {
|
||||
background-color: $gray-700;
|
||||
color: #4e4a57;
|
||||
padding: 2em;
|
||||
border-radius: 0px 0px 2px 2px;
|
||||
border-radius: 0px 0px 8px 8px;
|
||||
}
|
||||
|
||||
h2 {
|
||||
color: $gray-100;
|
||||
h1 {
|
||||
color: $purple-300;
|
||||
}
|
||||
|
||||
.header-wrap {
|
||||
@@ -132,10 +171,6 @@
|
||||
border-radius: 2px 2px 0 0;
|
||||
image-rendering: optimizequality;
|
||||
}
|
||||
|
||||
h2 {
|
||||
color: $purple-200;
|
||||
}
|
||||
}
|
||||
|
||||
.heading {
|
||||
@@ -182,6 +217,21 @@
|
||||
margin: 0.75rem auto 0.75rem 0.25rem;
|
||||
}
|
||||
|
||||
p {
|
||||
line-height: 1.71;
|
||||
}
|
||||
|
||||
.red-link {
|
||||
cursor: pointer;
|
||||
font-size: 14px;
|
||||
line-height: 1.71;
|
||||
text-align: center;
|
||||
color: $maroon-50;
|
||||
&:hover {
|
||||
text-decoration: underline;
|
||||
}
|
||||
}
|
||||
|
||||
.small {
|
||||
color: $gray-200;
|
||||
margin: auto 0.5rem auto 0.25rem;
|
||||
@@ -192,21 +242,29 @@
|
||||
import { mapState } from '@/libs/store';
|
||||
import * as Analytics from '@/libs/analytics';
|
||||
import notifications from '@/mixins/notifications';
|
||||
import closeX from '../ui/closeX';
|
||||
|
||||
import copyIcon from '@/assets/svg/copy.svg';
|
||||
|
||||
export default {
|
||||
components: {
|
||||
closeX,
|
||||
},
|
||||
mixins: [notifications],
|
||||
data () {
|
||||
return {
|
||||
icons: Object.freeze({
|
||||
copy: copyIcon,
|
||||
}),
|
||||
seeking: false,
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
...mapState({ user: 'user.data' }),
|
||||
},
|
||||
mounted () {
|
||||
this.seeking = Boolean(this.user.party.seeking);
|
||||
},
|
||||
methods: {
|
||||
async createParty () {
|
||||
const group = {
|
||||
@@ -223,7 +281,10 @@ export default {
|
||||
});
|
||||
|
||||
this.$root.$emit('bv::hide::modal', 'create-party-modal');
|
||||
this.$router.push('/party');
|
||||
await this.$router.push('/party');
|
||||
},
|
||||
close () {
|
||||
this.$root.$emit('bv::hide::modal', 'create-party-modal');
|
||||
},
|
||||
copyUsername () {
|
||||
if (navigator.clipboard) {
|
||||
@@ -238,6 +299,12 @@ export default {
|
||||
}
|
||||
this.text(this.$t('usernameCopied'));
|
||||
},
|
||||
seekParty () {
|
||||
this.$store.dispatch('user:set', {
|
||||
'party.seeking': !this.user.party.seeking ? new Date() : null,
|
||||
});
|
||||
this.seeking = !this.seeking;
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
@@ -542,7 +542,8 @@ export default {
|
||||
await this.$store.dispatch('guilds:leave', data);
|
||||
|
||||
if (this.isParty) {
|
||||
this.$router.push({ name: 'tasks' });
|
||||
await this.$router.push({ name: 'tasks' });
|
||||
window.location.reload(true);
|
||||
}
|
||||
},
|
||||
upgradeGroup () {
|
||||
|
||||
@@ -4,12 +4,12 @@
|
||||
<group-plan-creation-modal />
|
||||
<div>
|
||||
<div class="header">
|
||||
<h1 class="text-center">
|
||||
Need more for your Group?
|
||||
<h1 v-once class="text-center">
|
||||
{{ $t('groupPlanTitle') }}
|
||||
</h1>
|
||||
<div class="row">
|
||||
<div class="col-8 offset-2 text-center">
|
||||
<h2 class="sub-text">
|
||||
<h2 v-once class="sub-text">
|
||||
{{ $t('groupBenefitsDescription') }}
|
||||
</h2>
|
||||
</div>
|
||||
@@ -24,8 +24,8 @@
|
||||
src="~@/assets/images/group-plans/group-14@3x.png"
|
||||
>
|
||||
<hr>
|
||||
<h2>{{ $t('teamBasedTasks') }}</h2>
|
||||
<p>Set up an easily-viewed shared task list for the group. Assign tasks to your fellow group members, or let them claim their own tasks to make it clear what everyone is working on!</p><!-- eslint-disable-line max-len -->
|
||||
<h2 v-once> {{ $t('teamBasedTasks') }} </h2>
|
||||
<p v-once> {{ $t('teamBasedTasksListDesc') }} </p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-4">
|
||||
@@ -35,8 +35,8 @@
|
||||
src="~@/assets/images/group-plans/group-12@3x.png"
|
||||
>
|
||||
<hr>
|
||||
<h2>Group Management Controls</h2>
|
||||
<p>Use task approvals to verify that a task that was really completed, add Group Managers to share responsibilities, and enjoy a private group chat for all team members.</p><!-- eslint-disable-line max-len -->
|
||||
<h2 v-once> {{ $t('groupManagementControls') }} </h2>
|
||||
<p v-once> {{ $t('groupManagementControlsDesc') }} </p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-4">
|
||||
@@ -46,8 +46,8 @@
|
||||
src="~@/assets/images/group-plans/group-13@3x.png"
|
||||
>
|
||||
<hr>
|
||||
<h2>In-Game Benefits</h2>
|
||||
<p>Group members get an exclusive Jackalope Mount, as well as full subscription benefits, including special monthly equipment sets and the ability to buy gems with gold.</p><!-- eslint-disable-line max-len -->
|
||||
<h2 v-once> {{ $t('inGameBenefits') }} </h2>
|
||||
<p v-once> {{ $t('inGameBenefitsDesc') }} </p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -78,7 +78,6 @@
|
||||
@import '~@/assets/scss/colors.scss';
|
||||
|
||||
a:not([href]) {
|
||||
color: $blue-10;
|
||||
font-size: 16px;
|
||||
}
|
||||
|
||||
|
||||
343
website/client/src/components/groups/lookingForParty.vue
Normal file
@@ -0,0 +1,343 @@
|
||||
<template>
|
||||
<div>
|
||||
<div class="d-flex justify-content-center">
|
||||
<div
|
||||
v-if="seekers.length > 0"
|
||||
class="fit-content mx-auto mt-4"
|
||||
>
|
||||
<div class="d-flex align-items-center">
|
||||
<h1 v-once class="my-auto mr-auto"> {{ $t('findPartyMembers') }}</h1>
|
||||
<div
|
||||
class="btn btn-secondary btn-sync ml-auto my-auto pl-2 pr-3 d-flex"
|
||||
@click="refreshList()"
|
||||
>
|
||||
<div class="svg-icon icon-16 color my-auto mr-2" v-html="icons.sync"></div>
|
||||
<div class="ml-auto"> {{ $t('refreshList') }} </div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="d-flex flex-wrap seeker-list">
|
||||
<div
|
||||
v-for="(seeker, index) in seekers"
|
||||
:key="seeker._id"
|
||||
class="seeker"
|
||||
>
|
||||
<div class="d-flex">
|
||||
<avatar
|
||||
:member="seeker"
|
||||
:hideClassBadge="true"
|
||||
@click.native="showMemberModal(seeker._id)"
|
||||
class="mr-3 mb-2"
|
||||
/>
|
||||
<div class="card-data">
|
||||
<user-link
|
||||
:user-id="seeker._id"
|
||||
:name="seeker.profile.name"
|
||||
:backer="seeker.backer"
|
||||
:contributor="seeker.contributor"
|
||||
/>
|
||||
<div class="small-with-border pb-2 mb-2">
|
||||
@{{ seeker.auth.local.username }} • {{ $t('level') }} {{ seeker.stats.lvl }}
|
||||
</div>
|
||||
<div
|
||||
class="d-flex"
|
||||
>
|
||||
<strong v-once> {{ $t('classLabel') }} </strong>
|
||||
<span
|
||||
class="svg-icon d-inline-block icon-16 my-auto mx-2"
|
||||
v-html="icons[seeker.stats.class]"
|
||||
>
|
||||
</span>
|
||||
<strong
|
||||
:class="`${seeker.stats.class}-color`"
|
||||
>
|
||||
{{ $t(seeker.stats.class) }}
|
||||
</strong>
|
||||
</div>
|
||||
<div>
|
||||
<strong v-once class="mr-2"> {{ $t('checkinsLabel') }} </strong>
|
||||
{{ seeker.loginIncentives }}
|
||||
</div>
|
||||
<div>
|
||||
<strong v-once class="mr-2"> {{ $t('languageLabel') }} </strong>
|
||||
{{ displayLanguage(seeker.preferences.language) }}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<strong
|
||||
v-if="!seeker.invited"
|
||||
@click="inviteUser(seeker._id, index)"
|
||||
class="btn btn-primary w-100"
|
||||
>
|
||||
{{ $t('inviteToParty') }}
|
||||
</strong>
|
||||
<div
|
||||
v-else
|
||||
@click="rescindInvite(seeker._id, index)"
|
||||
class="btn btn-success w-100"
|
||||
v-html="$t('invitedToYourParty')"
|
||||
>
|
||||
</div>
|
||||
</div>
|
||||
<mugen-scroll
|
||||
v-show="loading"
|
||||
:handler="infiniteScrollTrigger"
|
||||
:should-handle="!loading && canLoadMore"
|
||||
:threshold="1"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
v-if="seekers.length === 0 && !loading"
|
||||
class="d-flex flex-column empty-state text-center my-5"
|
||||
>
|
||||
<div class="gray-circle mb-3 mx-auto d-flex">
|
||||
<div
|
||||
class="svg-icon icon-32 color m-auto"
|
||||
v-html="icons.users"
|
||||
>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
<strong class="mb-1"> {{ $t('findMorePartyMembers') }} </strong>
|
||||
<div v-html="$t('noOneLooking')"></div>
|
||||
</div>
|
||||
</div>
|
||||
<h2
|
||||
v-show="loading"
|
||||
class="loading"
|
||||
:class="seekers.length === 0 ? 'mt-3' : 'mt-0'"
|
||||
>
|
||||
{{ $t('loading') }}
|
||||
</h2>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
@import '~@/assets/scss/colors.scss';
|
||||
|
||||
h1 {
|
||||
color: $purple-300;
|
||||
}
|
||||
|
||||
strong {
|
||||
line-height: 1.71;
|
||||
}
|
||||
.avatar {
|
||||
background-color: $gray-600;
|
||||
}
|
||||
|
||||
.btn-success {
|
||||
box-shadow: none;
|
||||
color: $green-1;
|
||||
font-weight: normal;
|
||||
|
||||
&:not(:disabled):not(.disabled):active {
|
||||
color: $green-1;
|
||||
}
|
||||
}
|
||||
|
||||
.btn-sync {
|
||||
min-width: 128px;
|
||||
max-height: 32px;
|
||||
|
||||
.svg-icon {
|
||||
color: $gray-200;
|
||||
}
|
||||
}
|
||||
|
||||
.card-data {
|
||||
width: 267px;
|
||||
}
|
||||
|
||||
.empty-state {
|
||||
color: $gray-100;
|
||||
line-height: 1.71;
|
||||
}
|
||||
|
||||
.fit-content {
|
||||
width: fit-content;
|
||||
}
|
||||
|
||||
.gray-circle {
|
||||
width: 64px;
|
||||
height: 64px;
|
||||
color: $gray-600;
|
||||
background-color: $gray-200;
|
||||
border-radius: 100px;
|
||||
|
||||
.icon-32 {
|
||||
height: auto;
|
||||
}
|
||||
}
|
||||
|
||||
.loading {
|
||||
text-align: center;
|
||||
color: $purple-300;
|
||||
}
|
||||
|
||||
.seeker-list {
|
||||
max-width: 920px;
|
||||
|
||||
@media (max-width: 962px) {
|
||||
max-width: 464px;
|
||||
};
|
||||
|
||||
.seeker {
|
||||
width: 448px;
|
||||
margin-bottom: 24px;
|
||||
padding: 8px;
|
||||
border-radius: 4px;
|
||||
box-shadow: 0 1px 3px 0 rgba(26, 24, 29, 0.12), 0 1px 2px 0 rgba(26, 24, 29, 0.24);
|
||||
|
||||
&:first-of-type {
|
||||
margin-top: 24px;
|
||||
}
|
||||
|
||||
@media (min-width: 963px) {
|
||||
&:nth-child(2) {
|
||||
margin-top: 24px;
|
||||
}
|
||||
&:nth-child(even) {
|
||||
margin-left: 24px;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.small-with-border {
|
||||
border-bottom: 1px solid $gray-500;
|
||||
color: $gray-100;
|
||||
font-size: 12px;
|
||||
font-weight: normal;
|
||||
line-height: 1.33;
|
||||
}
|
||||
|
||||
.healer-color {
|
||||
color: $yellow-10;
|
||||
}
|
||||
|
||||
.rogue-color {
|
||||
color: $purple-200;
|
||||
}
|
||||
|
||||
.warrior-color {
|
||||
color: $red-50;
|
||||
}
|
||||
|
||||
.wizard-color {
|
||||
color: $blue-10;
|
||||
}
|
||||
</style>
|
||||
|
||||
<script>
|
||||
import debounce from 'lodash/debounce';
|
||||
import MugenScroll from 'vue-mugen-scroll';
|
||||
import Avatar from '../avatar';
|
||||
import userLink from '../userLink';
|
||||
import { mapState } from '@/libs/store';
|
||||
|
||||
import syncIcon from '@/assets/svg/sync-2.svg';
|
||||
import usersIcon from '@/assets/svg/users.svg';
|
||||
import warriorIcon from '@/assets/svg/warrior.svg';
|
||||
import rogueIcon from '@/assets/svg/rogue.svg';
|
||||
import healerIcon from '@/assets/svg/healer.svg';
|
||||
import wizardIcon from '@/assets/svg/wizard.svg';
|
||||
|
||||
export default {
|
||||
components: {
|
||||
Avatar,
|
||||
MugenScroll,
|
||||
userLink,
|
||||
},
|
||||
data () {
|
||||
return {
|
||||
canLoadMore: true,
|
||||
loading: true,
|
||||
page: 0,
|
||||
party: {},
|
||||
seekers: [],
|
||||
icons: Object.freeze({
|
||||
warrior: warriorIcon,
|
||||
rogue: rogueIcon,
|
||||
healer: healerIcon,
|
||||
sync: syncIcon,
|
||||
users: usersIcon,
|
||||
wizard: wizardIcon,
|
||||
}),
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
...mapState({
|
||||
availableLanguages: 'i18n.availableLanguages',
|
||||
user: 'user.data',
|
||||
}),
|
||||
},
|
||||
async mounted () {
|
||||
try {
|
||||
this.party = await this.$store.dispatch('guilds:getGroup', { groupId: this.user.party._id });
|
||||
} catch {
|
||||
this.$router.push('/');
|
||||
}
|
||||
if (!this.party._id || this.party.leader._id !== this.user._id) {
|
||||
this.$router.push('/');
|
||||
} else {
|
||||
this.$store.dispatch('common:setTitle', {
|
||||
section: this.$t('lookingForPartyTitle'),
|
||||
});
|
||||
this.seekers = await this.$store.dispatch('party:lookingForParty');
|
||||
this.canLoadMore = this.seekers.length === 30;
|
||||
this.loading = false;
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
displayLanguage (languageCode) {
|
||||
const language = this.availableLanguages.find(lang => lang.code === languageCode);
|
||||
if (language) {
|
||||
return language.name;
|
||||
}
|
||||
return languageCode;
|
||||
},
|
||||
infiniteScrollTrigger () {
|
||||
if (this.canLoadMore) {
|
||||
this.loading = true;
|
||||
}
|
||||
|
||||
this.loadMore();
|
||||
},
|
||||
async inviteUser (userId, index) {
|
||||
await this.$store.dispatch('guilds:invite', {
|
||||
invitationDetails: {
|
||||
inviter: this.user.profile.name,
|
||||
uuids: [userId],
|
||||
},
|
||||
groupId: this.party._id,
|
||||
});
|
||||
this.seekers[index].invited = true;
|
||||
},
|
||||
loadMore: debounce(async function loadMoreDebounce () {
|
||||
this.page += 1;
|
||||
const addlSeekers = await this.$store.dispatch('party:lookingForParty', { page: this.page });
|
||||
this.seekers = this.seekers.concat(addlSeekers);
|
||||
this.canLoadMore = this.seekers.length % 30 === 0;
|
||||
this.loading = false;
|
||||
}, 1000),
|
||||
async refreshList () {
|
||||
this.loading = true;
|
||||
this.page = 0;
|
||||
this.seekers = await this.$store.dispatch('party:lookingForParty');
|
||||
this.canLoadMore = this.seekers.length === 30;
|
||||
this.loading = false;
|
||||
},
|
||||
async rescindInvite (userId, index) {
|
||||
await this.$store.dispatch('members:removeMember', {
|
||||
memberId: userId,
|
||||
groupId: this.party._id,
|
||||
});
|
||||
this.seekers[index].invited = false;
|
||||
},
|
||||
showMemberModal (userId) {
|
||||
this.$router.push({ name: 'userProfile', params: { userId } });
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
@@ -245,10 +245,6 @@
|
||||
text-align: center;
|
||||
|
||||
color: $gray-100;
|
||||
|
||||
a {
|
||||
color: $blue-10;
|
||||
}
|
||||
}
|
||||
|
||||
#quest-detail-modal {
|
||||
|
||||
@@ -377,11 +377,9 @@
|
||||
|
||||
.members-invited {
|
||||
min-height: 1rem;
|
||||
color: $blue-10;
|
||||
margin: 0;
|
||||
|
||||
&:hover, &:focus {
|
||||
color: $blue-10;
|
||||
text-decoration: underline;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
<div class="sidebar px-4">
|
||||
<div>
|
||||
<div class="buttons-wrapper">
|
||||
<div class="button-container button-with-menu-row">
|
||||
<div class="button-container d-flex">
|
||||
<button
|
||||
v-if="!isMember"
|
||||
class="btn btn-success btn-success"
|
||||
@@ -203,10 +203,6 @@ export default {
|
||||
}
|
||||
}
|
||||
|
||||
.button-with-menu-row {
|
||||
display: flex;
|
||||
}
|
||||
|
||||
.menuIcon {
|
||||
width: 4px;
|
||||
height: 1rem;
|
||||
|
||||
@@ -340,12 +340,13 @@
|
||||
<li>
|
||||
<a
|
||||
v-once
|
||||
href="https://oldgods.net/habitrpg/habitrpg_user_data_display.html"
|
||||
href="https://tools.habitica.com/"
|
||||
target="_blank"
|
||||
>{{ $t('dataDisplayTool') }}</a>
|
||||
</li>
|
||||
<li>
|
||||
<a
|
||||
href=""
|
||||
target="_blank"
|
||||
@click.prevent="openBugReportModal()"
|
||||
>
|
||||
@@ -521,21 +522,6 @@
|
||||
margin-left: .5em;
|
||||
}
|
||||
|
||||
// formats the report a bug link to match the others
|
||||
a:not([href]) {
|
||||
&:not([role=button]) {
|
||||
color: #007bff;
|
||||
text-decoration: none;
|
||||
}
|
||||
}
|
||||
|
||||
a:not([href]):hover {
|
||||
&:not([role=button]) {
|
||||
color: #0056b3;
|
||||
text-decoration: underline;
|
||||
}
|
||||
}
|
||||
|
||||
.tier1-icon, .tier2-icon {
|
||||
width: 11px;
|
||||
}
|
||||
@@ -759,6 +745,7 @@
|
||||
</style>
|
||||
|
||||
<script>
|
||||
import find from 'lodash/find';
|
||||
import { mapState } from '@/libs/store';
|
||||
import { goToModForm } from '@/libs/modform';
|
||||
|
||||
@@ -835,22 +822,23 @@ export default {
|
||||
computed: {
|
||||
...mapState({
|
||||
user: 'user.data',
|
||||
currentEvent: 'worldState.data.currentEvent',
|
||||
currentEventList: 'worldState.data.currentEventList',
|
||||
}),
|
||||
questData () {
|
||||
if (!this.group.quest) return {};
|
||||
return quests.quests[this.group.quest.key];
|
||||
},
|
||||
imageURLs () {
|
||||
if (!this.currentEvent || !this.currentEvent.season) {
|
||||
const currentEvent = find(this.currentEventList, event => Boolean(event.season));
|
||||
if (!currentEvent) {
|
||||
return {
|
||||
background: 'url(/static/npc/normal/tavern_background.png)',
|
||||
npc: 'url(/static/npc/normal/tavern_npc.png)',
|
||||
};
|
||||
}
|
||||
return {
|
||||
background: `url(/static/npc/${this.currentEvent.season}/tavern_background.png)`,
|
||||
npc: `url(/static/npc/${this.currentEvent.season}/tavern_npc.png)`,
|
||||
background: `url(/static/npc/${currentEvent.season}/tavern_background.png)`,
|
||||
npc: `url(/static/npc/${currentEvent.season}/tavern_npc.png)`,
|
||||
};
|
||||
},
|
||||
},
|
||||
|
||||
@@ -258,13 +258,22 @@
|
||||
:key="hero._id"
|
||||
>
|
||||
<td>
|
||||
<user-link
|
||||
<div
|
||||
v-if="hasPermission(hero, 'userSupport')"
|
||||
:user="hero"
|
||||
:popover="$t('gamemaster')"
|
||||
popover-trigger="mouseenter"
|
||||
popover-placement="right"
|
||||
/>
|
||||
class="width-content"
|
||||
>
|
||||
<user-link
|
||||
:id="hero._id"
|
||||
:user="hero"
|
||||
/>
|
||||
<b-popover
|
||||
:target="hero._id"
|
||||
triggers="hover focus"
|
||||
placement="right"
|
||||
:prevent-overflow="false"
|
||||
:content="$t('gamemaster')"
|
||||
/>
|
||||
</div>
|
||||
<user-link
|
||||
v-else
|
||||
:user="hero"
|
||||
@@ -302,6 +311,10 @@
|
||||
h4.expand-toggle::after {
|
||||
margin-left: 5px;
|
||||
}
|
||||
|
||||
.width-content {
|
||||
width: fit-content;
|
||||
}
|
||||
</style>
|
||||
|
||||
<script>
|
||||
|
||||
119
website/client/src/components/header/banners/birthdayBanner.vue
Normal file
@@ -0,0 +1,119 @@
|
||||
<template>
|
||||
<base-banner
|
||||
banner-id="birthday-banner"
|
||||
class="birthday-banner"
|
||||
:show="showBirthdayBanner"
|
||||
height="3rem"
|
||||
:can-close="false"
|
||||
>
|
||||
<div
|
||||
slot="content"
|
||||
:aria-label="$t('celebrateBirthday')"
|
||||
class="content d-flex justify-content-around align-items-center ml-auto mr-auto"
|
||||
@click="showBirthdayModal"
|
||||
>
|
||||
<div
|
||||
v-once
|
||||
class="svg-icon svg-gifts left-gift"
|
||||
v-html="icons.giftsBirthday"
|
||||
>
|
||||
</div>
|
||||
<div
|
||||
v-once
|
||||
class="svg-icon svg-ten-birthday"
|
||||
v-html="icons.tenBirthday"
|
||||
>
|
||||
</div>
|
||||
<div
|
||||
v-once
|
||||
class="announce-text"
|
||||
v-html="$t('celebrateBirthday')"
|
||||
>
|
||||
</div>
|
||||
<div
|
||||
v-once
|
||||
class="svg-icon svg-gifts right-gift"
|
||||
v-html="icons.giftsBirthday"
|
||||
>
|
||||
</div>
|
||||
</div>
|
||||
</base-banner>
|
||||
</template>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
@import '~@/assets/scss/colors.scss';
|
||||
|
||||
.announce-text {
|
||||
color: $purple-50;
|
||||
}
|
||||
|
||||
.birthday-banner {
|
||||
width: 100%;
|
||||
min-height: 48px;
|
||||
padding: 8px;
|
||||
background-image: linear-gradient(90deg,
|
||||
rgba(255,190,93,0) 0%,
|
||||
rgba(255,190,93,1) 25%,
|
||||
rgba(255,190,93,1) 75%,
|
||||
rgba(255,190,93,0) 100%),
|
||||
url('~@/assets/images/glitter.png');
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.left-gift {
|
||||
margin: auto;
|
||||
}
|
||||
|
||||
.right-gift {
|
||||
margin: auto auto auto 8px;
|
||||
filter: flipH;
|
||||
transform: scaleX(-1);
|
||||
}
|
||||
|
||||
.svg-gifts {
|
||||
width: 85px;
|
||||
}
|
||||
|
||||
.svg-ten-birthday {
|
||||
width: 192.5px;
|
||||
margin-left: 8px;
|
||||
margin-right: 8.5px;
|
||||
}
|
||||
</style>
|
||||
|
||||
<script>
|
||||
import find from 'lodash/find';
|
||||
import { mapState } from '@/libs/store';
|
||||
import BaseBanner from './base';
|
||||
|
||||
import giftsBirthday from '@/assets/svg/gifts-birthday.svg';
|
||||
import tenBirthday from '@/assets/svg/10th-birthday-linear.svg';
|
||||
|
||||
export default {
|
||||
components: {
|
||||
BaseBanner,
|
||||
},
|
||||
data () {
|
||||
return {
|
||||
icons: Object.freeze({
|
||||
giftsBirthday,
|
||||
tenBirthday,
|
||||
}),
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
...mapState({
|
||||
currentEventList: 'worldState.data.currentEventList',
|
||||
}),
|
||||
showBirthdayBanner () {
|
||||
return Boolean(find(this.currentEventList, event => Boolean(event.event === 'birthday10')));
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
showBirthdayModal () {
|
||||
this.$root.$emit('bv::show::modal', 'birthday-modal');
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
</script>
|
||||
@@ -51,20 +51,20 @@
|
||||
</div>
|
||||
<div
|
||||
v-else
|
||||
class="no-party d-none d-md-flex justify-content-center text-center mr-4"
|
||||
class="no-party d-none d-md-flex justify-content-center text-center mr-4"
|
||||
>
|
||||
<div class="align-self-center">
|
||||
<h3>{{ $t('battleWithFriends') }}</h3>
|
||||
<h3>{{ user.party._id ? $t('questWithOthers') : $t('battleWithFriends') }}</h3>
|
||||
<span
|
||||
class="small-text"
|
||||
v-html="$t('inviteFriendsParty')"
|
||||
v-html="user.party._id ? $t('inviteFriendsParty') : $t('startPartyDetail')"
|
||||
></span>
|
||||
<br>
|
||||
<button
|
||||
class="btn btn-primary"
|
||||
@click="createOrInviteParty()"
|
||||
>
|
||||
{{ user.party._id ? $t('inviteFriends') : $t('startAParty') }}
|
||||
{{ user.party._id ? $t('findPartyMembers') : $t('getStarted') }}
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
@@ -122,6 +122,7 @@
|
||||
|
||||
<script>
|
||||
import orderBy from 'lodash/orderBy';
|
||||
import * as Analytics from '@/libs/analytics';
|
||||
import { mapGetters, mapActions } from '@/libs/store';
|
||||
import MemberDetails from '../memberDetails';
|
||||
import createPartyModal from '../groups/createPartyModal';
|
||||
@@ -232,10 +233,24 @@ export default {
|
||||
this.expandedMember = memberId;
|
||||
}
|
||||
},
|
||||
createOrInviteParty () {
|
||||
async createOrInviteParty () {
|
||||
if (this.user.party._id) {
|
||||
this.$root.$emit('inviteModal::inviteToGroup', this.user.party);
|
||||
await Analytics.track({
|
||||
eventName: 'Header Party CTA',
|
||||
eventAction: 'Header Party CTA',
|
||||
eventCategory: 'behavior',
|
||||
hitType: 'event',
|
||||
state: 'Find Party Members',
|
||||
});
|
||||
this.$router.push('/looking-for-party');
|
||||
} else {
|
||||
await Analytics.track({
|
||||
eventName: 'Header Party CTA',
|
||||
eventAction: 'Header Party CTA',
|
||||
eventCategory: 'behavior',
|
||||
hitType: 'event',
|
||||
state: 'Get Started',
|
||||
});
|
||||
this.$root.$emit('bv::show::modal', 'create-party-modal');
|
||||
}
|
||||
},
|
||||
|
||||
@@ -148,7 +148,7 @@
|
||||
</div>
|
||||
</li>
|
||||
<b-nav-item
|
||||
v-if="user.party._id"
|
||||
v-if="user.party._id && user._id !== partyLeaderId"
|
||||
class="topbar-item"
|
||||
:class="{'active': $route.path.startsWith('/party')}"
|
||||
tag="li"
|
||||
@@ -156,6 +156,36 @@
|
||||
>
|
||||
{{ $t('party') }}
|
||||
</b-nav-item>
|
||||
<li
|
||||
v-if="user.party._id && user._id === partyLeaderId"
|
||||
class="topbar-item droppable"
|
||||
:class="{'active': $route.path.startsWith('/party')}"
|
||||
>
|
||||
<div
|
||||
class="chevron rotate"
|
||||
@click="dropdownMobile($event)"
|
||||
>
|
||||
<div
|
||||
v-once
|
||||
class="chevron-icon-down"
|
||||
v-html="icons.chevronDown"
|
||||
></div>
|
||||
</div>
|
||||
<router-link
|
||||
class="nav-link"
|
||||
:to="{name: 'party'}"
|
||||
>
|
||||
{{ $t('party') }}
|
||||
</router-link>
|
||||
<div class="topbar-dropdown">
|
||||
<router-link
|
||||
class="topbar-dropdown-item dropdown-item"
|
||||
:to="{name: 'lookingForParty'}"
|
||||
>
|
||||
{{ $t('lookingForPartyTitle') }}
|
||||
</router-link>
|
||||
</div>
|
||||
</li>
|
||||
<b-nav-item
|
||||
v-if="!user.party._id"
|
||||
class="topbar-item"
|
||||
@@ -768,6 +798,7 @@ export default {
|
||||
return {
|
||||
isUserDropdownOpen: false,
|
||||
menuIsOpen: false,
|
||||
partyLeaderId: null,
|
||||
icons: Object.freeze({
|
||||
gem: gemIcon,
|
||||
gold: goldIcon,
|
||||
@@ -796,8 +827,9 @@ export default {
|
||||
};
|
||||
},
|
||||
},
|
||||
mounted () {
|
||||
this.getUserGroupPlans();
|
||||
async mounted () {
|
||||
await this.getUserGroupPlans();
|
||||
await this.getUserParty();
|
||||
Array.from(document.getElementById('menu_collapse').getElementsByTagName('a')).forEach(link => {
|
||||
link.addEventListener('click', this.closeMenu);
|
||||
});
|
||||
@@ -805,6 +837,9 @@ export default {
|
||||
link.addEventListener('mouseenter', this.dropdownDesktop);
|
||||
link.addEventListener('mouseleave', this.dropdownDesktop);
|
||||
});
|
||||
this.$root.$on('update-party', () => {
|
||||
this.getUserParty();
|
||||
});
|
||||
},
|
||||
methods: {
|
||||
modForm () {
|
||||
@@ -816,6 +851,12 @@ export default {
|
||||
async getUserGroupPlans () {
|
||||
await this.$store.dispatch('guilds:getGroupPlans');
|
||||
},
|
||||
async getUserParty () {
|
||||
if (this.user.party._id) {
|
||||
await this.$store.dispatch('party:getParty');
|
||||
this.partyLeaderId = this.$store.state.party.data.leader._id;
|
||||
}
|
||||
},
|
||||
openPartyModal () {
|
||||
this.$root.$emit('bv::show::modal', 'create-party-modal');
|
||||
},
|
||||
|
||||
@@ -0,0 +1,58 @@
|
||||
<template>
|
||||
<base-notification
|
||||
:can-remove="canRemove"
|
||||
:has-icon="true"
|
||||
:notification="notification"
|
||||
:read-after-click="true"
|
||||
@click="action"
|
||||
>
|
||||
<div
|
||||
slot="content"
|
||||
>
|
||||
<strong> {{ notification.data.title }} </strong>
|
||||
<span> {{ notification.data.text }} </span>
|
||||
</div>
|
||||
<div
|
||||
slot="icon"
|
||||
class="mt-3"
|
||||
:class="notification.data.icon"
|
||||
></div>
|
||||
</base-notification>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import BaseNotification from './base';
|
||||
|
||||
export default {
|
||||
components: {
|
||||
BaseNotification,
|
||||
},
|
||||
props: {
|
||||
notification: {
|
||||
type: Object,
|
||||
default (data) {
|
||||
return data;
|
||||
},
|
||||
},
|
||||
canRemove: {
|
||||
type: Boolean,
|
||||
default: true,
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
action () {
|
||||
if (!this.notification || !this.notification.data) {
|
||||
return;
|
||||
}
|
||||
if (this.notification.data.destination === 'backgrounds') {
|
||||
this.$store.state.avatarEditorOptions.editingUser = true;
|
||||
this.$store.state.avatarEditorOptions.startingPage = 'backgrounds';
|
||||
this.$store.state.avatarEditorOptions.subpage = '2023';
|
||||
this.$root.$emit('bv::show::modal', 'avatar-modal');
|
||||
} else {
|
||||
this.$router.push({ name: this.notification.data.destination || 'items' });
|
||||
}
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
@@ -5,7 +5,14 @@
|
||||
:notification="notification"
|
||||
>
|
||||
<div slot="content">
|
||||
<div v-html="$t('invitedToParty', {party: notification.data.name})"></div>
|
||||
<div
|
||||
v-html="$t('invitedToPartyBy', {
|
||||
userId: notification.data.inviter,
|
||||
userName: invitingUser.auth ? invitingUser.auth.local.username : null,
|
||||
party: notification.data.name,
|
||||
})"
|
||||
>
|
||||
</div>
|
||||
<div class="notifications-buttons">
|
||||
<div
|
||||
class="btn btn-small btn-success"
|
||||
@@ -27,15 +34,38 @@
|
||||
<script>
|
||||
import BaseNotification from './base';
|
||||
import { mapState } from '@/libs/store';
|
||||
import sync from '@/mixins/sync';
|
||||
|
||||
export default {
|
||||
components: {
|
||||
BaseNotification,
|
||||
},
|
||||
props: ['notification', 'canRemove'],
|
||||
mixins: [sync],
|
||||
props: {
|
||||
notification: {
|
||||
type: Object,
|
||||
default (data) {
|
||||
return data;
|
||||
},
|
||||
},
|
||||
canRemove: {
|
||||
type: Boolean,
|
||||
default: true,
|
||||
},
|
||||
},
|
||||
data () {
|
||||
return {
|
||||
invitingUser: {},
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
...mapState({ user: 'user.data' }),
|
||||
},
|
||||
async mounted () {
|
||||
this.invitingUser = await this.$store.dispatch('members:fetchMember', {
|
||||
memberId: this.notification.data.inviter,
|
||||
});
|
||||
},
|
||||
methods: {
|
||||
async accept () {
|
||||
const group = this.notification.data;
|
||||
@@ -45,6 +75,7 @@ export default {
|
||||
}
|
||||
|
||||
await this.$store.dispatch('guilds:join', { groupId: group.id, type: 'party' });
|
||||
this.sync();
|
||||
this.$router.push('/party');
|
||||
},
|
||||
reject () {
|
||||
|
||||
@@ -39,7 +39,7 @@
|
||||
{{ $t('notifications') }}
|
||||
</h4>
|
||||
<a
|
||||
class="small-link standard-link"
|
||||
class="small-link"
|
||||
:disabled="notificationsCount === 0"
|
||||
@click="dismissAll"
|
||||
>{{ $t('dismissAll') }}</a>
|
||||
@@ -123,23 +123,24 @@ import successImage from '@/assets/svg/success.svg';
|
||||
import starBadge from '@/assets/svg/star-badge.svg';
|
||||
|
||||
// Notifications
|
||||
import NEW_STUFF from './notifications/newStuff';
|
||||
import GROUP_TASK_NEEDS_WORK from './notifications/groupTaskNeedsWork';
|
||||
import GUILD_INVITATION from './notifications/guildInvitation';
|
||||
import PARTY_INVITATION from './notifications/partyInvitation';
|
||||
import CARD_RECEIVED from './notifications/cardReceived';
|
||||
import CHALLENGE_INVITATION from './notifications/challengeInvitation';
|
||||
import QUEST_INVITATION from './notifications/questInvitation';
|
||||
import GIFT_ONE_GET_ONE from './notifications/g1g1';
|
||||
import GROUP_TASK_ASSIGNED from './notifications/groupTaskAssigned';
|
||||
import GROUP_TASK_CLAIMED from './notifications/groupTaskClaimed';
|
||||
import UNALLOCATED_STATS_POINTS from './notifications/unallocatedStatsPoints';
|
||||
import NEW_MYSTERY_ITEMS from './notifications/newMysteryItems';
|
||||
import CARD_RECEIVED from './notifications/cardReceived';
|
||||
import NEW_INBOX_MESSAGE from './notifications/newPrivateMessage';
|
||||
import GROUP_TASK_NEEDS_WORK from './notifications/groupTaskNeedsWork';
|
||||
import GUILD_INVITATION from './notifications/guildInvitation';
|
||||
import ITEM_RECEIVED from './notifications/itemReceived';
|
||||
import NEW_CHAT_MESSAGE from './notifications/newChatMessage';
|
||||
import WORLD_BOSS from './notifications/worldBoss';
|
||||
import VERIFY_USERNAME from './notifications/verifyUsername';
|
||||
import NEW_INBOX_MESSAGE from './notifications/newPrivateMessage';
|
||||
import NEW_MYSTERY_ITEMS from './notifications/newMysteryItems';
|
||||
import NEW_STUFF from './notifications/newStuff';
|
||||
import ONBOARDING_COMPLETE from './notifications/onboardingComplete';
|
||||
import GIFT_ONE_GET_ONE from './notifications/g1g1';
|
||||
import PARTY_INVITATION from './notifications/partyInvitation';
|
||||
import QUEST_INVITATION from './notifications/questInvitation';
|
||||
import UNALLOCATED_STATS_POINTS from './notifications/unallocatedStatsPoints';
|
||||
import VERIFY_USERNAME from './notifications/verifyUsername';
|
||||
import WORLD_BOSS from './notifications/worldBoss';
|
||||
import OnboardingGuide from './onboardingGuide';
|
||||
|
||||
export default {
|
||||
@@ -147,24 +148,25 @@ export default {
|
||||
MenuDropdown,
|
||||
MessageCount,
|
||||
// One component for each type
|
||||
NEW_STUFF,
|
||||
GROUP_TASK_NEEDS_WORK,
|
||||
GUILD_INVITATION,
|
||||
PARTY_INVITATION,
|
||||
CARD_RECEIVED,
|
||||
CHALLENGE_INVITATION,
|
||||
QUEST_INVITATION,
|
||||
GIFT_ONE_GET_ONE,
|
||||
GROUP_TASK_ASSIGNED,
|
||||
GROUP_TASK_CLAIMED,
|
||||
UNALLOCATED_STATS_POINTS,
|
||||
NEW_MYSTERY_ITEMS,
|
||||
CARD_RECEIVED,
|
||||
NEW_INBOX_MESSAGE,
|
||||
GROUP_TASK_NEEDS_WORK,
|
||||
GUILD_INVITATION,
|
||||
ITEM_RECEIVED,
|
||||
NEW_CHAT_MESSAGE,
|
||||
WorldBoss: WORLD_BOSS,
|
||||
VERIFY_USERNAME,
|
||||
OnboardingGuide,
|
||||
NEW_INBOX_MESSAGE,
|
||||
NEW_MYSTERY_ITEMS,
|
||||
NEW_STUFF,
|
||||
ONBOARDING_COMPLETE,
|
||||
GIFT_ONE_GET_ONE,
|
||||
PARTY_INVITATION,
|
||||
QUEST_INVITATION,
|
||||
UNALLOCATED_STATS_POINTS,
|
||||
VERIFY_USERNAME,
|
||||
WorldBoss: WORLD_BOSS,
|
||||
OnboardingGuide,
|
||||
},
|
||||
data () {
|
||||
return {
|
||||
@@ -185,6 +187,7 @@ export default {
|
||||
// NOTE: Those not listed here won't be shown in the notification panel!
|
||||
handledNotifications: [
|
||||
'NEW_STUFF',
|
||||
'ITEM_RECEIVED',
|
||||
'GIFT_ONE_GET_ONE',
|
||||
'GROUP_TASK_NEEDS_WORK',
|
||||
'GUILD_INVITATION',
|
||||
|
||||
@@ -40,7 +40,7 @@
|
||||
>{{ $t('editAvatar') }}</a>
|
||||
<a
|
||||
class="topbar-dropdown-item dropdown-item dropdown-separated"
|
||||
@click="showAvatar('backgrounds', '2022')"
|
||||
@click="showAvatar('backgrounds', '2023')"
|
||||
>{{ $t('backgrounds') }}</a>
|
||||
<a
|
||||
class="topbar-dropdown-item dropdown-item"
|
||||
|
||||
@@ -879,7 +879,7 @@ export default {
|
||||
return;
|
||||
}
|
||||
|
||||
if (this.user.preferences.suppressModals.raisePet) {
|
||||
if (this.user.preferences.suppressModals.hatchPet) {
|
||||
this.hatchPet(pet);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -171,8 +171,9 @@ export default {
|
||||
getPetItemClass () {
|
||||
if (this.isOwned() && some(
|
||||
this.currentEventList,
|
||||
event => moment().isBetween(event.start, event.end) && event.aprilFools && event.aprilFools === 'virtual',
|
||||
event => moment().isBetween(event.start, event.end) && event.aprilFools && event.aprilFools === 'teaShop',
|
||||
)) {
|
||||
if (this.isSpecial()) return `Pet ${this.foolPet(this.item.key)}`;
|
||||
const petString = `${this.item.eggKey}-${this.item.key}`;
|
||||
return `Pet ${this.foolPet(petString)}`;
|
||||
}
|
||||
|
||||
@@ -139,6 +139,8 @@
|
||||
import axios from 'axios';
|
||||
import moment from 'moment';
|
||||
|
||||
import externalLinks from '../../mixins/externalLinks';
|
||||
|
||||
import renderWithMentions from '@/libs/renderWithMentions';
|
||||
import { mapState } from '@/libs/store';
|
||||
import userLink from '../userLink';
|
||||
@@ -150,6 +152,7 @@ export default {
|
||||
components: {
|
||||
userLink,
|
||||
},
|
||||
mixins: [externalLinks],
|
||||
filters: {
|
||||
timeAgo (value) {
|
||||
return moment(value).fromNow();
|
||||
@@ -179,6 +182,10 @@ export default {
|
||||
},
|
||||
mounted () {
|
||||
this.$emit('message-card-mounted');
|
||||
this.handleExternalLinks();
|
||||
},
|
||||
updated () {
|
||||
this.handleExternalLinks();
|
||||
},
|
||||
methods: {
|
||||
report () {
|
||||
|
||||
877
website/client/src/components/news/birthdayModal.vue
Normal file
@@ -0,0 +1,877 @@
|
||||
<template>
|
||||
<b-modal
|
||||
id="birthday-modal"
|
||||
:hide-header="true"
|
||||
:hide-footer="true"
|
||||
>
|
||||
<div class="modal-content">
|
||||
<div
|
||||
class="modal-close"
|
||||
@click="close()"
|
||||
>
|
||||
<div
|
||||
class="svg-icon svg-close"
|
||||
v-html="icons.close"
|
||||
>
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
class="svg-confetti svg-icon"
|
||||
v-html="icons.confetti"
|
||||
>
|
||||
</div>
|
||||
<div>
|
||||
<img
|
||||
src="~@/assets/images/10-birthday.png"
|
||||
class="ten-birthday"
|
||||
>
|
||||
</div>
|
||||
<div class="limited-wrapper">
|
||||
<div
|
||||
class="svg-gifts svg-icon"
|
||||
v-html="icons.gifts"
|
||||
>
|
||||
</div>
|
||||
<div class="limited-event">
|
||||
{{ $t('limitedEvent') }}
|
||||
</div>
|
||||
<div class="dates">
|
||||
{{ $t('anniversaryLimitedDates') }}
|
||||
</div>
|
||||
<div
|
||||
class="svg-gifts-flip svg-icon"
|
||||
v-html="icons.gifts"
|
||||
>
|
||||
</div>
|
||||
</div>
|
||||
<div class="celebrate d-flex justify-content-center">
|
||||
{{ $t('celebrateAnniversary') }}
|
||||
</div>
|
||||
<h2 class="d-flex justify-content-center">
|
||||
<span
|
||||
class="left-divider"
|
||||
v-html="icons.divider"
|
||||
></span>
|
||||
<span
|
||||
class="svg-cross"
|
||||
v-html="icons.cross"
|
||||
>
|
||||
</span>
|
||||
{{ $t('jubilantGryphatricePromo') }}
|
||||
<span
|
||||
class="svg-cross"
|
||||
v-html="icons.cross"
|
||||
>
|
||||
</span>
|
||||
<span
|
||||
class="right-divider"
|
||||
></span>
|
||||
</h2>
|
||||
<!-- gryphatrice info -->
|
||||
<div class="d-flex">
|
||||
<div class="jubilant-gryphatrice d-flex mr-auto">
|
||||
<img
|
||||
src="https://habitica-assets.s3.amazonaws.com/mobileApp/images/Pet-Gryphatrice-Jubilant-Large.gif"
|
||||
width="156px"
|
||||
height="144px"
|
||||
alt="a pink, purple, and green gryphatrice pet winks at you adorably"
|
||||
>
|
||||
</div>
|
||||
<div class="align-items-center">
|
||||
<div class="limited-edition mr-auto">
|
||||
{{ $t('limitedEdition') }}
|
||||
</div>
|
||||
<div class="gryphatrice-text">
|
||||
{{ $t('anniversaryGryphatriceText') }}
|
||||
</div>
|
||||
<div
|
||||
class="gryphatrice-price"
|
||||
v-html="$t('anniversaryGryphatricePrice')"
|
||||
>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<!-- beginning of payments -->
|
||||
<!-- buy with money OR gems -->
|
||||
<div
|
||||
v-if="!ownGryphatrice && !gryphBought"
|
||||
>
|
||||
<div
|
||||
v-if="selectedPage !== 'payment-buttons'"
|
||||
id="initial-buttons"
|
||||
class="d-flex justify-content-center"
|
||||
>
|
||||
<button
|
||||
class="btn btn-secondary buy-now-left"
|
||||
:class="{active: selectedPage === 'payment-buttons'}"
|
||||
@click="selectedPage = 'payment-buttons'"
|
||||
>
|
||||
{{ $t('buyNowMoneyButton') }}
|
||||
</button>
|
||||
<button
|
||||
class="btn btn-secondary buy-now-right"
|
||||
@click="buyGryphatriceGems()"
|
||||
>
|
||||
{{ $t('buyNowGemsButton') }}
|
||||
</button>
|
||||
</div>
|
||||
<!-- buy with money -->
|
||||
<div
|
||||
v-else-if="selectedPage === 'payment-buttons'"
|
||||
id="payment-buttons"
|
||||
class="d-flex flex-column"
|
||||
>
|
||||
<button
|
||||
class="btn btn-secondary d-flex stripe"
|
||||
@click="redirectToStripe({ sku: 'price_0MPZ6iZCD0RifGXlLah2furv' })"
|
||||
>
|
||||
<span
|
||||
class="svg-stripe"
|
||||
v-html="icons.stripe"
|
||||
>
|
||||
</span>
|
||||
</button>
|
||||
<button
|
||||
class="btn btn-secondary d-flex paypal"
|
||||
@click="openPaypal({
|
||||
url: paypalCheckoutLink, type: 'sku', sku: 'Pet-Gryphatrice-Jubilant'
|
||||
})"
|
||||
>
|
||||
<span
|
||||
class="svg-paypal"
|
||||
v-html="icons.paypal"
|
||||
>
|
||||
</span>
|
||||
</button>
|
||||
<amazon-button
|
||||
:disabled="disabled"
|
||||
:amazon-data="amazonData"
|
||||
class="btn btn-secondary d-flex amazon"
|
||||
v-html="icons.amazon"
|
||||
/>
|
||||
<div
|
||||
class="pay-with-gems"
|
||||
@click="selectedPage = 'initial-buttons'"
|
||||
>
|
||||
{{ $t('wantToPayWithGemsText') }}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<!-- Own the gryphatrice -->
|
||||
<div
|
||||
v-else
|
||||
class="d-flex"
|
||||
>
|
||||
<button
|
||||
class="own-gryphatrice-button"
|
||||
@click="closeAndRedirect('/inventory/stable')"
|
||||
v-html="$t('ownJubilantGryphatrice')"
|
||||
>
|
||||
</button>
|
||||
</div>
|
||||
<!-- end of payments -->
|
||||
<h2 class="d-flex justify-content-center">
|
||||
<span
|
||||
class="left-divider"
|
||||
v-html="icons.divider"
|
||||
></span>
|
||||
<span
|
||||
class="svg-cross"
|
||||
v-html="icons.cross"
|
||||
>
|
||||
</span>
|
||||
{{ $t('plentyOfPotions') }}
|
||||
<span
|
||||
class="svg-cross"
|
||||
v-html="icons.cross"
|
||||
>
|
||||
</span>
|
||||
<span
|
||||
class="right-divider"
|
||||
></span>
|
||||
</h2>
|
||||
<div class="plenty-of-potions d-flex">
|
||||
{{ $t('plentyOfPotionsText') }}
|
||||
</div>
|
||||
<div class="potions">
|
||||
<div class="pot-1">
|
||||
<img src="https://habitica-assets.s3.amazonaws.com/mobileApp/images/Pet_HatchingPotion_Porcelain.png">
|
||||
</div>
|
||||
<div class="pot-2">
|
||||
<img src="https://habitica-assets.s3.amazonaws.com/mobileApp/images/Pet_HatchingPotion_Vampire.png">
|
||||
</div>
|
||||
<div class="pot-3">
|
||||
<img src="https://habitica-assets.s3.amazonaws.com/mobileApp/images/Pet_HatchingPotion_Aquatic.png">
|
||||
</div>
|
||||
<div class="pot-4">
|
||||
<img src="https://habitica-assets.s3.amazonaws.com/mobileApp/images/Pet_HatchingPotion_StainedGlass.png">
|
||||
</div>
|
||||
<div class="pot-5">
|
||||
<img src="https://habitica-assets.s3.amazonaws.com/mobileApp/images/Pet_HatchingPotion_Celestial.png">
|
||||
</div>
|
||||
<div class="pot-6">
|
||||
<img src="https://habitica-assets.s3.amazonaws.com/mobileApp/images/Pet_HatchingPotion_Glow.png">
|
||||
</div>
|
||||
<div class="pot-7">
|
||||
<img src="https://habitica-assets.s3.amazonaws.com/mobileApp/images/Pet_HatchingPotion_AutumnLeaf.png">
|
||||
</div>
|
||||
<div class="pot-8">
|
||||
<img src="https://habitica-assets.s3.amazonaws.com/mobileApp/images/Pet_HatchingPotion_SandSculpture.png">
|
||||
</div>
|
||||
<div class="pot-9">
|
||||
<img src="https://habitica-assets.s3.amazonaws.com/mobileApp/images/Pet_HatchingPotion_Peppermint.png">
|
||||
</div>
|
||||
<div class="pot-10">
|
||||
<img src="https://habitica-assets.s3.amazonaws.com/mobileApp/images/Pet_HatchingPotion_Shimmer.png">
|
||||
</div>
|
||||
</div>
|
||||
<button
|
||||
class="btn btn-secondary d-flex justify-content-center visit-the-market"
|
||||
@click="closeAndRedirect('/shops/market')"
|
||||
>
|
||||
{{ $t('visitTheMarketButton') }}
|
||||
</button>
|
||||
<h2 class="d-flex justify-content-center">
|
||||
<span
|
||||
class="left-divider"
|
||||
v-html="icons.divider"
|
||||
></span>
|
||||
<span
|
||||
class="svg-cross"
|
||||
v-html="icons.cross"
|
||||
>
|
||||
</span>
|
||||
{{ $t('fourForFree') }}
|
||||
<span
|
||||
class="svg-cross"
|
||||
v-html="icons.cross"
|
||||
>
|
||||
</span>
|
||||
<span
|
||||
class="right-divider"
|
||||
></span>
|
||||
</h2>
|
||||
<div class="four-for-free">
|
||||
{{ $t('fourForFreeText') }}
|
||||
</div>
|
||||
<div class="four-grid d-flex justify-content-center">
|
||||
<div class="day-one-a">
|
||||
<div class="day-text">
|
||||
{{ $t('dayOne') }}
|
||||
</div>
|
||||
<div class="gift d-flex justify-content-center align-items-middle">
|
||||
<img
|
||||
src="~@/assets/images/robes.webp"
|
||||
class="m-auto"
|
||||
width="40px"
|
||||
height="66px"
|
||||
>
|
||||
</div>
|
||||
<div class="description">
|
||||
{{ $t('partyRobes') }}
|
||||
</div>
|
||||
</div>
|
||||
<div class="day-one-b">
|
||||
<div class="day-text">
|
||||
{{ $t('dayOne') }}
|
||||
</div>
|
||||
<div class="gift d-flex justify-content-center align-items-middle">
|
||||
<div
|
||||
class="svg-gem svg-icon m-auto"
|
||||
v-html="icons.birthdayGems"
|
||||
>
|
||||
</div>
|
||||
</div>
|
||||
<div class="description">
|
||||
{{ $t('twentyGems') }}
|
||||
</div>
|
||||
</div>
|
||||
<div class="day-five">
|
||||
<div class="day-text">
|
||||
{{ $t('dayFive') }}
|
||||
</div>
|
||||
<div class="gift d-flex justify-content-center align-items-middle">
|
||||
<img
|
||||
src="~@/assets/images/habitica-hero-goober.webp"
|
||||
class="m-auto"
|
||||
><!-- Birthday Set -->
|
||||
</div>
|
||||
<div class="description">
|
||||
{{ $t('birthdaySet') }}
|
||||
</div>
|
||||
</div>
|
||||
<div class="day-ten">
|
||||
<div class="day-text">
|
||||
{{ $t('dayTen') }}
|
||||
</div>
|
||||
<div class="gift d-flex justify-content-center align-items-middle">
|
||||
<div
|
||||
class="svg-background svg-icon m-auto"
|
||||
v-html="icons.birthdayBackground"
|
||||
>
|
||||
</div>
|
||||
</div>
|
||||
<div class="description">
|
||||
{{ $t('background') }}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="modal-bottom">
|
||||
<div class="limitations d-flex justify-content-center">
|
||||
{{ $t('limitations') }}
|
||||
</div>
|
||||
<div class="fine-print">
|
||||
{{ $t('anniversaryLimitations') }}
|
||||
</div>
|
||||
</div>
|
||||
</b-modal>
|
||||
</template>
|
||||
|
||||
<style lang="scss">
|
||||
#birthday-modal {
|
||||
.modal-body {
|
||||
padding: 0px;
|
||||
border: 0px;
|
||||
}
|
||||
.modal-content {
|
||||
border-radius: 14px;
|
||||
border: 0px;
|
||||
}
|
||||
.modal-footer {
|
||||
border-radius: 14px;
|
||||
border: 0px;
|
||||
}
|
||||
.amazon {
|
||||
margin-bottom: 16px;
|
||||
|
||||
svg {
|
||||
width: 84px;
|
||||
position: absolute;
|
||||
}
|
||||
|
||||
.amazonpay-button-inner-image {
|
||||
opacity: 0;
|
||||
width: 100%;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
|
||||
<style scoped lang="scss">
|
||||
@import '~@/assets/scss/colors.scss';
|
||||
@import '~@/assets/scss/mixins.scss';
|
||||
|
||||
#birthday-modal {
|
||||
h2 {
|
||||
font-size: 1.25rem;
|
||||
font-weight: bold;
|
||||
line-height: 1.4;
|
||||
color: $white;
|
||||
column-gap: 0.5rem;
|
||||
display: flex;
|
||||
flex-wrap: nowrap;
|
||||
justify-content: space-between;
|
||||
align-content: center;
|
||||
}
|
||||
|
||||
.modal-body{
|
||||
box-shadow: 0 14px 28px 0 rgba(26, 24, 29, 0.24), 0 10px 10px 0 rgba(26, 24, 29, 0.28);
|
||||
}
|
||||
|
||||
.modal-content {
|
||||
width: 566px;
|
||||
padding: 32px 24px 24px;
|
||||
background: linear-gradient(158deg,#6133b4,#4f2a93);
|
||||
border-top-left-radius: 12px;
|
||||
border-top-right-radius: 12px;
|
||||
border-bottom-left-radius: 0px;
|
||||
border-bottom-right-radius: 0px;
|
||||
}
|
||||
|
||||
.modal-bottom {
|
||||
width: 566px;
|
||||
background-color: $purple-50;
|
||||
color: $purple-500;
|
||||
line-height: 1.33;
|
||||
border-top: 0px;
|
||||
padding: 16px 40px 28px 40px;
|
||||
border-bottom-left-radius: 12px;
|
||||
border-bottom-right-radius: 12px;
|
||||
}
|
||||
.limitations {
|
||||
color: $white;
|
||||
font-weight: bold;
|
||||
line-height: 1.71;
|
||||
margin-top: 8px;
|
||||
justify-content: center;
|
||||
}
|
||||
.fine-print {
|
||||
font-size: 0.75rem;
|
||||
color: $purple-500;
|
||||
line-height: 1.33;
|
||||
margin-top: 8px;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.ten-birthday {
|
||||
position: relative;
|
||||
width: 268px;
|
||||
height: 244px;
|
||||
margin: 0 125px 16px;
|
||||
}
|
||||
|
||||
.limited-event {
|
||||
font-size: 0.75rem;
|
||||
font-weight: bold;
|
||||
text-transform: uppercase;
|
||||
text-align: center;
|
||||
justify-content: center;
|
||||
letter-spacing: 2.4px;
|
||||
margin-top: -8px;
|
||||
color: $yellow-50;
|
||||
}
|
||||
|
||||
.dates {
|
||||
font-size: 0.875rem;
|
||||
font-weight: bold;
|
||||
line-height: 1.71;
|
||||
text-align: center;
|
||||
justify-content: center;
|
||||
color: $white;
|
||||
}
|
||||
|
||||
.celebrate {
|
||||
font-size: 1.25rem;
|
||||
font-weight: bold;
|
||||
line-height: 1.4;
|
||||
margin: 16px 16px 24px 16px;
|
||||
text-align: center;
|
||||
color: $yellow-50;
|
||||
}
|
||||
|
||||
.jubilant-gryphatrice {
|
||||
height: 176px;
|
||||
width: 204px;
|
||||
border-radius: 12px;
|
||||
background-color: $purple-50;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
margin-right: 24px;
|
||||
margin-left: 4px;
|
||||
color: $white;
|
||||
}
|
||||
|
||||
.limited-wrapper {
|
||||
margin-top: -36px;
|
||||
margin-bottom: -36px;
|
||||
}
|
||||
|
||||
.limited-edition, .gryphatrice-text, .gryphatrice-price {
|
||||
max-width: 274px;
|
||||
}
|
||||
|
||||
.limited-edition {
|
||||
font-size: 0.75rem;
|
||||
font-weight: bold;
|
||||
text-transform: uppercase;
|
||||
line-height:1.33;
|
||||
letter-spacing:2.4px;
|
||||
padding-top: 18px;
|
||||
margin-left: 24px;
|
||||
margin-bottom: 8px;
|
||||
color: $yellow-50;
|
||||
}
|
||||
|
||||
.gryphatrice-text, .gryphatrice-price {
|
||||
font-size: 0.875rem;
|
||||
line-height: 1.71;
|
||||
margin-left: 24px;
|
||||
margin-right: 4px;
|
||||
color: $white;
|
||||
}
|
||||
|
||||
.gryphatrice-price {
|
||||
padding-top: 16px;
|
||||
margin-left: 24px;
|
||||
}
|
||||
|
||||
.buy-now-left {
|
||||
width: 243px;
|
||||
margin: 24px 8px 24px 0px;
|
||||
border-radius: 4px;
|
||||
box-shadow: 0 1px 3px 0 rgba(26, 24, 29, 0.12), 0 1px 2px 0 rgba(26, 24, 29, 0.24);
|
||||
}
|
||||
|
||||
.buy-now-right {
|
||||
width: 243px;
|
||||
margin: 24px 0px 24px 8px;
|
||||
border-radius: 4px;
|
||||
box-shadow: 0 1px 3px 0 rgba(26, 24, 29, 0.12), 0 1px 2px 0 rgba(26, 24, 29, 0.24);
|
||||
}
|
||||
|
||||
.stripe {
|
||||
margin-top: 24px;
|
||||
margin-bottom: 8px;
|
||||
padding-bottom: 10px;
|
||||
}
|
||||
|
||||
.paypal {
|
||||
margin-bottom: 8px;
|
||||
padding-bottom: 10px;
|
||||
}
|
||||
|
||||
.stripe, .paypal, .amazon {
|
||||
width: 506px;
|
||||
height: 32px;
|
||||
margin-left: 4px;
|
||||
margin-right: 4px;
|
||||
border-radius: 4px;
|
||||
flex-direction: row;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.pay-with-gems {
|
||||
color: $white;
|
||||
text-align: center;
|
||||
margin-bottom: 24px;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.pay-with-gems:hover {
|
||||
text-decoration: underline;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.own-gryphatrice-button {
|
||||
width: 506px;
|
||||
height: 32px;
|
||||
margin: 24px 4px;
|
||||
border-radius: 4px;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
border: $green-100;
|
||||
background-color: $green-100;
|
||||
color: $green-1;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.plenty-of-potions {
|
||||
font-size: 0.875rem;
|
||||
line-height: 1.71;
|
||||
margin: 0 8px 24px;
|
||||
text-align: center;
|
||||
color: $white;
|
||||
}
|
||||
|
||||
.potions {
|
||||
display: grid;
|
||||
grid-template-columns: 5;
|
||||
grid-template-rows: 2;
|
||||
gap: 24px 24px;
|
||||
justify-content: center;
|
||||
|
||||
.pot-1, .pot-2, .pot-3, .pot-4, .pot-5,
|
||||
.pot-6, .pot-7, .pot-8, .pot-9, .pot-10 {
|
||||
height: 68px;
|
||||
width: 68px;
|
||||
border-radius: 8px;
|
||||
background-color: $purple-50;
|
||||
}
|
||||
|
||||
.pot-1 {
|
||||
grid-column: 1 / 1;
|
||||
grid-row: 1 / 2;
|
||||
}
|
||||
.pot-2 {
|
||||
grid-column: 2 / 2;
|
||||
grid-row: 1 / 2;
|
||||
}
|
||||
.pot-3 {
|
||||
grid-column: 3 / 3;
|
||||
grid-row: 1 / 2;
|
||||
}
|
||||
.pot-4 {
|
||||
grid-column: 4 / 4;
|
||||
grid-row: 1 / 2;
|
||||
}
|
||||
.pot-5 {
|
||||
grid-column: 5 / 5;
|
||||
grid-row: 1 / 2;
|
||||
}
|
||||
.pot-6 {
|
||||
grid-column: 1 / 5;
|
||||
grid-row: 2 / 2;
|
||||
}
|
||||
.pot-7 {
|
||||
grid-column: 2 / 5;
|
||||
grid-row: 2 / 2;
|
||||
}
|
||||
.pot-8 {
|
||||
grid-column: 3 / 5;
|
||||
grid-row: 2 / 2;
|
||||
}
|
||||
.pot-9 {
|
||||
grid-column: 4 / 5;
|
||||
grid-row: 2 / 2;
|
||||
}
|
||||
.pot-10 {
|
||||
grid-column: 5 / 5;
|
||||
grid-row: 2 / 2;
|
||||
}
|
||||
|
||||
}
|
||||
.visit-the-market {
|
||||
height: 32px;
|
||||
margin: 24px 4px;
|
||||
border-radius: 4px;
|
||||
box-shadow: 0 1px 3px 0 rgba(26, 24, 29, 0.12), 0 1px 2px 0 rgba(26, 24, 29, 0.24);
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.four-for-free {
|
||||
font-size: 0.875rem;
|
||||
line-height: 1.71;
|
||||
margin: 0 36px 24px;
|
||||
text-align: center;
|
||||
color: $white;
|
||||
}
|
||||
|
||||
.four-grid {
|
||||
display: grid;
|
||||
grid-template-columns: 4;
|
||||
grid-template-rows: 1;
|
||||
gap: 24px;
|
||||
}
|
||||
.day-one-a, .day-one-b, .day-five, .day-ten {
|
||||
height: 140px;
|
||||
width: 100px;
|
||||
border-radius: 8px;
|
||||
background-color: $purple-50;
|
||||
}
|
||||
|
||||
.day-one-a {
|
||||
grid-column: 1 / 1;
|
||||
grid-row: 1 / 1;
|
||||
}
|
||||
.day-one-b {
|
||||
grid-column: 2 / 2;
|
||||
grid-row: 1 / 1;
|
||||
}
|
||||
.day-five {
|
||||
grid-column: 3 / 3;
|
||||
grid-row: 1 / 1;
|
||||
}
|
||||
.day-ten {
|
||||
grid-column: 4 / 4;
|
||||
grid-row: 1 / 1;
|
||||
}
|
||||
|
||||
.day-text {
|
||||
font-size: 0.75rem;
|
||||
font-weight: bold;
|
||||
line-height: 1.33;
|
||||
letter-spacing: 2.4px;
|
||||
text-align: center;
|
||||
text-transform: uppercase;
|
||||
padding: 4px 0px;
|
||||
color: $yellow-50;
|
||||
}
|
||||
|
||||
.gift {
|
||||
height: 80px;
|
||||
width: 84px;
|
||||
margin: 0 8px 32px;
|
||||
background-color: $purple-100;
|
||||
}
|
||||
|
||||
.description {
|
||||
font-size: 0.75rem;
|
||||
line-height: 1.33;
|
||||
text-align: center;
|
||||
padding: 8px 0px;
|
||||
margin-top: -32px;
|
||||
color: $white;
|
||||
}
|
||||
|
||||
// SVG CSS
|
||||
.modal-close {
|
||||
position: absolute;
|
||||
right: 16px;
|
||||
top: 16px;
|
||||
cursor: pointer;
|
||||
|
||||
.svg-close {
|
||||
width: 18px;
|
||||
height: 18px;
|
||||
vertical-align: middle;
|
||||
fill: $purple-50;
|
||||
|
||||
& svg path {
|
||||
fill: $purple-50 !important;;
|
||||
}
|
||||
& :hover {
|
||||
fill: $purple-50;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.svg-confetti {
|
||||
position: absolute;
|
||||
height: 152px;
|
||||
width: 518px;
|
||||
margin-top: 24px;
|
||||
}
|
||||
|
||||
.svg-gifts, .svg-gifts-flip {
|
||||
position: relative;
|
||||
height: 32px;
|
||||
width: 85px;
|
||||
}
|
||||
|
||||
.svg-gifts {
|
||||
margin-left: 70px;
|
||||
top: 30px;
|
||||
}
|
||||
|
||||
.svg-gifts-flip {
|
||||
-webkit-transform: scaleX(-1);
|
||||
transform: scaleX(-1);
|
||||
left: 366px;
|
||||
bottom: 34px;
|
||||
}
|
||||
|
||||
.left-divider, .right-divider {
|
||||
background-image: url('~@/assets/images/fancy-divider.png');
|
||||
background-position: right center;
|
||||
background-repeat: no-repeat;
|
||||
display: inline-flex;
|
||||
flex-grow: 2;
|
||||
min-height: 1.25rem;
|
||||
}
|
||||
|
||||
.right-divider {
|
||||
-webkit-transform: scaleX(-1);
|
||||
transform: scaleX(-1);
|
||||
}
|
||||
|
||||
.svg-cross {
|
||||
height: 12px;
|
||||
width: 12px;
|
||||
color: $yellow-50;
|
||||
}
|
||||
|
||||
.svg-gem {
|
||||
height: 48px;
|
||||
width: 58px;
|
||||
}
|
||||
|
||||
.svg-background {
|
||||
height: 68px;
|
||||
width: 68px;
|
||||
}
|
||||
|
||||
.svg-stripe {
|
||||
height: 20px;
|
||||
width: 48px;
|
||||
}
|
||||
|
||||
.svg-paypal {
|
||||
height: 16px;
|
||||
width: 60px;
|
||||
}
|
||||
}
|
||||
|
||||
</style>
|
||||
|
||||
|
||||
<script>
|
||||
// to check if user owns JG or not
|
||||
import { mapState } from '@/libs/store';
|
||||
|
||||
// Purchase functionality
|
||||
import buy from '@/mixins/buy';
|
||||
import notifications from '@/mixins/notifications';
|
||||
import payments from '@/mixins/payments';
|
||||
import content from '@/../../common/script/content/index';
|
||||
import amazonButton from '@/components/payments/buttons/amazon';
|
||||
|
||||
// import images
|
||||
import close from '@/assets/svg/new-close.svg';
|
||||
import confetti from '@/assets/svg/confetti.svg';
|
||||
import gifts from '@/assets/svg/gifts-birthday.svg';
|
||||
import cross from '@/assets/svg/cross.svg';
|
||||
import stripe from '@/assets/svg/stripe.svg';
|
||||
import paypal from '@/assets/svg/paypal-logo.svg';
|
||||
import amazon from '@/assets/svg/amazonpay.svg';
|
||||
import birthdayGems from '@/assets/svg/birthday-gems.svg';
|
||||
import birthdayBackground from '@/assets/svg/icon-background-birthday.svg';
|
||||
|
||||
export default {
|
||||
components: {
|
||||
amazonButton,
|
||||
},
|
||||
mixins: [buy, notifications, payments],
|
||||
data () {
|
||||
return {
|
||||
amazonData: {
|
||||
type: 'single',
|
||||
sku: 'Pet-Gryphatrice-Jubilant',
|
||||
},
|
||||
icons: Object.freeze({
|
||||
close,
|
||||
confetti,
|
||||
gifts,
|
||||
cross,
|
||||
stripe,
|
||||
paypal,
|
||||
amazon,
|
||||
birthdayGems,
|
||||
birthdayBackground,
|
||||
}),
|
||||
selectedPage: 'initial-buttons',
|
||||
gryphBought: false,
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
...mapState({
|
||||
user: 'user.data',
|
||||
}),
|
||||
ownGryphatrice () {
|
||||
return Boolean(this.user && this.user.items.pets['Gryphatrice-Jubilant']);
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
hide () {
|
||||
this.$root.$emit('bv::hide::modal', 'birthday-modal');
|
||||
},
|
||||
buyGryphatriceGems () {
|
||||
const gryphatrice = content.petInfo['Gryphatrice-Jubilant'];
|
||||
if (this.user.balance * 4 < gryphatrice.value) {
|
||||
this.$root.$emit('bv::show::modal', 'buy-gems');
|
||||
return this.hide();
|
||||
}
|
||||
if (!this.confirmPurchase(gryphatrice.currency, gryphatrice.value)) {
|
||||
return null;
|
||||
}
|
||||
this.makeGenericPurchase(gryphatrice);
|
||||
this.gryphBought = true;
|
||||
return this.purchased(gryphatrice.text());
|
||||
},
|
||||
closeAndRedirect (route) {
|
||||
const routeTerminator = route.split('/')[route.split('/').length - 1];
|
||||
if (this.$router.history.current.name !== routeTerminator) {
|
||||
this.$router.push(route);
|
||||
}
|
||||
this.hide();
|
||||
},
|
||||
close () {
|
||||
this.$root.$emit('bv::hide::modal', 'birthday-modal');
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
@@ -78,6 +78,7 @@ export default {
|
||||
orderReferenceId: null,
|
||||
subscription: null,
|
||||
coupon: null,
|
||||
sku: null,
|
||||
},
|
||||
isAmazonSetup: false,
|
||||
amazonButtonEnabled: false,
|
||||
@@ -174,7 +175,10 @@ export default {
|
||||
storePaymentStatusAndReload (url) {
|
||||
let paymentType;
|
||||
|
||||
if (this.amazonPayments.type === 'single' && !this.amazonPayments.gift) paymentType = 'gems';
|
||||
if (this.amazonPayments.type === 'single') {
|
||||
if (this.amazonPayments.sku) paymentType = 'sku';
|
||||
else if (!this.amazonPayments.gift) paymentType = 'gems';
|
||||
}
|
||||
if (this.amazonPayments.type === 'subscription') paymentType = 'subscription';
|
||||
if (this.amazonPayments.groupId || this.amazonPayments.groupToCreate) paymentType = 'groupPlan';
|
||||
if (this.amazonPayments.type === 'single' && this.amazonPayments.gift && this.amazonPayments.giftReceiver) {
|
||||
@@ -223,6 +227,7 @@ export default {
|
||||
const data = {
|
||||
orderReferenceId: this.amazonPayments.orderReferenceId,
|
||||
gift: this.amazonPayments.gift,
|
||||
sku: this.amazonPayments.sku,
|
||||
};
|
||||
|
||||
if (this.amazonPayments.gemsBlock) {
|
||||
|
||||
@@ -83,6 +83,7 @@
|
||||
}
|
||||
|
||||
h4 {
|
||||
color: $gray-10;
|
||||
font-size: 0.875rem;
|
||||
font-weight: bold;
|
||||
text-align: center;
|
||||
|
||||
@@ -31,7 +31,6 @@
|
||||
</button>
|
||||
<a
|
||||
v-once
|
||||
class="standard-link"
|
||||
@click="close()"
|
||||
>{{ $t('neverMind') }}</a>
|
||||
</div>
|
||||
|
||||
@@ -180,7 +180,6 @@
|
||||
@import '~@/assets/scss/colors.scss';
|
||||
|
||||
a:not([href]) {
|
||||
color: $blue-10;
|
||||
font-size: 0.875rem;
|
||||
line-height: 1.71;
|
||||
}
|
||||
|
||||
@@ -126,7 +126,7 @@
|
||||
|
||||
<!-- the word "total" -->
|
||||
<div class="buy-gem-total">
|
||||
{{ $t('sendGiftTotal') }}
|
||||
{{ $t('sendTotal') }}
|
||||
</div>
|
||||
|
||||
<!-- the actual dollar amount -->
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
<template>
|
||||
<b-modal
|
||||
id="payments-success-modal"
|
||||
:hide-footer="isNewGroup || isGems || isSubscription"
|
||||
:modal-class="isNewGroup || isGems || isSubscription
|
||||
:hide-footer="isNewGroup || isGems || isSubscription || ownsJubilantGryphatrice"
|
||||
:modal-class="isNewGroup || isGems || isSubscription || ownsJubilantGryphatrice
|
||||
? ['modal-hidden-footer'] : []"
|
||||
>
|
||||
<!-- HEADER -->
|
||||
@@ -20,7 +20,7 @@
|
||||
<div class="check-container d-flex align-items-center justify-content-center">
|
||||
<div
|
||||
v-once
|
||||
class="svg-icon check"
|
||||
class="svg-icon svg-check"
|
||||
v-html="icons.check"
|
||||
></div>
|
||||
</div>
|
||||
@@ -107,6 +107,35 @@
|
||||
class="small-text auto-renew"
|
||||
>{{ $t('paymentAutoRenew') }}</span>
|
||||
</template>
|
||||
<!-- if you buy the Jubilant Gryphatrice during 10th birthday -->
|
||||
<template
|
||||
v-if="ownsJubilantGryphatrice"
|
||||
>
|
||||
<div class="words">
|
||||
<p class="jub-success">
|
||||
<span
|
||||
v-once
|
||||
v-html="$t('jubilantSuccess')"
|
||||
>
|
||||
</span>
|
||||
</p>
|
||||
<p class="jub-success">
|
||||
<span
|
||||
v-once
|
||||
v-html="$t('stableVisit')"
|
||||
>
|
||||
</span>
|
||||
</p>
|
||||
</div>
|
||||
<div class="gryph-bg">
|
||||
<img
|
||||
src="https://habitica-assets.s3.amazonaws.com/mobileApp/images/Pet-Gryphatrice-Jubilant-Large.gif"
|
||||
alt="a pink, purple, and green gryphatrice pet winks at you adorably"
|
||||
width="78px"
|
||||
height="72px"
|
||||
>
|
||||
</div>
|
||||
</template>
|
||||
<!-- buttons for subscriptions / new Group / buy Gems for self -->
|
||||
<button
|
||||
v-if="isNewGroup || isGems || isSubscription"
|
||||
@@ -116,6 +145,14 @@
|
||||
>
|
||||
{{ $t('onwards') }}
|
||||
</button>
|
||||
<!-- buttons for Jubilant Gryphatrice purchase during 10th birthday -->
|
||||
<button
|
||||
v-if="ownsJubilantGryphatrice"
|
||||
class="btn btn-primary mx-auto btn-jub"
|
||||
@click="closeAndRedirect()"
|
||||
>
|
||||
{{ $t('takeMeToStable') }}
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
<!-- FOOTER -->
|
||||
@@ -232,9 +269,8 @@
|
||||
margin-bottom: 16px;
|
||||
}
|
||||
|
||||
.check {
|
||||
width: 35.1px;
|
||||
height: 28px;
|
||||
.svg-check {
|
||||
width: 45px;
|
||||
color: $white;
|
||||
}
|
||||
}
|
||||
@@ -293,6 +329,34 @@
|
||||
.group-billing-date {
|
||||
width: 269px;
|
||||
}
|
||||
|
||||
.words {
|
||||
margin-bottom: 16px;
|
||||
justify-content: center;
|
||||
font-size: 0.875rem;
|
||||
color: $gray-50;
|
||||
line-height: 1.71;
|
||||
}
|
||||
|
||||
.jub-success {
|
||||
margin-top: 0px;
|
||||
margin-bottom: 0px;
|
||||
}
|
||||
|
||||
.gryph-bg {
|
||||
width: 110px;
|
||||
height: 104px;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
padding: 16px;
|
||||
border-radius: 4px;
|
||||
background-color: $gray-700;
|
||||
}
|
||||
.btn-jub {
|
||||
margin-bottom: 8px;
|
||||
margin-top: 24px;
|
||||
}
|
||||
|
||||
}
|
||||
.modal-footer {
|
||||
background: $gray-700;
|
||||
@@ -430,6 +494,9 @@ export default {
|
||||
isNewGroup () {
|
||||
return this.paymentData.paymentType === 'groupPlan' && this.paymentData.newGroup;
|
||||
},
|
||||
ownsJubilantGryphatrice () {
|
||||
return this.paymentData.paymentType === 'sku'; // will need to be revised when there are other discrete skus in system
|
||||
},
|
||||
},
|
||||
mounted () {
|
||||
this.$root.$on('habitica:payment-success', data => {
|
||||
@@ -458,6 +525,12 @@ export default {
|
||||
this.sendingInProgress = false;
|
||||
this.$root.$emit('bv::hide::modal', 'payments-success-modal');
|
||||
},
|
||||
closeAndRedirect () {
|
||||
if (this.$router.history.current.name !== 'stable') {
|
||||
this.$router.push('/inventory/stable');
|
||||
}
|
||||
this.close();
|
||||
},
|
||||
submit () {
|
||||
if (this.paymentData.group && !this.paymentData.newGroup) {
|
||||
Analytics.track({
|
||||
|
||||
@@ -23,33 +23,7 @@
|
||||
</div>
|
||||
<div class="section">
|
||||
<h3>{{ $t('thirdPartyApps') }}</h3>
|
||||
<ul>
|
||||
<li>
|
||||
<a
|
||||
target="_blank"
|
||||
href="https://www.beeminder.com/habitica"
|
||||
>{{ $t('beeminder') }}</a>
|
||||
<br>
|
||||
{{ $t('beeminderDesc') }}
|
||||
</li>
|
||||
<li>
|
||||
<div v-html="$t('chatExtension')">
|
||||
</div>
|
||||
<span>{{ $t('chatExtensionDesc') }}</span>
|
||||
</li>
|
||||
<li>
|
||||
<a
|
||||
target="_blank"
|
||||
:href="`https://oldgods.net/habitica/habitrpg_user_data_display.html?uuid=` + user._id"
|
||||
>{{ $t('dataDisplayTool') }}</a>
|
||||
<br>
|
||||
{{ $t('dataToolDesc') }}
|
||||
</li>
|
||||
<li>
|
||||
<div v-html="$t('otherExtensions')"></div>
|
||||
<span>{{ $t('otherDesc') }}</span>
|
||||
</li>
|
||||
</ul>
|
||||
<p v-html="$t('thirdPartyTools')"></p>
|
||||
<hr>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -179,7 +179,9 @@ export default {
|
||||
let valid = true;
|
||||
|
||||
for (const stat of canRestore) {
|
||||
if (this.restoreValues.stats[stat] === '') {
|
||||
if (this.restoreValues.stats[stat] === ''
|
||||
|| this.restoreValues.stats[stat] < 0
|
||||
) {
|
||||
this.restoreValues.stats[stat] = this.user.stats[stat];
|
||||
valid = false;
|
||||
}
|
||||
|
||||
@@ -7,6 +7,38 @@
|
||||
{{ $t('settings') }}
|
||||
</h1>
|
||||
<div class="col-sm-6">
|
||||
<div class="sleep">
|
||||
<h5>{{ $t('pauseDailies') }}</h5>
|
||||
<h4>{{ $t('sleepDescription') }}</h4>
|
||||
<ul>
|
||||
<li v-once>
|
||||
{{ $t('sleepBullet1') }}
|
||||
</li>
|
||||
<li v-once>
|
||||
{{ $t('sleepBullet2') }}
|
||||
</li>
|
||||
<li v-once>
|
||||
{{ $t('sleepBullet3') }}
|
||||
</li>
|
||||
</ul>
|
||||
<button
|
||||
v-if="!user.preferences.sleep"
|
||||
v-once
|
||||
class="sleep btn btn-primary btn-block pause-button"
|
||||
@click="toggleSleep()"
|
||||
>
|
||||
{{ $t('pauseDailies') }}
|
||||
</button>
|
||||
<button
|
||||
v-if="user.preferences.sleep"
|
||||
v-once
|
||||
class="btn btn-secondary btn-block pause-button"
|
||||
@click="toggleSleep()"
|
||||
>
|
||||
{{ $t('unpauseDailies') }}
|
||||
</button>
|
||||
</div>
|
||||
<hr>
|
||||
<div class="form-horizontal">
|
||||
<h5>{{ $t('language') }}</h5>
|
||||
<select
|
||||
@@ -96,7 +128,10 @@
|
||||
<hr>
|
||||
</div>
|
||||
<div>
|
||||
<div class="checkbox">
|
||||
<div
|
||||
class="checkbox"
|
||||
id="preferenceAdvancedCollapsed"
|
||||
>
|
||||
<label>
|
||||
<input
|
||||
v-model="user.preferences.advancedCollapsed"
|
||||
@@ -104,33 +139,22 @@
|
||||
class="mr-2"
|
||||
@change="set('advancedCollapsed')"
|
||||
>
|
||||
<span
|
||||
class="hint"
|
||||
popover-trigger="mouseenter"
|
||||
popover-placement="right"
|
||||
:popover="$t('startAdvCollapsedPop')"
|
||||
>{{ $t('startAdvCollapsed') }}</span>
|
||||
</label>
|
||||
</div>
|
||||
<div class="checkbox">
|
||||
<label>
|
||||
<input
|
||||
v-model="user.preferences.dailyDueDefaultView"
|
||||
type="checkbox"
|
||||
class="mr-2"
|
||||
@change="set('dailyDueDefaultView')"
|
||||
>
|
||||
<span
|
||||
class="hint"
|
||||
popover-trigger="mouseenter"
|
||||
popover-placement="right"
|
||||
:popover="$t('dailyDueDefaultViewPop')"
|
||||
>{{ $t('dailyDueDefaultView') }}</span>
|
||||
<span class="hint">
|
||||
{{ $t('startAdvCollapsed') }}
|
||||
</span>
|
||||
<b-popover
|
||||
target="preferenceAdvancedCollapsed"
|
||||
triggers="hover focus"
|
||||
placement="right"
|
||||
:prevent-overflow="false"
|
||||
:content="$t('startAdvCollapsedPop')"
|
||||
/>
|
||||
</label>
|
||||
</div>
|
||||
<div
|
||||
v-if="party.memberCount === 1"
|
||||
class="checkbox"
|
||||
id="preferenceDisplayInviteAtOneMember"
|
||||
>
|
||||
<label>
|
||||
<input
|
||||
@@ -139,12 +163,9 @@
|
||||
class="mr-2"
|
||||
@change="set('displayInviteToPartyWhenPartyIs1')"
|
||||
>
|
||||
<span
|
||||
class="hint"
|
||||
popover-trigger="mouseenter"
|
||||
popover-placement="right"
|
||||
:popover="$t('displayInviteToPartyWhenPartyIs1')"
|
||||
>{{ $t('displayInviteToPartyWhenPartyIs1') }}</span>
|
||||
<span class="hint">
|
||||
{{ $t('displayInviteToPartyWhenPartyIs1') }}
|
||||
</span>
|
||||
</label>
|
||||
</div>
|
||||
<div class="checkbox">
|
||||
@@ -185,32 +206,47 @@
|
||||
</div>
|
||||
<hr>
|
||||
<button
|
||||
id="buttonShowBailey"
|
||||
class="btn btn-primary mr-2 mb-2"
|
||||
popover-trigger="mouseenter"
|
||||
popover-placement="right"
|
||||
:popover="$t('showBaileyPop')"
|
||||
@click="showBailey()"
|
||||
>
|
||||
{{ $t('showBailey') }}
|
||||
<b-popover
|
||||
target="buttonShowBailey"
|
||||
triggers="hover focus"
|
||||
placement="right"
|
||||
:prevent-overflow="false"
|
||||
:content="$t('showBaileyPop')"
|
||||
/>
|
||||
</button>
|
||||
<button
|
||||
id="buttonFCV"
|
||||
class="btn btn-primary mr-2 mb-2"
|
||||
popover-trigger="mouseenter"
|
||||
popover-placement="right"
|
||||
:popover="$t('fixValPop')"
|
||||
@click="openRestoreModal()"
|
||||
>
|
||||
{{ $t('fixVal') }}
|
||||
<b-popover
|
||||
target="buttonFCV"
|
||||
triggers="hover focus"
|
||||
placement="right"
|
||||
:prevent-overflow="false"
|
||||
:content="$t('fixValPop')"
|
||||
/>
|
||||
</button>
|
||||
<button
|
||||
v-if="user.preferences.disableClasses == true"
|
||||
id="buttonEnableClasses"
|
||||
class="btn btn-primary mb-2"
|
||||
popover-trigger="mouseenter"
|
||||
popover-placement="right"
|
||||
:popover="$t('enableClassPop')"
|
||||
@click="changeClassForUser(false)"
|
||||
>
|
||||
{{ $t('enableClass') }}
|
||||
<b-popover
|
||||
target="buttonEnableClasses"
|
||||
triggers="hover focus"
|
||||
placement="right"
|
||||
:prevent-overflow="false"
|
||||
:content="$t('enableClassPop')"
|
||||
/>
|
||||
</button>
|
||||
<hr>
|
||||
<day-start-adjustment />
|
||||
@@ -500,6 +536,10 @@
|
||||
input {
|
||||
color: $gray-50;
|
||||
}
|
||||
|
||||
.checkbox {
|
||||
width: fit-content;
|
||||
}
|
||||
.usersettings h5 {
|
||||
margin-top: 1em;
|
||||
}
|
||||
@@ -517,6 +557,10 @@
|
||||
width: 100%;
|
||||
margin-top: 5px;
|
||||
}
|
||||
|
||||
.sleep {
|
||||
margin-bottom: 16px;
|
||||
}
|
||||
</style>
|
||||
|
||||
<script>
|
||||
@@ -651,6 +695,9 @@ export default {
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
toggleSleep () {
|
||||
this.$store.dispatch('user:sleep');
|
||||
},
|
||||
validateDisplayName: debounce(function checkName (displayName) {
|
||||
if (displayName.length <= 1 || displayName === this.user.profile.name) {
|
||||
this.displayNameIssues = [];
|
||||
|
||||
@@ -93,7 +93,7 @@
|
||||
<div class="subscribe-card mx-auto">
|
||||
<div
|
||||
v-if="hasSubscription && !hasCanceledSubscription"
|
||||
class="d-flex flex-column align-items-center"
|
||||
class="d-flex flex-column align-items-center pt-4"
|
||||
>
|
||||
<div class="round-container bg-green-10 d-flex align-items-center justify-content-center">
|
||||
<div
|
||||
@@ -107,7 +107,7 @@
|
||||
</h2>
|
||||
<div
|
||||
v-if="hasGroupPlan"
|
||||
class="mx-5 text-center"
|
||||
class="mx-5 mb-4 text-center"
|
||||
>
|
||||
{{ $t('youHaveGroupPlan') }}
|
||||
</div>
|
||||
@@ -130,7 +130,7 @@
|
||||
</div>
|
||||
<button
|
||||
class="btn btn-primary btn-update-card
|
||||
d-flex justify-content-center align-items-center"
|
||||
d-flex justify-content-center align-items-center mb-4"
|
||||
@click="redirectToStripeEdit()"
|
||||
>
|
||||
<div
|
||||
@@ -143,21 +143,61 @@
|
||||
</div>
|
||||
<div
|
||||
v-else
|
||||
class="svg-icon"
|
||||
class="svg-icon mb-4"
|
||||
:class="paymentMethodLogo.class"
|
||||
v-html="paymentMethodLogo.icon"
|
||||
>
|
||||
</div>
|
||||
<div
|
||||
v-if="purchasedPlanExtraMonthsDetails.months > 0"
|
||||
class="extra-months green-10 py-2 px-3 mt-4"
|
||||
class="extra-months green-10 py-2 px-3 mb-4"
|
||||
v-html="$t('purchasedPlanExtraMonths',
|
||||
{months: purchasedPlanExtraMonthsDetails.months})"
|
||||
>
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
v-if="hasCanceledSubscription"
|
||||
v-if="hasGiftSubscription"
|
||||
class="d-flex flex-column align-items-center mt-4"
|
||||
>
|
||||
<div class="round-container bg-green-10 d-flex align-items-center justify-content-center">
|
||||
<div
|
||||
v-once
|
||||
class="svg-icon svg-check"
|
||||
v-html="icons.checkmarkIcon"
|
||||
></div>
|
||||
</div>
|
||||
<h2 class="green-10 mx-auto mb-75">
|
||||
{{ $t('youAreSubscribed') }}
|
||||
</h2>
|
||||
<div
|
||||
class="mx-4 text-center mb-4 lh-71"
|
||||
>
|
||||
<span v-once>
|
||||
{{ $t('haveNonRecurringSub') }}
|
||||
</span>
|
||||
<span
|
||||
v-once
|
||||
v-html="$t('subscriptionInactiveDate', {date: subscriptionEndDate})"
|
||||
>
|
||||
</span>
|
||||
</div>
|
||||
<h2 v-once>
|
||||
{{ $t('switchToRecurring') }}
|
||||
</h2>
|
||||
<small
|
||||
v-once
|
||||
class="mx-4 mb-3 text-center"
|
||||
>
|
||||
{{ $t('continueGiftSubBenefits') }}
|
||||
</small>
|
||||
<subscription-options
|
||||
:note="'subscriptionCreditConversion'"
|
||||
class="w-100 mb-2"
|
||||
/>
|
||||
</div>
|
||||
<div
|
||||
v-else-if="hasCanceledSubscription"
|
||||
class="d-flex flex-column align-items-center mt-4"
|
||||
>
|
||||
<div class="round-container bg-gray-300 d-flex align-items-center justify-content-center">
|
||||
@@ -180,7 +220,7 @@
|
||||
</div>
|
||||
<div
|
||||
v-if="hasSubscription"
|
||||
class="bg-gray-700 py-3 mt-4 mb-3 text-center"
|
||||
class="bg-gray-700 py-3 mb-3 text-center"
|
||||
>
|
||||
<div class="header-mini mb-3">
|
||||
{{ $t('subscriptionStats') }}
|
||||
@@ -322,6 +362,12 @@
|
||||
max-width: 21rem;
|
||||
}
|
||||
|
||||
small {
|
||||
color: $gray-100;
|
||||
font-size: 12px ;
|
||||
line-height: 1.33;
|
||||
}
|
||||
|
||||
strong {
|
||||
font-size: 16px;
|
||||
}
|
||||
@@ -399,6 +445,10 @@
|
||||
height: 49px;
|
||||
}
|
||||
|
||||
.lh-71 {
|
||||
line-height: 1.71;
|
||||
}
|
||||
|
||||
.maroon-50 {
|
||||
color: $maroon-50;
|
||||
}
|
||||
@@ -443,7 +493,6 @@
|
||||
}
|
||||
|
||||
.subscribe-card {
|
||||
padding-top: 2rem;
|
||||
width: 28rem;
|
||||
border-radius: 8px;
|
||||
box-shadow: 0 2px 2px 0 rgba(26, 24, 29, 0.16), 0 1px 4px 0 rgba(26, 24, 29, 0.12);
|
||||
@@ -472,8 +521,7 @@
|
||||
}
|
||||
|
||||
.svg-check {
|
||||
width: 35.1px;
|
||||
height: 28px;
|
||||
width: 36px;
|
||||
color: $white;
|
||||
}
|
||||
|
||||
@@ -670,6 +718,9 @@ export default {
|
||||
hasSubscription () {
|
||||
return Boolean(this.user.purchased.plan.customerId);
|
||||
},
|
||||
hasGiftSubscription () {
|
||||
return this.user.purchased.plan.customerId === 'Gift';
|
||||
},
|
||||
hasCanceledSubscription () {
|
||||
return (
|
||||
this.hasSubscription
|
||||
@@ -753,7 +804,7 @@ export default {
|
||||
return currentPlanContext.nextHourglassDate;
|
||||
},
|
||||
nextHourGlass () {
|
||||
const nextHourglassMonth = this.nextHourGlassDate.format('MMM');
|
||||
const nextHourglassMonth = this.nextHourGlassDate.format('MMM YYYY');
|
||||
|
||||
return nextHourglassMonth;
|
||||
},
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
<template>
|
||||
<div id="subscription-form">
|
||||
<b-form-group class="mb-4 w-100 h-100">
|
||||
<b-form-group class="mb-3 w-100 h-100">
|
||||
<!-- eslint-disable vue/no-use-v-if-with-v-for -->
|
||||
<b-form-radio
|
||||
v-for="block in subscriptionBlocksOrdered"
|
||||
@@ -32,6 +32,15 @@
|
||||
</div>
|
||||
</b-form-radio>
|
||||
</b-form-group>
|
||||
<div class="mx-4 mb-4 text-center">
|
||||
<small
|
||||
v-if="note"
|
||||
v-once
|
||||
class="font-italic"
|
||||
>
|
||||
{{ $t(note) }}
|
||||
</small>
|
||||
</div>
|
||||
<!-- payment buttons first is for gift subs and the second is for renewing subs -->
|
||||
<payments-buttons
|
||||
v-if="userReceivingGift && userReceivingGift._id"
|
||||
@@ -82,7 +91,10 @@
|
||||
|
||||
.subscription-bubble, .discount-bubble {
|
||||
border-radius: 100px;
|
||||
padding-left: 12px;
|
||||
padding-right: 12px;
|
||||
font-size: 12px;
|
||||
line-height: 1.33;
|
||||
}
|
||||
|
||||
.subscription-bubble {
|
||||
@@ -100,8 +112,20 @@
|
||||
<style lang="scss" scoped>
|
||||
@import '~@/assets/scss/colors.scss';
|
||||
|
||||
small {
|
||||
color: $gray-100;
|
||||
display: inline-block;
|
||||
font-size: 12px ;
|
||||
font-weight: normal;
|
||||
line-height: 1.33;
|
||||
}
|
||||
|
||||
.subscribe-option {
|
||||
border-bottom: 1px solid $gray-600;
|
||||
background-color: $gray-700;
|
||||
|
||||
&:not(:last-of-type) {
|
||||
border-bottom: 1px solid $gray-600;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -121,6 +145,10 @@ export default {
|
||||
paymentsMixin,
|
||||
],
|
||||
props: {
|
||||
note: {
|
||||
type: String,
|
||||
default: null,
|
||||
},
|
||||
userReceivingGift: {
|
||||
type: Object,
|
||||
default () {},
|
||||
@@ -154,13 +182,13 @@ export default {
|
||||
subscriptionBubbles (subscription) {
|
||||
switch (subscription) {
|
||||
case 'basic_3mo':
|
||||
return '<span class="subscription-bubble px-2 py-1 mr-1">Gem cap raised to 30</span><span class="subscription-bubble px-2 py-1">+1 Mystic Hourglass</span>';
|
||||
return '<span class="subscription-bubble py-1 mr-1">Gem cap raised to 30</span><span class="subscription-bubble py-1">+1 Mystic Hourglass</span>';
|
||||
case 'basic_6mo':
|
||||
return '<span class="subscription-bubble px-2 py-1 mr-1">Gem cap raised to 35</span><span class="subscription-bubble px-2 py-1">+2 Mystic Hourglass</span>';
|
||||
return '<span class="subscription-bubble py-1 mr-1">Gem cap raised to 35</span><span class="subscription-bubble py-1">+2 Mystic Hourglass</span>';
|
||||
case 'basic_12mo':
|
||||
return '<span class="discount-bubble px-2 py-1 mr-1">Save 20%</span><span class="subscription-bubble px-2 py-1 mr-1">Gem cap raised to 45</span><span class="subscription-bubble px-2 py-1">+4 Mystic Hourglass</span>';
|
||||
return '<span class="discount-bubble py-1 mr-1">Save 20%</span><span class="subscription-bubble py-1 mr-1">Gem cap raised to 45</span><span class="subscription-bubble py-1">+4 Mystic Hourglass</span>';
|
||||
default:
|
||||
return '<span class="subscription-bubble px-2 py-1">Gem cap at 25</span>';
|
||||
return '<span class="subscription-bubble py-1">Gem cap at 25</span>';
|
||||
}
|
||||
},
|
||||
updateSubscriptionData (key) {
|
||||
|
||||
93
website/client/src/components/shared/itemCost.vue
Normal file
@@ -0,0 +1,93 @@
|
||||
<template>
|
||||
<div class="item-cost">
|
||||
<span
|
||||
class="cost"
|
||||
:class="getPriceClass()"
|
||||
>
|
||||
<span
|
||||
class="svg-icon inline icon-24"
|
||||
aria-hidden="true"
|
||||
v-html="icons[getPriceClass()]"
|
||||
>
|
||||
</span>
|
||||
<span
|
||||
:class="getPriceClass()"
|
||||
>{{ item.value }}</span>
|
||||
</span>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
|
||||
<style lang="scss">
|
||||
@import '~@/assets/scss/colors.scss';
|
||||
@import '~@/assets/scss/mixins.scss';
|
||||
|
||||
.item-cost {
|
||||
padding-bottom: 16px;
|
||||
}
|
||||
|
||||
.cost {
|
||||
height: 40px;
|
||||
font-size: 1.25rem;
|
||||
font-weight: bold;
|
||||
line-height: 1.4;
|
||||
vertical-align: middle;
|
||||
|
||||
&.gems {
|
||||
color: $gems-color;
|
||||
border-radius: 20px;
|
||||
padding: 8px 20px 8px 20px;
|
||||
margin-top: 16px;
|
||||
margin-bottom: 16px;
|
||||
background-color: rgba(36, 204, 143, 0.15);
|
||||
}
|
||||
|
||||
&.gold {
|
||||
color: $gold-color;
|
||||
border-radius: 20px;
|
||||
padding: 8px 20px 8px 20px;
|
||||
margin-top: 16px;
|
||||
margin-bottom: 16px;
|
||||
background-color: rgba(255, 190, 93, 0.15);
|
||||
}
|
||||
|
||||
&.hourglasses {
|
||||
color: $hourglass-color;
|
||||
border-radius: 20px;
|
||||
padding: 8px 20px 8px 20px;
|
||||
margin-top: 16px;
|
||||
margin-bottom: 16px;
|
||||
background-color: rgba(41, 149, 205, 0.15);
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
<script>
|
||||
import svgClose from '@/assets/svg/close.svg';
|
||||
import svgGold from '@/assets/svg/gold.svg';
|
||||
import svgGem from '@/assets/svg/gem.svg';
|
||||
|
||||
export default {
|
||||
data () {
|
||||
return {
|
||||
icons: Object.freeze({
|
||||
close: svgClose,
|
||||
gold: svgGold,
|
||||
gems: svgGem,
|
||||
}),
|
||||
selectedAmountToBuy: 1,
|
||||
selectedAmount: 1,
|
||||
};
|
||||
},
|
||||
methods: {
|
||||
getPriceClass () {
|
||||
if (this.priceType && this.icons[this.priceType]) {
|
||||
return this.priceType;
|
||||
} if (this.item.currency && this.icons[this.item.currency]) {
|
||||
return this.item.currency;
|
||||
}
|
||||
return 'gold';
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
137
website/client/src/components/shared/numberIncrement.vue
Normal file
@@ -0,0 +1,137 @@
|
||||
<template>
|
||||
<div class="d-flex flex-row align-items-center justify-content-center number-increment">
|
||||
<!-- buy modal -->
|
||||
<div
|
||||
class="gray-circle"
|
||||
@click="quantity <= 0
|
||||
? quantity = 0
|
||||
: quantity--"
|
||||
>
|
||||
<div
|
||||
class="icon-negative"
|
||||
v-html="icons.svgNegative"
|
||||
></div>
|
||||
</div>
|
||||
<div class="input-group">
|
||||
<div class="align-items-center">
|
||||
</div>
|
||||
<input
|
||||
v-model="quantity"
|
||||
class="form-control alignment"
|
||||
step="1"
|
||||
type="number"
|
||||
>
|
||||
</div>
|
||||
<div
|
||||
class="gray-circle"
|
||||
@click="quantity++"
|
||||
>
|
||||
<div
|
||||
class="icon-positive"
|
||||
v-html="icons.svgPositive"
|
||||
></div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<style scoped lang="scss">
|
||||
@import '~@/assets/scss/colors.scss';
|
||||
|
||||
.number-increment {
|
||||
padding-bottom: 0px;
|
||||
}
|
||||
|
||||
.alignment {
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.input-group {
|
||||
width: 94px;
|
||||
height: 32px;
|
||||
width: 48px;
|
||||
margin: 0px 16px 0px 16px;
|
||||
padding: 0;
|
||||
border-radius: 2px;
|
||||
border: solid 1px $gray-400;
|
||||
background-color: $white;
|
||||
}
|
||||
|
||||
.gray-circle {
|
||||
border-radius: 100%;
|
||||
border: solid 2px $gray-300;
|
||||
width: 32px;
|
||||
height: 32px;
|
||||
cursor: pointer;
|
||||
|
||||
&:hover {
|
||||
border-color: $purple-300;
|
||||
}
|
||||
}
|
||||
|
||||
.gray-circle:hover{
|
||||
.icon-positive, .icon-negative {
|
||||
& ::v-deep svg path {
|
||||
fill: $purple-300;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.icon-positive, .icon-negative {
|
||||
width: 10px;
|
||||
height: 10px;
|
||||
margin: 4px auto;
|
||||
|
||||
& ::v-deep svg path {
|
||||
fill: $gray-300;
|
||||
}
|
||||
}
|
||||
|
||||
/* Chrome, Safari, Edge, Opera */
|
||||
input::-webkit-outer-spin-button,
|
||||
input::-webkit-inner-spin-button {
|
||||
-webkit-appearance: none;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
/* Firefox */
|
||||
input[type=number] {
|
||||
-moz-appearance: textfield;
|
||||
}
|
||||
|
||||
</style>
|
||||
|
||||
<script>
|
||||
// icons
|
||||
import svgGem from '@/assets/svg/gem.svg';
|
||||
import svgGold from '@/assets/svg/gold.svg';
|
||||
import svgPositive from '@/assets/svg/positive.svg';
|
||||
import svgNegative from '@/assets/svg/negative.svg';
|
||||
|
||||
export default {
|
||||
data () {
|
||||
return {
|
||||
icons: Object.freeze({
|
||||
svgGem,
|
||||
svgGold,
|
||||
svgPositive,
|
||||
svgNegative,
|
||||
}),
|
||||
item: { },
|
||||
quantity: 1,
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
},
|
||||
watch: {
|
||||
quantity () {
|
||||
this.$emit('updateQuantity', this.quantity);
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
setDefaults () {
|
||||
this.input = 1;
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
</script>
|
||||
@@ -22,10 +22,11 @@
|
||||
@import '~@/assets/scss/colors.scss';
|
||||
|
||||
span {
|
||||
font-weight: normal;
|
||||
font-size: 12px;
|
||||
font-size: 0.75rem;
|
||||
line-height: 1.33;
|
||||
color: $gray-200;
|
||||
color: $gray-100;
|
||||
margin-bottom: 16px;
|
||||
margin-top: -4px;
|
||||
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
</span>
|
||||
<div>
|
||||
<span
|
||||
class="svg-icon icon-12 close-icon"
|
||||
class="svg-icon close-icon icon-16 color"
|
||||
aria-hidden="true"
|
||||
tabindex="0"
|
||||
@click="hideDialog()"
|
||||
@@ -45,6 +45,13 @@
|
||||
:sprites-margin="'0px auto 0px -24px'"
|
||||
/>
|
||||
</div>
|
||||
<item
|
||||
v-else-if="item.key === 'gem'"
|
||||
class="flat bordered-item"
|
||||
:item="item"
|
||||
:item-content-class="item.class"
|
||||
:show-popover="false"
|
||||
/>
|
||||
<item
|
||||
v-else-if="item.key != 'gem'"
|
||||
class="flat bordered-item"
|
||||
@@ -53,10 +60,20 @@
|
||||
:show-popover="false"
|
||||
/>
|
||||
</slot>
|
||||
<div
|
||||
v-if="!showAvatar && user.items[item.purchaseType]"
|
||||
class="owned"
|
||||
:class="totalOwned"
|
||||
>
|
||||
<!-- eslint-disable-next-line max-len -->
|
||||
<span class="owned-text">{{ $t('owned') }}: <span class="user-amount">{{ totalOwned }}</span></span>
|
||||
</div>
|
||||
<h4 class="title">
|
||||
{{ itemText }}
|
||||
</h4>
|
||||
<div v-html="itemNotes"></div>
|
||||
<div class="item-notes">
|
||||
{{ itemNotes }}
|
||||
</div>
|
||||
<slot
|
||||
name="additionalInfo"
|
||||
:item="item"
|
||||
@@ -69,60 +86,61 @@
|
||||
/>
|
||||
</slot>
|
||||
<div
|
||||
v-if="item.value > 0"
|
||||
v-if="item.value > 0 && !(item.key === 'gem' && gemsLeft < 1)"
|
||||
class="purchase-amount"
|
||||
>
|
||||
<div
|
||||
v-if="showAmountToBuy(item)"
|
||||
class="how-many-to-buy"
|
||||
>
|
||||
<strong>{{ $t('howManyToBuy') }}</strong>
|
||||
</div>
|
||||
<div v-if="showAmountToBuy(item)">
|
||||
<div class="box">
|
||||
<input
|
||||
v-model.number="selectedAmountToBuy"
|
||||
class="form-control"
|
||||
type="number"
|
||||
min="0"
|
||||
step="1"
|
||||
>
|
||||
</div>
|
||||
<span :class="{'notEnough': notEnoughCurrency}">
|
||||
<!-- this is where the pretty item cost element lives -->
|
||||
<div class="item-cost">
|
||||
<span
|
||||
class="cost"
|
||||
:class="getPriceClass()"
|
||||
>
|
||||
<span
|
||||
class="svg-icon inline icon-32"
|
||||
class="svg-icon inline icon-24"
|
||||
aria-hidden="true"
|
||||
v-html="icons[getPriceClass()]"
|
||||
></span>
|
||||
>
|
||||
</span>
|
||||
<span
|
||||
class="cost"
|
||||
:class="getPriceClass()"
|
||||
>{{ item.value }}</span>
|
||||
</span>
|
||||
</div>
|
||||
|
||||
<div
|
||||
v-else
|
||||
class="d-flex align-items-middle"
|
||||
v-if="showAmountToBuy(item)"
|
||||
class="how-many-to-buy"
|
||||
>
|
||||
<span
|
||||
class="svg-icon inline icon-32 ml-auto my-auto"
|
||||
aria-hidden="true"
|
||||
v-html="icons[getPriceClass()]"
|
||||
></span>
|
||||
<span
|
||||
class="cost mr-auto my-auto"
|
||||
:class="getPriceClass()"
|
||||
>{{ item.value }}</span>
|
||||
{{ $t('howManyToBuy') }}
|
||||
</div>
|
||||
<div
|
||||
v-if="showAmountToBuy(item)"
|
||||
>
|
||||
<number-increment
|
||||
class="number-increment"
|
||||
@updateQuantity="selectedAmountToBuy = $event"
|
||||
/>
|
||||
<div
|
||||
:class="{'notEnough': notEnoughCurrency}"
|
||||
class="total"
|
||||
>
|
||||
<span class="total-text">{{ $t('sendTotal') }}</span>
|
||||
<span
|
||||
class="svg-icon total icon-24"
|
||||
aria-hidden="true"
|
||||
v-html="icons[getPriceClass()]"
|
||||
></span>
|
||||
<span
|
||||
class="total-text"
|
||||
:class="getPriceClass()"
|
||||
>{{ item.value * selectedAmountToBuy }}</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
v-if="item.key === 'gem'"
|
||||
class="gems-left"
|
||||
v-if="item.key === 'gem' && gemsLeft < 1"
|
||||
class="no-more-gems"
|
||||
>
|
||||
<strong v-if="gemsLeft > 0">{{ gemsLeft }} {{ $t('gemsRemaining') }}</strong>
|
||||
<strong v-if="gemsLeft === 0">{{ $t('maxBuyGems') }}</strong>
|
||||
</div>
|
||||
<div v-if="attemptingToPurchaseMoreGemsThanAreLeft">
|
||||
{{ $t('notEnoughGemsToBuy') }}
|
||||
</div>
|
||||
<div
|
||||
@@ -147,7 +165,7 @@
|
||||
{{ $t('viewSubscriptions') }}
|
||||
</button>
|
||||
<button
|
||||
v-else
|
||||
v-else-if="!(item.key === 'gem' && gemsLeft < 1)"
|
||||
class="btn btn-primary"
|
||||
:disabled="item.key === 'gem' && gemsLeft === 0 ||
|
||||
attemptingToPurchaseMoreGemsThanAreLeft || numberInvalid || item.locked ||
|
||||
@@ -165,6 +183,7 @@
|
||||
<countdown-banner
|
||||
v-if="item.event && item.owned == null"
|
||||
:end-date="endDate"
|
||||
class="limitedTime available"
|
||||
/>
|
||||
<div
|
||||
v-if="item.key === 'rebirth_orb' && item.value > 0 && user.stats.lvl >= 100"
|
||||
@@ -179,12 +198,31 @@
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
slot="modal-footer"
|
||||
class="d-flex"
|
||||
v-if="item.key === 'gem'"
|
||||
class="d-flex justify-content-center align-items-center"
|
||||
>
|
||||
<span class="balance mr-auto">{{ $t('yourBalance') }}</span>
|
||||
<div
|
||||
v-if="gemsLeft > 0"
|
||||
class="gems-left d-flex justify-content-center align-items-center"
|
||||
>
|
||||
<strong>{{ $t('monthlyGems') }} </strong>
|
||||
{{ gemsLeft }} / {{ totalGems }} {{ $t('gemsRemaining') }}
|
||||
</div>
|
||||
<div
|
||||
v-if="gemsLeft === 0"
|
||||
class="out-of-gems-banner d-flex justify-content-center align-items-center"
|
||||
>
|
||||
<strong>{{ $t('monthlyGems') }} </strong>
|
||||
{{ gemsLeft }} / {{ totalGems }} {{ $t('gemsRemaining') }}
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
slot="modal-footer"
|
||||
class="clearfix"
|
||||
>
|
||||
<span class="user-balance float-left">{{ $t('yourBalance') }}</span>
|
||||
<balanceInfo
|
||||
class="ml-auto"
|
||||
class="currency-totals"
|
||||
:currency-needed="getPriceClass()"
|
||||
:amount-needed="item.value"
|
||||
/>
|
||||
@@ -200,11 +238,47 @@
|
||||
@include centeredModal();
|
||||
|
||||
.modal-body {
|
||||
padding-left: 0px;
|
||||
padding-right: 0px;
|
||||
padding-bottom: 0px;
|
||||
}
|
||||
|
||||
.modal-footer {
|
||||
height: 48px;
|
||||
background-color: $gray-700;
|
||||
border-bottom-right-radius: 8px;
|
||||
border-bottom-left-radius: 8px;
|
||||
display: block;
|
||||
margin: 24px 0 0 0;
|
||||
padding: 16px 24px;
|
||||
align-content: center;
|
||||
|
||||
.user-balance {
|
||||
width: 150px;
|
||||
height: 16px;
|
||||
font-size: 0.75rem;
|
||||
font-weight: bold;
|
||||
line-height: 1.33;
|
||||
color: $gray-100;
|
||||
margin-bottom: 16px;
|
||||
margin-top: -4px;
|
||||
margin-left: -4px;
|
||||
}
|
||||
|
||||
.currency-totals {
|
||||
margin-right: -8px;
|
||||
float: right;
|
||||
}
|
||||
}
|
||||
|
||||
.modal-dialog {
|
||||
width: 330px;
|
||||
width: 448px;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.badge-dialog {
|
||||
left: -8px;
|
||||
top: -8px;
|
||||
}
|
||||
|
||||
.avatar {
|
||||
@@ -212,8 +286,71 @@
|
||||
margin: 0 auto;
|
||||
}
|
||||
|
||||
.owned {
|
||||
height: 32px;
|
||||
width: 141px;
|
||||
margin-top: -36px;
|
||||
margin-left: 153px;
|
||||
padding-top: 6px;
|
||||
background-color: $gray-600;
|
||||
border-bottom-right-radius: 4px;
|
||||
border-bottom-left-radius: 4px;
|
||||
display: block;
|
||||
text-align: center;
|
||||
position: relative;
|
||||
z-index: 1;
|
||||
|
||||
.owned-text {
|
||||
font-size: 0.75rem;
|
||||
font-weight: bold;
|
||||
line-height: 1.71;
|
||||
}
|
||||
|
||||
.user-amount {
|
||||
font-weight: normal !important;
|
||||
}
|
||||
}
|
||||
|
||||
.item {
|
||||
width: 141px;
|
||||
height: 147px;
|
||||
border-top-left-radius: 4px;
|
||||
border-top-right-radius: 4px;
|
||||
border-bottom-right-radius: 0px;
|
||||
border-bottom-left-radius: 0px;
|
||||
cursor: default;
|
||||
}
|
||||
|
||||
.item-content {
|
||||
transform: scale(1.45, 1.45);
|
||||
top: -25.67px;
|
||||
left: 1px;
|
||||
|
||||
&.shop_gem {
|
||||
transform: scale(1.45, 1.45);
|
||||
top: -2px;
|
||||
left: 0px;
|
||||
}
|
||||
}
|
||||
|
||||
.title {
|
||||
height: 28px;
|
||||
color: $gray-10;
|
||||
font-size: 1.25rem;
|
||||
margin-top: 25px;
|
||||
}
|
||||
|
||||
.item-notes {
|
||||
margin-top: 8px;
|
||||
padding-left: 48.5px;
|
||||
padding-right: 48.5px;
|
||||
line-height: 1.71;
|
||||
font-size: 0.875rem;
|
||||
}
|
||||
|
||||
.content {
|
||||
text-align: center;
|
||||
width: 448px;
|
||||
}
|
||||
|
||||
.item-wrapper {
|
||||
@@ -221,15 +358,22 @@
|
||||
}
|
||||
|
||||
.inner-content {
|
||||
margin: 33px auto auto;
|
||||
width: 282px;
|
||||
margin: 32px auto auto;
|
||||
}
|
||||
|
||||
.btn-primary {
|
||||
margin-top: 16px;
|
||||
}
|
||||
|
||||
.purchase-amount {
|
||||
margin-top: 24px;
|
||||
margin-top: 0px;
|
||||
|
||||
.how-many-to-buy {
|
||||
margin-bottom: 16px;
|
||||
font-weight: bold !important;
|
||||
}
|
||||
|
||||
.number-increment {
|
||||
margin-top: 16px;
|
||||
}
|
||||
|
||||
.box {
|
||||
@@ -255,31 +399,105 @@
|
||||
}
|
||||
}
|
||||
}
|
||||
.no-more-gems {
|
||||
color: $yellow-5;
|
||||
font-size: 0.875em;
|
||||
line-height: 1.33;
|
||||
margin: 16px 48px 0 48px;
|
||||
}
|
||||
|
||||
span.svg-icon.inline.icon-32 {
|
||||
height: 32px;
|
||||
width: 32px;
|
||||
|
||||
// for cost icon of a single item
|
||||
span.svg-icon.inline.icon-24 {
|
||||
display: inline-block;
|
||||
height: 24px;
|
||||
width: 24px;
|
||||
margin-right: 4px;
|
||||
padding-top: 4px;
|
||||
}
|
||||
// for the total user cost
|
||||
span.svg-icon.total.icon-24 {
|
||||
display: inline-block;
|
||||
height: 24px;
|
||||
width: 24px;
|
||||
margin-left: 6px;
|
||||
margin-right: 8px;
|
||||
padding-top: 6px;
|
||||
}
|
||||
|
||||
vertical-align: middle;
|
||||
span.svg-icon.icon-16 {
|
||||
height: 16px;
|
||||
width: 16px;
|
||||
}
|
||||
|
||||
.close-icon {
|
||||
color: $gray-200;
|
||||
stroke-width: 0px;
|
||||
|
||||
&:hover {
|
||||
color: $gray-100;
|
||||
}
|
||||
}
|
||||
|
||||
.attributes-group {
|
||||
margin: 32px;
|
||||
border-radius: 4px;
|
||||
line-height: 1.71;
|
||||
font-size: 0.875;
|
||||
}
|
||||
|
||||
.attributesGrid {
|
||||
margin-top: 28px;
|
||||
border-radius: 2px;
|
||||
background-color: $gray-500;
|
||||
}
|
||||
|
||||
.item-cost {
|
||||
display: inline-flex;
|
||||
margin: 16px 0;
|
||||
align-items: center;
|
||||
height: 40px;
|
||||
}
|
||||
|
||||
.cost {
|
||||
width: 28px;
|
||||
height: 32px;
|
||||
font-size: 24px;
|
||||
display: inline-block;
|
||||
font-family: sans-serif;
|
||||
font-size: 1.25rem;
|
||||
font-weight: bold;
|
||||
line-height: 1.33;
|
||||
|
||||
vertical-align: middle;
|
||||
padding: 6px 20px;
|
||||
line-height: 1.4;
|
||||
border-radius: 20px;
|
||||
|
||||
&.gems {
|
||||
color: $gems-color;
|
||||
color: $green-10;
|
||||
background-color: rgba(36, 204, 143, 0.15);
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
&.gold {
|
||||
color: $gold-color;
|
||||
color: $yellow-5;
|
||||
background-color: rgba(255, 190, 93, 0.15);
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
&.hourglasses {
|
||||
color: $hourglass-color;
|
||||
background-color: rgba(41, 149, 205, 0.15);
|
||||
align-items: center;
|
||||
}
|
||||
}
|
||||
|
||||
.total {
|
||||
font-weight: bold;
|
||||
font-size: 0.875rem;
|
||||
padding-top: 2px;
|
||||
margin-top: 4px;
|
||||
|
||||
&.gems {
|
||||
color: $green-10;
|
||||
}
|
||||
|
||||
&.gold {
|
||||
color: $yellow-5;
|
||||
}
|
||||
|
||||
&.hourglasses {
|
||||
@@ -287,62 +505,84 @@
|
||||
}
|
||||
}
|
||||
|
||||
.total-text {
|
||||
color: $gray-50;
|
||||
font-weight: bold;
|
||||
font-size: 0.875rem;
|
||||
line-height: 1.71;
|
||||
|
||||
&.gems {
|
||||
color: $green-10;
|
||||
}
|
||||
|
||||
&.gold {
|
||||
color: $yellow-5;
|
||||
}
|
||||
|
||||
&.hourglasses {
|
||||
color: $hourglass-color;
|
||||
}
|
||||
}
|
||||
|
||||
button.btn.btn-primary {
|
||||
margin-top: 24px;
|
||||
margin-bottom: 24px;
|
||||
min-width: 6rem;
|
||||
margin-top: 16px;
|
||||
padding: 4px 16px;
|
||||
height: 32px;
|
||||
|
||||
&:focus {
|
||||
border: 2px solid black;
|
||||
}
|
||||
}
|
||||
|
||||
.balance {
|
||||
width: 74px;
|
||||
height: 16px;
|
||||
font-size: 12px;
|
||||
font-weight: bold;
|
||||
line-height: 1.33;
|
||||
color: $gray-200;
|
||||
}
|
||||
.notEnough {
|
||||
pointer-events: none;
|
||||
opacity: 0.55;
|
||||
}
|
||||
|
||||
.modal-footer {
|
||||
height: 48px;
|
||||
background-color: $gray-700;
|
||||
border-bottom-right-radius: 8px;
|
||||
border-bottom-left-radius: 8px;
|
||||
display: block;
|
||||
}
|
||||
.free-rebirth {
|
||||
background-color: $yellow-5;
|
||||
color: $white;
|
||||
height: 2rem;
|
||||
line-height: 16px;
|
||||
margin: auto -1rem -1rem;
|
||||
}
|
||||
|
||||
.notEnough {
|
||||
pointer-events: none;
|
||||
opacity: 0.55;
|
||||
}
|
||||
// .pt-015 {
|
||||
// padding-top: 0.15rem;
|
||||
// }
|
||||
|
||||
.attributesGrid {
|
||||
margin-top: 8px;
|
||||
border-radius: 2px;
|
||||
background-color: $gray-500;
|
||||
|
||||
margin: 10px 0 24px;
|
||||
}
|
||||
|
||||
.gems-left {
|
||||
margin-top: .5em;
|
||||
height: 32px;
|
||||
background-color: $green-100;
|
||||
font-size: 0.75rem;
|
||||
margin-top: 24px;
|
||||
color: $green-1;
|
||||
width: 100%;
|
||||
margin-bottom: -24px;
|
||||
}
|
||||
|
||||
.free-rebirth {
|
||||
background-color: $yellow-5;
|
||||
.out-of-gems-banner {
|
||||
height: 32px;
|
||||
font-size: 0.75rem;
|
||||
margin-top: 24px;
|
||||
background-color: $yellow-100;
|
||||
color: $yellow-1;
|
||||
width: 100%;
|
||||
margin-bottom: -24px;
|
||||
}
|
||||
|
||||
.limitedTime {
|
||||
height: 32px;
|
||||
width: 446px;
|
||||
font-size: 0.75rem;
|
||||
margin: 24px 0 0 0;
|
||||
background-color: $purple-300;
|
||||
color: $white;
|
||||
height: 2rem;
|
||||
line-height: 16px;
|
||||
margin: auto -1rem -1rem;
|
||||
}
|
||||
|
||||
.pt-015 {
|
||||
padding-top: 0.15rem;
|
||||
margin-bottom: -24px;
|
||||
}
|
||||
}
|
||||
|
||||
</style>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
@@ -370,6 +610,8 @@ import svgGem from '@/assets/svg/gem.svg';
|
||||
import svgHourglasses from '@/assets/svg/hourglass.svg';
|
||||
import svgClock from '@/assets/svg/clock.svg';
|
||||
import svgWhiteClock from '@/assets/svg/clock-white.svg';
|
||||
import svgPositive from '@/assets/svg/positive.svg';
|
||||
import svgNegative from '@/assets/svg/negative.svg';
|
||||
|
||||
import BalanceInfo from './balanceInfo.vue';
|
||||
import PinBadge from '@/components/ui/pinBadge';
|
||||
@@ -377,6 +619,7 @@ import CountdownBanner from './countdownBanner';
|
||||
import currencyMixin from './_currencyMixin';
|
||||
import notifications from '@/mixins/notifications';
|
||||
import buyMixin from '@/mixins/buy';
|
||||
import numberIncrement from '@/components/shared/numberIncrement';
|
||||
|
||||
import { mapState } from '@/libs/store';
|
||||
|
||||
@@ -407,14 +650,17 @@ export default {
|
||||
Avatar,
|
||||
PinBadge,
|
||||
CountdownBanner,
|
||||
numberIncrement,
|
||||
},
|
||||
mixins: [buyMixin, currencyMixin, notifications, numberInvalid, spellsMixin],
|
||||
props: {
|
||||
// eslint-disable-next-line vue/require-default-prop
|
||||
item: {
|
||||
type: Object,
|
||||
},
|
||||
priceType: {
|
||||
type: String,
|
||||
default: '',
|
||||
},
|
||||
withPin: {
|
||||
type: Boolean,
|
||||
@@ -433,10 +679,14 @@ export default {
|
||||
hourglasses: svgHourglasses,
|
||||
clock: svgClock,
|
||||
whiteClock: svgWhiteClock,
|
||||
positive: svgPositive,
|
||||
negative: svgNegative,
|
||||
}),
|
||||
|
||||
selectedAmountToBuy: 1,
|
||||
selectedAmount: 1,
|
||||
isPinned: false,
|
||||
quantity: 1,
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
@@ -474,6 +724,11 @@ export default {
|
||||
return planGemLimits.convCap
|
||||
+ this.user.purchased.plan.consecutive.gemCapExtra - this.user.purchased.plan.gemsBought;
|
||||
},
|
||||
totalGems () {
|
||||
if (!this.user.purchased.plan) return 0;
|
||||
return planGemLimits.convCap
|
||||
+ this.user.purchased.plan.consecutive.gemCapExtra;
|
||||
},
|
||||
attemptingToPurchaseMoreGemsThanAreLeft () {
|
||||
if (this.item && this.item.key && this.item.key === 'gem' && this.selectedAmountToBuy > this.gemsLeft) return true;
|
||||
return false;
|
||||
@@ -490,6 +745,9 @@ export default {
|
||||
endDate () {
|
||||
return moment(this.item.event.end);
|
||||
},
|
||||
totalOwned () {
|
||||
return this.user.items[this.item.purchaseType][this.item.key] || 0;
|
||||
},
|
||||
},
|
||||
watch: {
|
||||
item: function itemChanged () {
|
||||
@@ -500,7 +758,9 @@ export default {
|
||||
methods: {
|
||||
onChange ($event) {
|
||||
this.$emit('change', $event);
|
||||
this.selectedAmountToBuy = 1;
|
||||
},
|
||||
|
||||
buyItem () {
|
||||
// @TODO: I think we should buying to the items.
|
||||
// Turn the items into classes, and use polymorphism
|
||||
@@ -597,6 +857,7 @@ export default {
|
||||
}
|
||||
},
|
||||
hideDialog () {
|
||||
this.selectedAmountToBuy = 1;
|
||||
this.$root.$emit('bv::hide::modal', 'buy-modal');
|
||||
},
|
||||
getPriceClass () {
|
||||
|
||||
@@ -16,9 +16,6 @@
|
||||
|
||||
.limitedTime {
|
||||
height: 32px;
|
||||
width: calc(100% + 30px);
|
||||
margin: 0 -15px; // the modal content has its own padding
|
||||
|
||||
font-size: 12px;
|
||||
line-height: 1.33;
|
||||
text-align: center;
|
||||
|
||||
@@ -146,6 +146,7 @@
|
||||
</style>
|
||||
|
||||
<script>
|
||||
import find from 'lodash/find';
|
||||
import _filter from 'lodash/filter';
|
||||
import _map from 'lodash/map';
|
||||
import _throttle from 'lodash/throttle';
|
||||
@@ -225,7 +226,7 @@ export default {
|
||||
user: 'user.data',
|
||||
userStats: 'user.data.stats',
|
||||
userItems: 'user.data.items',
|
||||
currentEvent: 'worldState.data.currentEvent',
|
||||
currentEventList: 'worldState.data.currentEventList',
|
||||
}),
|
||||
market () {
|
||||
return shops.getMarketShop(this.user);
|
||||
@@ -292,15 +293,16 @@ export default {
|
||||
return Object.values(this.viewOptions).some(g => g.selected);
|
||||
},
|
||||
imageURLs () {
|
||||
if (!this.currentEvent || !this.currentEvent.season) {
|
||||
const currentEvent = find(this.currentEventList, event => Boolean(event.season));
|
||||
if (!currentEvent) {
|
||||
return {
|
||||
background: 'url(/static/npc/normal/market_background.png)',
|
||||
npc: 'url(/static/npc/normal/market_banner_npc.png)',
|
||||
};
|
||||
}
|
||||
return {
|
||||
background: `url(/static/npc/${this.currentEvent.season}/market_background.png)`,
|
||||
npc: `url(/static/npc/${this.currentEvent.season}/market_banner_npc.png)`,
|
||||
background: `url(/static/npc/${currentEvent.season}/market_background.png)`,
|
||||
npc: `url(/static/npc/${currentEvent.season}/market_banner_npc.png)`,
|
||||
};
|
||||
},
|
||||
},
|
||||
|
||||
@@ -4,9 +4,9 @@
|
||||
:hide-header="true"
|
||||
@change="onChange($event)"
|
||||
>
|
||||
<div class="close">
|
||||
<div>
|
||||
<span
|
||||
class="svg-icon inline icon-10"
|
||||
class="svg-icon close-icon icon-16 color"
|
||||
aria-hidden="true"
|
||||
@click="hideDialog()"
|
||||
v-html="icons.close"
|
||||
@@ -14,60 +14,73 @@
|
||||
</div>
|
||||
<div
|
||||
v-if="item"
|
||||
class="content"
|
||||
class="content bordered-item"
|
||||
>
|
||||
<div class="inner-content">
|
||||
<item
|
||||
class="flat"
|
||||
class="flat bordered-item"
|
||||
:item="item"
|
||||
:item-content-class="itemContextToSell.itemClass"
|
||||
:show-popover="false"
|
||||
>
|
||||
<countBadge
|
||||
slot="itemBadge"
|
||||
:show="true"
|
||||
:count="itemContextToSell.itemCount"
|
||||
/>
|
||||
</item>
|
||||
/>
|
||||
<span class="owned">
|
||||
{{ $t('owned') }}: <span class="user-amount">{{ itemContextToSell.itemCount }}</span>
|
||||
</span>
|
||||
<h4 class="title">
|
||||
{{ itemContextToSell.itemName }}
|
||||
</h4>
|
||||
<div v-if="item.key === 'Saddle'">
|
||||
<div class="text">
|
||||
<div class="item-notes">
|
||||
{{ item.sellWarningNote() }}
|
||||
</div>
|
||||
<br>
|
||||
</div>
|
||||
<div v-else>
|
||||
<div>
|
||||
<div class="text">
|
||||
<div class="item-notes">
|
||||
{{ item.notes() }}
|
||||
</div>
|
||||
<div>
|
||||
<b class="how-many-to-sell">{{ $t('howManyToSell') }}</b>
|
||||
<div class="item-cost">
|
||||
<span class="cost gold">
|
||||
<span
|
||||
class="svg-icon inline icon-24"
|
||||
aria-hidden="true"
|
||||
v-html="icons.gold"
|
||||
></span>
|
||||
<span>{{ item.value }}</span>
|
||||
</span>
|
||||
</div>
|
||||
<div>
|
||||
<b-input
|
||||
v-model="selectedAmountToSell"
|
||||
class="itemsToSell"
|
||||
type="number"
|
||||
:max="itemContextToSell.itemCount"
|
||||
min="1"
|
||||
step="1"
|
||||
@keyup.native="preventNegative($event)"
|
||||
/>
|
||||
<span
|
||||
class="svg-icon inline icon-32"
|
||||
class="how-many-to-sell"
|
||||
>
|
||||
{{ $t('howManyToSell') }}
|
||||
</span>
|
||||
</div>
|
||||
<div>
|
||||
<number-increment
|
||||
@updateQuantity="selectedAmountToSell = $event"
|
||||
/>
|
||||
</div>
|
||||
<div class="total-row">
|
||||
<span class="total-text">
|
||||
{{ $t('sendTotal') }}
|
||||
</span>
|
||||
<span
|
||||
class="svg-icon total icon-24"
|
||||
aria-hidden="true"
|
||||
v-html="icons.gold"
|
||||
></span>
|
||||
<span class="value">{{ item.value }}</span>
|
||||
<span class="total-text gold">
|
||||
{{ item.value * selectedAmountToSell }}
|
||||
</span>
|
||||
</div>
|
||||
<button
|
||||
class="btn btn-primary"
|
||||
:disabled="selectedAmountToSell > itemContextToSell.itemCount"
|
||||
@click="sellItems()"
|
||||
>
|
||||
{{ $t('sell') }}
|
||||
{{ $t('sellItems') }}
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
@@ -77,8 +90,10 @@
|
||||
slot="modal-footer"
|
||||
class="clearfix"
|
||||
>
|
||||
<span class="balance float-left">{{ $t('yourBalance') }}</span>
|
||||
<balanceInfo class="float-right" />
|
||||
<span class="user-balance float-left">{{ $t('yourBalance') }}</span>
|
||||
<balanceInfo
|
||||
class="float-right currency-totals"
|
||||
/>
|
||||
</div>
|
||||
</b-modal>
|
||||
</template>
|
||||
@@ -95,51 +110,13 @@
|
||||
}
|
||||
|
||||
.modal-dialog {
|
||||
width: 330px;
|
||||
width: 448px;
|
||||
}
|
||||
|
||||
.content {
|
||||
text-align: center;
|
||||
|
||||
}
|
||||
.inner-content {
|
||||
margin: 33px auto auto;
|
||||
width: 282px;
|
||||
}
|
||||
|
||||
span.svg-icon.inline.icon-32 {
|
||||
height: 32px;
|
||||
width: 32px;
|
||||
|
||||
margin-left: 24px;
|
||||
margin-right: 8px;
|
||||
|
||||
vertical-align: middle;
|
||||
}
|
||||
|
||||
.value {
|
||||
width: 28px;
|
||||
height: 32px;
|
||||
font-size: 24px;
|
||||
font-weight: bold;
|
||||
line-height: 1.33;
|
||||
color: #df911e;
|
||||
|
||||
vertical-align: middle;
|
||||
}
|
||||
|
||||
button.btn.btn-primary {
|
||||
margin-top: 24px;
|
||||
margin-bottom: 24px;
|
||||
}
|
||||
|
||||
.balance {
|
||||
width: 74px;
|
||||
height: 16px;
|
||||
font-size: 12px;
|
||||
font-weight: bold;
|
||||
line-height: 1.33;
|
||||
color: $gray-200;
|
||||
.modal-body {
|
||||
padding-left: 0px;
|
||||
padding-right: 0px;
|
||||
padding-bottom: 0px;
|
||||
}
|
||||
|
||||
.modal-footer {
|
||||
@@ -148,29 +125,215 @@
|
||||
border-bottom-right-radius: 8px;
|
||||
border-bottom-left-radius: 8px;
|
||||
display: block;
|
||||
margin: 24px 0 0;
|
||||
padding: 16px 24px;
|
||||
align-content: center;
|
||||
|
||||
.user-balance {
|
||||
width: 150px;
|
||||
height: 16px;
|
||||
font-size: 0.75rem;
|
||||
font-weight: bold;
|
||||
line-height: 1.33;
|
||||
color: $gray-100;
|
||||
margin-bottom: 16px;
|
||||
margin-top: -4px;
|
||||
margin-left: -4px;
|
||||
}
|
||||
|
||||
.currency-totals {
|
||||
margin-right: -8px;
|
||||
float: right;
|
||||
}
|
||||
}
|
||||
|
||||
.how-many-to-sell {
|
||||
margin-bottom: 16px;
|
||||
.content {
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.inner-content {
|
||||
margin: 33px auto auto;
|
||||
width: 282px;
|
||||
}
|
||||
|
||||
.owned {
|
||||
font-size: 0.75rem;
|
||||
font-weight: bold;
|
||||
line-height: 1.33;
|
||||
background-color: $gray-600;
|
||||
padding: 8px 8px;
|
||||
border-bottom-right-radius: 4px;
|
||||
border-bottom-left-radius: 4px;
|
||||
display: block;
|
||||
width: 141px;
|
||||
margin-left: 71px;
|
||||
margin-top: -48px;
|
||||
position: relative;
|
||||
z-index: 1;
|
||||
|
||||
.user-amount {
|
||||
font-weight: normal !important;
|
||||
}
|
||||
}
|
||||
|
||||
.item-wrapper {
|
||||
margin-top: -10px;
|
||||
}
|
||||
|
||||
.item {
|
||||
width: 141px;
|
||||
height: 147px;
|
||||
border-top-left-radius: 4px;
|
||||
border-top-right-radius: 4px;
|
||||
border-bottom-right-radius: 0px;
|
||||
border-bottom-left-radius: 0px;
|
||||
cursor: default;
|
||||
margin-top: 8px;
|
||||
}
|
||||
|
||||
.item-content {
|
||||
transform: scale(1.45, 1.45);
|
||||
top: -25px;
|
||||
left: 1px;
|
||||
}
|
||||
|
||||
.title {
|
||||
color: $gray-10;
|
||||
font-size: 1.25rem;
|
||||
margin-top: 26px;
|
||||
margin-bottom: 0px;
|
||||
}
|
||||
|
||||
.item-notes {
|
||||
margin-top: 12px;
|
||||
line-height: 1.71;
|
||||
font-size: 0.875rem;
|
||||
}
|
||||
|
||||
// for cost icon of a single item
|
||||
span.svg-icon.inline.icon-24 {
|
||||
display: inline-block;
|
||||
height: 24px;
|
||||
width: 24px;
|
||||
margin-right: 4px;
|
||||
padding-top: 4px;
|
||||
}
|
||||
// for the total user cost
|
||||
span.svg-icon.total.icon-24 {
|
||||
display: inline-block;
|
||||
height: 24px;
|
||||
width: 24px;
|
||||
margin-left: 6px;
|
||||
margin-right: 8px;
|
||||
padding-top: 6px;
|
||||
}
|
||||
|
||||
span.svg-icon.icon-16 {
|
||||
height: 16px;
|
||||
width: 16px;
|
||||
}
|
||||
|
||||
.close-icon {
|
||||
color: $gray-200;
|
||||
stroke-width: 0px;
|
||||
cursor: pointer;
|
||||
|
||||
&:hover {
|
||||
color: $gray-100;
|
||||
}
|
||||
}
|
||||
|
||||
.item-cost {
|
||||
display: inline-flex;
|
||||
margin: 16px 0;
|
||||
align-items: center;
|
||||
height: 40px;
|
||||
}
|
||||
|
||||
.cost {
|
||||
display: inline-block;
|
||||
font-family: sans-serif;
|
||||
font-size: 1.25rem;
|
||||
font-weight: bold;
|
||||
padding: 6px 20px;
|
||||
line-height: 1.4;
|
||||
border-radius: 20px;
|
||||
|
||||
&.gold {
|
||||
color: $yellow-5;
|
||||
background-color: rgba(255, 190, 93, 0.15);
|
||||
align-items: center;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.how-many-to-sell {
|
||||
font-weight: bold !important;
|
||||
}
|
||||
|
||||
.number-increment {
|
||||
margin-top: 16px;
|
||||
}
|
||||
|
||||
.total-row {
|
||||
font-weight: bold;
|
||||
font-size: 0.875rem;
|
||||
margin-top: 16px;
|
||||
|
||||
&.gold {
|
||||
color: $yellow-5;
|
||||
}
|
||||
}
|
||||
|
||||
.total-text {
|
||||
color: $gray-50;
|
||||
font-weight: bold;
|
||||
font-size: 0.875rem;
|
||||
line-height: 1.71;
|
||||
|
||||
&.gold {
|
||||
color: $yellow-5;
|
||||
}
|
||||
}
|
||||
|
||||
button.btn.btn-primary {
|
||||
margin-top: 16px;
|
||||
padding: 4px 16px;
|
||||
height: 32px;
|
||||
|
||||
&:focus {
|
||||
border: 2px solid black;
|
||||
}
|
||||
|
||||
.balance {
|
||||
width: 74px;
|
||||
height: 16px;
|
||||
font-size: 12px;
|
||||
font-weight: bold;
|
||||
line-height: 1.33;
|
||||
color: $gray-200;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
</style>
|
||||
|
||||
<script>
|
||||
import svgClose from '@/assets/svg/close.svg';
|
||||
import svgGold from '@/assets/svg/gold.svg';
|
||||
import svgGem from '@/assets/svg/gem.svg';
|
||||
import svgPositive from '@/assets/svg/positive.svg';
|
||||
import svgNegative from '@/assets/svg/negative.svg';
|
||||
|
||||
import BalanceInfo from '../balanceInfo.vue';
|
||||
import Item from '@/components/inventory/item';
|
||||
import CountBadge from '@/components/ui/countBadge';
|
||||
import numberIncrement from '@/components/shared/numberIncrement';
|
||||
|
||||
export default {
|
||||
components: {
|
||||
BalanceInfo,
|
||||
Item,
|
||||
CountBadge,
|
||||
numberIncrement,
|
||||
},
|
||||
data () {
|
||||
return {
|
||||
@@ -181,6 +344,8 @@ export default {
|
||||
close: svgClose,
|
||||
gold: svgGold,
|
||||
gem: svgGem,
|
||||
svgPositive,
|
||||
svgNegative,
|
||||
}),
|
||||
};
|
||||
},
|
||||
@@ -211,6 +376,10 @@ export default {
|
||||
this.selectedAmountToSell = 0;
|
||||
}
|
||||
},
|
||||
maxOwned () {
|
||||
const maxOwned = this.itemContextToSell.itemCount;
|
||||
return maxOwned;
|
||||
},
|
||||
sellItems () {
|
||||
if (!Number.isInteger(Number(this.selectedAmountToSell))) {
|
||||
this.selectedAmountToSell = 0;
|
||||
|
||||
@@ -33,6 +33,22 @@
|
||||
v-if="!item.locked"
|
||||
class="purchase-amount"
|
||||
>
|
||||
<div class="item-cost">
|
||||
<span
|
||||
class="cost"
|
||||
:class="priceType"
|
||||
>
|
||||
<span
|
||||
class="svg-icon inline icon-24"
|
||||
aria-hidden="true"
|
||||
v-html="icons[priceType]"
|
||||
>
|
||||
</span>
|
||||
<span
|
||||
:class="priceType"
|
||||
>{{ item.value }}</span>
|
||||
</span>
|
||||
</div>
|
||||
<div class="how-many-to-buy">
|
||||
<strong>{{ $t('howManyToBuy') }}</strong>
|
||||
</div>
|
||||
@@ -42,24 +58,25 @@
|
||||
>
|
||||
{{ item.addlNotes }}
|
||||
</div>
|
||||
<div class="box">
|
||||
<input
|
||||
v-model.number="selectedAmountToBuy"
|
||||
class="form-control"
|
||||
type="number"
|
||||
min="0"
|
||||
step="1"
|
||||
>
|
||||
<div>
|
||||
<number-increment
|
||||
@updateQuantity="selectedAmountToBuy = $event"
|
||||
/>
|
||||
</div>
|
||||
<div class="total-row">
|
||||
<span class="total-text">
|
||||
{{ $t('sendTotal') }}
|
||||
</span>
|
||||
<span
|
||||
class="svg-icon inline icon-20"
|
||||
aria-hidden="true"
|
||||
v-html="currencyIcon"
|
||||
></span>
|
||||
<span
|
||||
class="total"
|
||||
:class="priceType"
|
||||
>{{ item.value * selectedAmountToBuy }}</span>
|
||||
</div>
|
||||
<span
|
||||
class="svg-icon inline icon-32"
|
||||
aria-hidden="true"
|
||||
v-html="currencyIcon"
|
||||
></span>
|
||||
<span
|
||||
class="value"
|
||||
:class="priceType"
|
||||
>{{ item.value }}</span>
|
||||
</div>
|
||||
<button
|
||||
v-if="priceType === 'gems'
|
||||
@@ -72,7 +89,7 @@
|
||||
</button>
|
||||
<button
|
||||
v-else
|
||||
class="btn btn-primary"
|
||||
class="btn btn-primary mb-4"
|
||||
:class="{'notEnough': !enoughCurrency(priceType, item.value * selectedAmountToBuy)}"
|
||||
:disabled="numberInvalid"
|
||||
@click="buyItem()"
|
||||
@@ -112,6 +129,39 @@
|
||||
margin-top: 1rem;
|
||||
}
|
||||
|
||||
.modal-body {
|
||||
padding-left: 0px;
|
||||
padding-right: 0px;
|
||||
padding-bottom: 0px;
|
||||
}
|
||||
|
||||
.modal-footer {
|
||||
height: 48px;
|
||||
background-color: $gray-700;
|
||||
border-bottom-right-radius: 8px;
|
||||
border-bottom-left-radius: 8px;
|
||||
display: block;
|
||||
padding: 16px 24px;
|
||||
align-content: center;
|
||||
|
||||
.user-balance {
|
||||
width: 150px;
|
||||
height: 16px;
|
||||
font-size: 0.75rem;
|
||||
font-weight: bold;
|
||||
line-height: 1.33;
|
||||
color: $gray-100;
|
||||
margin-bottom: 16px;
|
||||
margin-top: -4px;
|
||||
margin-left: -4px;
|
||||
}
|
||||
|
||||
.currency-totals {
|
||||
margin-right: -8px;
|
||||
float: right;
|
||||
}
|
||||
}
|
||||
|
||||
.modal-dialog {
|
||||
margin-top: 8%;
|
||||
width: 448px !important;
|
||||
@@ -129,8 +179,13 @@
|
||||
margin: 33px auto auto;
|
||||
}
|
||||
|
||||
.modal-body {
|
||||
padding-bottom: 0px;
|
||||
.item-notes {
|
||||
height: 48px;
|
||||
margin-top: 8px;
|
||||
padding-left: 48.5px;
|
||||
padding-right: 48.5px;
|
||||
line-height: 1.71;
|
||||
font-size: 0.875rem;
|
||||
}
|
||||
|
||||
.questInfo {
|
||||
@@ -152,16 +207,14 @@
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
span.svg-icon.inline.icon-32 {
|
||||
height: 32px;
|
||||
width: 32px;
|
||||
margin-right: 8px;
|
||||
vertical-align: middle;
|
||||
}
|
||||
|
||||
button.btn.btn-primary {
|
||||
margin-top: 24px;
|
||||
margin-bottom: 24px;
|
||||
margin-top: 14px;
|
||||
padding: 4px 16px;
|
||||
height: 32px;
|
||||
|
||||
&:focus {
|
||||
border: 2px solid black;
|
||||
}
|
||||
}
|
||||
|
||||
.balance {
|
||||
@@ -173,19 +226,6 @@
|
||||
color: $gray-200;
|
||||
}
|
||||
|
||||
.modal-footer {
|
||||
height: 48px;
|
||||
background-color: $gray-700;
|
||||
border-bottom-right-radius: 8px;
|
||||
border-bottom-left-radius: 8px;
|
||||
display: block;
|
||||
padding: 1rem 1.5rem;
|
||||
|
||||
&> * {
|
||||
margin: 0;
|
||||
}
|
||||
}
|
||||
|
||||
.notEnough {
|
||||
pointer-events: none;
|
||||
opacity: 0.55;
|
||||
@@ -198,30 +238,108 @@
|
||||
margin-bottom: 16px;
|
||||
}
|
||||
|
||||
.box {
|
||||
display: inline-block;
|
||||
width: 74px;
|
||||
height: 40px;
|
||||
border-radius: 2px;
|
||||
background-color: #ffffff;
|
||||
box-shadow: 0 2px 2px 0 rgba(26, 24, 29, 0.16), 0 1px 4px 0 rgba(26, 24, 29, 0.12);
|
||||
margin-right: 24px;
|
||||
|
||||
input {
|
||||
width: 100%;
|
||||
border: none;
|
||||
.item-cost {
|
||||
padding-bottom: 16px;
|
||||
}
|
||||
|
||||
input::-webkit-contacts-auto-fill-button {
|
||||
visibility: hidden;
|
||||
display: none !important;
|
||||
pointer-events: none;
|
||||
position: absolute;
|
||||
right: 0;
|
||||
}
|
||||
.cost {
|
||||
height: 40px;
|
||||
font-size: 1.25rem;
|
||||
font-weight: bold;
|
||||
vertical-align: middle;
|
||||
padding: 8px 20px 8px 20px;
|
||||
|
||||
&.gems {
|
||||
color: $green-10;
|
||||
background-color: rgba(36, 204, 143, 0.15);
|
||||
line-height: 1.4;
|
||||
margin: 0 0 0 -4px;
|
||||
border-radius: 20px;
|
||||
}
|
||||
|
||||
&.gold {
|
||||
color: $yellow-5;
|
||||
background-color: rgba(255, 190, 93, 0.15);
|
||||
line-height: 1.4;
|
||||
margin: 0 0 0 -4px;
|
||||
border-radius: 20px;
|
||||
}
|
||||
|
||||
&.hourglasses {
|
||||
color: $hourglass-color;
|
||||
background-color: rgba(41, 149, 205, 0.15);
|
||||
line-height: 1.4;
|
||||
margin: 0 0 0 -4px;
|
||||
border-radius: 20px;
|
||||
}
|
||||
}
|
||||
|
||||
.total-row {
|
||||
font-weight: bold;
|
||||
font-size: 0.875rem;
|
||||
margin-top: 16px;
|
||||
}
|
||||
|
||||
.total {
|
||||
font-weight: bold;
|
||||
font-size: 0.875rem;
|
||||
margin-top: 16px;
|
||||
|
||||
&.gems {
|
||||
color: $green-10;
|
||||
}
|
||||
|
||||
&.gold {
|
||||
color: $yellow-5;
|
||||
}
|
||||
|
||||
&.hourglasses {
|
||||
color: $hourglass-color;
|
||||
}
|
||||
}
|
||||
|
||||
.total-text {
|
||||
color: $gray-50;
|
||||
font-weight: bold;
|
||||
font-size: 0.875rem;
|
||||
height: 24px;
|
||||
line-height: 1.71;
|
||||
padding-right: 4px;
|
||||
|
||||
&.gems {
|
||||
color: $green-10;
|
||||
}
|
||||
|
||||
&.gold {
|
||||
color: $yellow-5;
|
||||
}
|
||||
|
||||
&.hourglasses {
|
||||
color: $hourglass-color;
|
||||
}
|
||||
}
|
||||
|
||||
span.svg-icon.inline.icon-20 {
|
||||
height: 20px;
|
||||
width: 20px;
|
||||
margin-right: 4px;
|
||||
vertical-align: middle;
|
||||
}
|
||||
|
||||
span.svg-icon.inline.icon-24 {
|
||||
height: 24px;
|
||||
width: 24px;
|
||||
margin-right: 8px;
|
||||
vertical-align: middle;
|
||||
}
|
||||
|
||||
span.svg-icon.inline.icon-32 {
|
||||
height: 32px;
|
||||
width: 32px;
|
||||
margin-right: 8px;
|
||||
vertical-align: middle;
|
||||
}
|
||||
|
||||
@media only screen and (max-width: 1000px) {
|
||||
.modal-dialog {
|
||||
max-width: 80%;
|
||||
@@ -234,9 +352,10 @@
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
<!-- <style lang="scss" scoped>
|
||||
@import '~@/assets/scss/colors.scss';
|
||||
|
||||
.value {
|
||||
@@ -260,7 +379,7 @@
|
||||
color: $hourglass-color;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
</style> -->
|
||||
|
||||
<script>
|
||||
import moment from 'moment';
|
||||
@@ -272,6 +391,8 @@ import svgExperience from '@/assets/svg/experience.svg';
|
||||
import svgGem from '@/assets/svg/gem.svg';
|
||||
import svgGold from '@/assets/svg/gold.svg';
|
||||
import svgHourglasses from '@/assets/svg/hourglass.svg';
|
||||
import svgPositive from '@/assets/svg/positive.svg';
|
||||
import svgNegative from '@/assets/svg/negative.svg';
|
||||
|
||||
import BalanceInfo from '../balanceInfo.vue';
|
||||
import currencyMixin from '../_currencyMixin';
|
||||
@@ -280,6 +401,7 @@ import buyMixin from '@/mixins/buy';
|
||||
import numberInvalid from '@/mixins/numberInvalid';
|
||||
import PinBadge from '@/components/ui/pinBadge';
|
||||
import CountdownBanner from '../countdownBanner';
|
||||
import numberIncrement from '@/components/shared/numberIncrement';
|
||||
|
||||
import questDialogContent from './questDialogContent';
|
||||
import QuestRewards from './questRewards';
|
||||
@@ -293,6 +415,7 @@ export default {
|
||||
PinBadge,
|
||||
questDialogContent,
|
||||
CountdownBanner,
|
||||
numberIncrement,
|
||||
},
|
||||
mixins: [buyMixin, currencyMixin, notifications, numberInvalid],
|
||||
props: {
|
||||
@@ -301,6 +424,7 @@ export default {
|
||||
},
|
||||
priceType: {
|
||||
type: String,
|
||||
default: '',
|
||||
},
|
||||
withPin: {
|
||||
type: Boolean,
|
||||
@@ -312,9 +436,11 @@ export default {
|
||||
clock: svgClock,
|
||||
close: svgClose,
|
||||
experience: svgExperience,
|
||||
gem: svgGem,
|
||||
gems: svgGem,
|
||||
gold: svgGold,
|
||||
hourglass: svgHourglasses,
|
||||
hourglasses: svgHourglasses,
|
||||
positive: svgPositive,
|
||||
negative: svgNegative,
|
||||
}),
|
||||
|
||||
isPinned: false,
|
||||
@@ -339,8 +465,8 @@ export default {
|
||||
},
|
||||
currencyIcon () {
|
||||
if (this.priceType === 'gold') return this.icons.gold;
|
||||
if (this.priceType === 'hourglasses') return this.icons.hourglass;
|
||||
return this.icons.gem;
|
||||
if (this.priceType === 'hourglasses') return this.icons.hourglasses;
|
||||
return this.icons.gems;
|
||||
},
|
||||
endDate () {
|
||||
return moment(this.item.event.end);
|
||||
|
||||
@@ -397,6 +397,7 @@
|
||||
</style>
|
||||
|
||||
<script>
|
||||
import find from 'lodash/find';
|
||||
import _filter from 'lodash/filter';
|
||||
import _sortBy from 'lodash/sortBy';
|
||||
import _throttle from 'lodash/throttle';
|
||||
@@ -512,7 +513,7 @@ export default {
|
||||
user: 'user.data',
|
||||
userStats: 'user.data.stats',
|
||||
userItems: 'user.data.items',
|
||||
currentEvent: 'worldState.data.currentEvent',
|
||||
currentEventList: 'worldState.data.currentEventList',
|
||||
}),
|
||||
shop () {
|
||||
return shops.getQuestShop(this.user);
|
||||
@@ -536,15 +537,16 @@ export default {
|
||||
return Object.values(this.viewOptions).some(g => g.selected);
|
||||
},
|
||||
imageURLs () {
|
||||
if (!this.currentEvent || !this.currentEvent.season) {
|
||||
const currentEvent = find(this.currentEventList, event => Boolean(event.season));
|
||||
if (!currentEvent) {
|
||||
return {
|
||||
background: 'url(/static/npc/normal/quest_shop_background.png)',
|
||||
npc: 'url(/static/npc/normal/quest_shop_npc.png)',
|
||||
};
|
||||
}
|
||||
return {
|
||||
background: `url(/static/npc/${this.currentEvent.season}/quest_shop_background.png)`,
|
||||
npc: `url(/static/npc/${this.currentEvent.season}/quest_shop_npc.png)`,
|
||||
background: `url(/static/npc/${currentEvent.season}/quest_shop_background.png)`,
|
||||
npc: `url(/static/npc/${currentEvent.season}/quest_shop_npc.png)`,
|
||||
};
|
||||
},
|
||||
},
|
||||
|
||||
@@ -33,17 +33,17 @@
|
||||
|
||||
h3 {
|
||||
color: $gray-10;
|
||||
margin-bottom: 0.25rem;
|
||||
margin-bottom: 4pxrem;
|
||||
}
|
||||
|
||||
.quest-image {
|
||||
margin: 0 auto;
|
||||
margin-bottom: 1em;
|
||||
margin-top: 1.5em;
|
||||
margin-bottom: 16px;
|
||||
margin-top: 24px;
|
||||
}
|
||||
|
||||
.text {
|
||||
margin-bottom: 1rem;
|
||||
margin: 16px 16px;
|
||||
overflow-y: auto;
|
||||
text-overflow: ellipsis;
|
||||
}
|
||||
@@ -54,10 +54,10 @@
|
||||
line-height: 1.71;
|
||||
color: $gray-50;
|
||||
text-align: center;
|
||||
margin-bottom: 0.5rem;
|
||||
margin-bottom: 8px;
|
||||
|
||||
::v-deep .user-label {
|
||||
font-size: 14px;
|
||||
font-size: 0.875rem;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -177,9 +177,6 @@ export default {
|
||||
@import '~@/assets/scss/colors.scss';
|
||||
|
||||
.quest-rewards {
|
||||
margin-left: -1rem;
|
||||
margin-right: -1rem;
|
||||
|
||||
background-color: $gray-700;
|
||||
}
|
||||
|
||||
|
||||
@@ -7,13 +7,19 @@
|
||||
<br>
|
||||
<p class="text-center">
|
||||
<button
|
||||
id="buttonClearBrowserData"
|
||||
class="btn btn-lg btn-danger"
|
||||
popover-trigger="mouseover"
|
||||
:popover="$t('localStorageClearExplanation')"
|
||||
@click="clearLocalStorage()"
|
||||
>
|
||||
{{ $t('localStorageClear') }}
|
||||
</button>
|
||||
<b-popover
|
||||
target="buttonClearBrowserData"
|
||||
triggers="hover focus"
|
||||
placement="right"
|
||||
:prevent-overflow="false"
|
||||
:content="$t('localStorageClearExplanation')"
|
||||
/>
|
||||
</p>
|
||||
<br>
|
||||
<p v-html="$t('localStorageTryNext', localStorageTryNext) "></p>
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
<div class="container-fluid">
|
||||
<h1>{{ $t('communityGuidelines') }}</h1>
|
||||
<hr>
|
||||
<p>{{ $t('lastUpdated') }} July 28, 2021</p>
|
||||
<p>{{ $t('lastUpdated') }} February 8, 2023</p>
|
||||
<h2 id="welcome">
|
||||
{{ $t('commGuideHeadingWelcome') }}
|
||||
</h2>
|
||||
@@ -21,6 +21,7 @@
|
||||
<p v-html="$t('commGuidePara016')"></p>
|
||||
<p v-html="$t('commGuidePara017')"></p>
|
||||
<ul>
|
||||
<li v-html="$t('commGuideList01F')"></li>
|
||||
<li v-html="$t('commGuideList01A')"></li>
|
||||
<li v-html="$t('commGuideList01B')"></li>
|
||||
<li v-html="$t('commGuideList01C')"></li>
|
||||
@@ -32,6 +33,7 @@
|
||||
<img src="~@/assets/images/community-guidelines/publicSpaces.png">
|
||||
</div>
|
||||
<ul>
|
||||
<li v-html="$t('commGuideList02N')"></li>
|
||||
<li v-html="$t('commGuideList02A')"></li>
|
||||
<li v-html="$t('commGuideList02B')"></li>
|
||||
<li v-html="$t('commGuideList02G')"></li>
|
||||
@@ -147,10 +149,9 @@
|
||||
<li>
|
||||
{{ $t('commGuideList10A') }}
|
||||
<ul>
|
||||
<li>{{ $t('commGuideList10A1') }}</li>
|
||||
<li v-html="$t('commGuideList10A1')"></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li v-html="$t('commGuideList10C')"></li>
|
||||
<li v-html="$t('commGuideList10D')"></li>
|
||||
<li v-html="$t('commGuideList10F')"></li>
|
||||
</ul>
|
||||
@@ -176,50 +177,53 @@
|
||||
<h2 id="meet-the-mods">
|
||||
{{ $t('commGuideHeadingMeet') }}
|
||||
</h2>
|
||||
<p v-html="$t('commGuidePara006')"></p>
|
||||
<p v-html="$t('commGuidePara007')"></p>
|
||||
<p v-html="$t('commGuidePara008')"></p>
|
||||
<p v-html="$t('commGuidePara009')"></p>
|
||||
<div class="media align-items-center">
|
||||
<img src="~@/assets/images/community-guidelines/staff.png">
|
||||
<div class="media-body">
|
||||
<ul>
|
||||
<li>{{ $t('commGuideAKA', {habitName: 'Viirus', realName: 'Phillip'}) }}</li>
|
||||
<li>
|
||||
{{ $t('commGuideAKA', {habitName: 'heyeilatan', realName: 'Natalie'}) }}
|
||||
({{ $t('commGuideOnGitHub', {gitHubName: 'CuriousMagpie'}) }})
|
||||
- Web Developer
|
||||
</li>
|
||||
<li>
|
||||
{{ $t('commGuideAKA', {habitName: 'Viirus', realName: 'Phillip'}) }}
|
||||
- Mobile Developer
|
||||
</li>
|
||||
<li>
|
||||
{{ $t('commGuideAKA', {habitName: 'redphoenix', realName: 'Vicky'}) }}
|
||||
({{ $t('commGuideOnGitHub', {gitHubName: 'veeeeeee'}) }})
|
||||
- Co-Founder
|
||||
</li>
|
||||
<li>
|
||||
{{ $t('commGuideAKA', {habitName: 'Beffymaroo', realName: 'Beth'}) }}
|
||||
- Art, Community Management, Many Hats
|
||||
</li>
|
||||
<li>
|
||||
{{ $t('commGuideAKA', {habitName: 'SabreCat', realName: 'Sabe'}) }}
|
||||
- Web Developer
|
||||
</li>
|
||||
<li>
|
||||
{{ $t('commGuideAKA', {habitName: 'Apollo', realName: 'Tressley'}) }}
|
||||
- Designer
|
||||
</li>
|
||||
<li>
|
||||
{{ $t('commGuideAKA', {habitName: 'Piyo', realName: 'Sara'}) }}
|
||||
- Mobile Designer
|
||||
</li>
|
||||
<li>{{ $t('commGuideAKA', {habitName: 'Beffymaroo', realName: 'Beth'}) }}</li>
|
||||
<li>{{ $t('commGuideAKA', {habitName: 'SabreCat', realName: 'Sabe'}) }}</li>
|
||||
<li>{{ $t('commGuideAKA', {habitName: 'Apollo', realName: 'Tressley'}) }}</li>
|
||||
<li>{{ $t('commGuideAKA', {habitName: 'Piyo', realName: 'Sara'}) }}</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
<p v-html="$t('commGuidePara010')"></p>
|
||||
<div class="media align-items-center">
|
||||
<img src="~@/assets/images/community-guidelines/moderators.png">
|
||||
<div class="media-body">
|
||||
<p v-html="$t('commGuidePara011')"></p>
|
||||
<ul>
|
||||
<li>Dewines</li>
|
||||
<li>Nakonana</li>
|
||||
<li>Cantras</li>
|
||||
<li>Alys (LadyAlys {{ $t('commGuidePara011c') }})</li>
|
||||
<li>Fox_town</li>
|
||||
<li>MaybeSteveRogers</li>
|
||||
<li>shanaqui</li>
|
||||
<li>deilann (not yet pictured)</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
<p v-html="$t('commGuidePara012')"></p>
|
||||
<p v-html="$t('commGuidePara013')"></p>
|
||||
<p>
|
||||
{{ $t('commGuidePara014') }}<br>
|
||||
<em>
|
||||
Lemoness, lefnire, Slappybag, litenull, Shaner, Bobbyroberts99, wc8,
|
||||
Breadstrings, Megan, Blade, and Daniel the Bard
|
||||
Breadstrings, Megan, Blade, Daniel the Bard, deilann, shanaqui, Nakonana,
|
||||
Dewines, Alys, Fox_town, MaybeSteveRogers, and Cantras.
|
||||
|
||||
</em>
|
||||
</p>
|
||||
<h2 id="final">
|
||||
@@ -240,6 +244,7 @@
|
||||
</ul>
|
||||
<p v-html="$t('commGuidePara069')"></p>
|
||||
<ul class="list-2col list-unstyled">
|
||||
<li>Beffymaroo</li>
|
||||
<li>Breadstrings</li>
|
||||
<li>Draayder</li>
|
||||
<li>Kiwibot</li>
|
||||
|
||||
@@ -17,6 +17,19 @@
|
||||
class="faq-question"
|
||||
>
|
||||
<h2
|
||||
v-once
|
||||
v-if="index === 0"
|
||||
>
|
||||
{{ $t('general') }}
|
||||
</h2>
|
||||
<h2
|
||||
v-once
|
||||
v-if="entry.heading === 'party-with-friends'"
|
||||
id="parties"
|
||||
>
|
||||
{{ $t('parties') }}
|
||||
</h2>
|
||||
<h3
|
||||
v-once
|
||||
v-b-toggle="entry.heading"
|
||||
role="tab"
|
||||
@@ -24,7 +37,7 @@
|
||||
@click="handleClick($event)"
|
||||
>
|
||||
{{ entry.question }}
|
||||
</h2>
|
||||
</h3>
|
||||
<b-collapse
|
||||
:id="entry.heading"
|
||||
:visible="isVisible(entry.heading)"
|
||||
@@ -49,25 +62,36 @@
|
||||
</template>
|
||||
|
||||
<style lang='scss' scoped>
|
||||
.card-body {
|
||||
margin-bottom: 1em;
|
||||
h2 {
|
||||
color: #34313a;
|
||||
border-bottom: 1px solid #e1e0e3;
|
||||
margin-top: 24px;
|
||||
padding-bottom: 16px;
|
||||
}
|
||||
|
||||
.faq-question h2 {
|
||||
cursor: pointer;
|
||||
}
|
||||
.faq-question {
|
||||
a {
|
||||
text-decoration: none;
|
||||
color: #4F2A93;
|
||||
}
|
||||
|
||||
.faq-question .card-body {
|
||||
padding: 0;
|
||||
}
|
||||
h3 {
|
||||
font-size: 16px;
|
||||
font-weight: normal;
|
||||
line-height: 1.75;
|
||||
cursor: pointer;
|
||||
|
||||
.static-wrapper .faq-question h2 {
|
||||
margin: 0 0 16px 0;
|
||||
}
|
||||
&:hover {
|
||||
text-decoration: underline;
|
||||
}
|
||||
}
|
||||
|
||||
.faq-question a {
|
||||
text-decoration: none;
|
||||
color: #4F2A93;
|
||||
.card-body {
|
||||
padding: 0;
|
||||
font-size: 14px;
|
||||
line-height: 1.71;
|
||||
margin-bottom: 1em;
|
||||
}
|
||||
}
|
||||
|
||||
@media only screen and (max-width: 768px) {
|
||||
|
||||
@@ -354,6 +354,9 @@
|
||||
|
||||
<style lang='scss'>
|
||||
@import '~@/assets/scss/static.scss';
|
||||
#front .form-text a {
|
||||
color: $white !important;
|
||||
}
|
||||
</style>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
@@ -362,10 +365,6 @@
|
||||
@import url('https://fonts.googleapis.com/css?family=Varela+Round');
|
||||
|
||||
#front {
|
||||
.form-text a {
|
||||
color: $white !important;
|
||||
}
|
||||
|
||||
.container-fluid {
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
@@ -165,10 +165,6 @@ export default {
|
||||
question: 'pkQuestion7',
|
||||
answer: 'pkAnswer7',
|
||||
},
|
||||
{
|
||||
question: 'pkQuestion8',
|
||||
answer: 'pkAnswer8',
|
||||
},
|
||||
],
|
||||
});
|
||||
},
|
||||
|
||||
@@ -198,10 +198,6 @@
|
||||
color: $purple-200;
|
||||
}
|
||||
|
||||
li, p {
|
||||
font-size: 16px;
|
||||
}
|
||||
|
||||
.media img {
|
||||
margin: 1em;
|
||||
}
|
||||
|
||||
@@ -81,7 +81,6 @@
|
||||
</span>
|
||||
<a
|
||||
v-if="assignedUsersCount > 1 && !showStatus"
|
||||
class="blue-10"
|
||||
@click="showStatus = !showStatus"
|
||||
>
|
||||
{{ $t('viewStatus') }}
|
||||
@@ -128,10 +127,6 @@
|
||||
padding-top: 0.25rem;
|
||||
z-index: 9;
|
||||
height: 24px;
|
||||
|
||||
.blue-10 {
|
||||
color: $blue-10;
|
||||
}
|
||||
}
|
||||
|
||||
.completion-row {
|
||||
|
||||
@@ -355,6 +355,7 @@ import Task from './task';
|
||||
import ClearCompletedTodos from './clearCompletedTodos';
|
||||
import buyMixin from '@/mixins/buy';
|
||||
import sync from '@/mixins/sync';
|
||||
import externalLinks from '@/mixins/externalLinks';
|
||||
import { mapState, mapActions, mapGetters } from '@/libs/store';
|
||||
import shopItem from '../shops/shopItem';
|
||||
import BuyQuestModal from '@/components/shops/quests/buyQuestModal.vue';
|
||||
@@ -384,7 +385,7 @@ export default {
|
||||
shopItem,
|
||||
draggable,
|
||||
},
|
||||
mixins: [buyMixin, notifications, sync],
|
||||
mixins: [buyMixin, notifications, sync, externalLinks],
|
||||
// @TODO Set default values for props
|
||||
// allows for better control of props values
|
||||
// allows for better control of where this component is called
|
||||
@@ -520,7 +521,12 @@ export default {
|
||||
// Get Category Filter Labels
|
||||
this.typeFilters = getFilterLabels(this.type, this.challenge);
|
||||
// Set default filter for task column
|
||||
this.activateFilter(this.type);
|
||||
|
||||
if (this.challenge) {
|
||||
this.activateFilter(this.type);
|
||||
} else {
|
||||
this.activateFilter(this.type, this.user.preferences.tasks.activeFilter[this.type], true);
|
||||
}
|
||||
},
|
||||
mounted () {
|
||||
this.setColumnBackgroundVisibility();
|
||||
@@ -534,6 +540,10 @@ export default {
|
||||
if (this.activeFilter.label !== 'complete2') return;
|
||||
this.loadCompletedTodos();
|
||||
});
|
||||
this.handleExternalLinks();
|
||||
},
|
||||
updated () {
|
||||
this.handleExternalLinks();
|
||||
},
|
||||
beforeDestroy () {
|
||||
this.$root.$off('buyModal::boughtItem');
|
||||
@@ -656,7 +666,7 @@ export default {
|
||||
taskSummary (task) {
|
||||
this.$emit('taskSummary', task);
|
||||
},
|
||||
activateFilter (type, filter = '') {
|
||||
activateFilter (type, filter = '', skipSave = false) {
|
||||
// Needs a separate API call as this data may not reside in store
|
||||
if (type === 'todo' && filter === 'complete2') {
|
||||
if (this.group && this.group._id) {
|
||||
@@ -672,14 +682,16 @@ export default {
|
||||
// as default filter for daily
|
||||
// and set the filter as 'due' only when the component first
|
||||
// loads and not on subsequent reloads.
|
||||
if (
|
||||
type === 'daily' && filter === '' && !this.challenge
|
||||
&& this.user.preferences.dailyDueDefaultView
|
||||
) {
|
||||
if (type === 'daily' && filter === '' && !this.challenge) {
|
||||
filter = 'due'; // eslint-disable-line no-param-reassign
|
||||
}
|
||||
|
||||
this.activeFilter = getActiveFilter(type, filter, this.challenge);
|
||||
|
||||
if (!skipSave && !this.challenge) {
|
||||
const propertyToUpdate = `preferences.tasks.activeFilter.${type}`;
|
||||
this.$store.dispatch('user:set', { [propertyToUpdate]: filter });
|
||||
}
|
||||
},
|
||||
setColumnBackgroundVisibility () {
|
||||
this.$nextTick(() => {
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
'groupTask': task.group.id,
|
||||
'task-not-editable': !teamManagerAccess,
|
||||
'task-not-scoreable': showTaskLockIcon,
|
||||
'link-exempt': !isChallengeTask && !isGroupTask,
|
||||
}, `type_${task.type}`
|
||||
]"
|
||||
@click="castEnd($event, task)"
|
||||
@@ -31,6 +32,9 @@
|
||||
'task-not-scoreable': showTaskLockIcon,
|
||||
}, controlClass.up.inner]"
|
||||
tabindex="0"
|
||||
role="button"
|
||||
:aria-label="$t('scoreUp')"
|
||||
:aria-disabled="showTaskLockIcon || (!task.up && !showTaskLockIcon)"
|
||||
@click="score('up')"
|
||||
@keypress.enter="score('up')"
|
||||
>
|
||||
@@ -62,6 +66,7 @@
|
||||
controlClass.inner,
|
||||
]"
|
||||
tabindex="0"
|
||||
role="checkbox"
|
||||
@click="score(showCheckIcon ? 'down' : 'up' )"
|
||||
@keypress.enter="score(showCheckIcon ? 'down' : 'up' )"
|
||||
>
|
||||
@@ -240,7 +245,7 @@
|
||||
>
|
||||
<div
|
||||
v-b-tooltip.hover.bottom="$t('dueDate')"
|
||||
class="svg-icon calendar"
|
||||
class="svg-icon calendar my-auto"
|
||||
v-html="icons.calendar"
|
||||
></div>
|
||||
<span>{{ formatDueDate() }}</span>
|
||||
@@ -358,6 +363,9 @@
|
||||
'task-not-scoreable': showTaskLockIcon,
|
||||
}, controlClass.down.inner]"
|
||||
tabindex="0"
|
||||
role="button"
|
||||
:aria-label="$t('scoreDown')"
|
||||
:aria-disabled="showTaskLockIcon || (!task.down && !showTaskLockIcon)"
|
||||
@click="score('down')"
|
||||
@keypress.enter="score('down')"
|
||||
>
|
||||
@@ -700,7 +708,7 @@
|
||||
|
||||
.icons {
|
||||
margin-top: 4px;
|
||||
color: $gray-300;
|
||||
color: $gray-100;
|
||||
font-style: normal;
|
||||
|
||||
&-right {
|
||||
@@ -759,7 +767,7 @@
|
||||
}
|
||||
|
||||
.due-overdue {
|
||||
color: $red-50;
|
||||
color: $maroon-10;
|
||||
}
|
||||
|
||||
.calendar.svg-icon {
|
||||
@@ -898,7 +906,7 @@
|
||||
}
|
||||
</style>
|
||||
<!-- eslint-enable max-len -->
|
||||
|
||||
<!-- eslint-disable-next-line vue/component-tags-order -->
|
||||
<script>
|
||||
import moment from 'moment';
|
||||
import { v4 as uuid } from 'uuid';
|
||||
@@ -1125,13 +1133,13 @@ export default {
|
||||
return moment.duration(endOfDueDate.diff(endOfToday));
|
||||
},
|
||||
checkIfOverdue () {
|
||||
return this.calculateTimeTillDue().asDays() <= 0;
|
||||
return this.calculateTimeTillDue().asDays() < 0;
|
||||
},
|
||||
formatDueDate () {
|
||||
const timeTillDue = this.calculateTimeTillDue();
|
||||
const dueIn = timeTillDue.asDays() === 0 ? this.$t('today') : timeTillDue.humanize(true);
|
||||
|
||||
return this.task.date && this.$t('dueIn', { dueIn });
|
||||
if (moment().isSame(this.task.date, 'day')) {
|
||||
return this.$t('today');
|
||||
}
|
||||
return moment(this.task.date).format(this.user.preferences.dateFormat.toUpperCase());
|
||||
},
|
||||
edit (e, task) {
|
||||
if (this.isRunningYesterdailies) return;
|
||||
|
||||
@@ -593,7 +593,6 @@
|
||||
a:not(.dropdown-item) {
|
||||
font-size: 12px;
|
||||
line-height: 1.33;
|
||||
color: $blue-10;
|
||||
}
|
||||
|
||||
.modal-dialog.modal-sm {
|
||||
|
||||
@@ -276,7 +276,6 @@
|
||||
a {
|
||||
font-size: 12px;
|
||||
line-height: 1.33;
|
||||
color: $blue-10;
|
||||
margin-top: 4px;
|
||||
|
||||
&:focus, &:hover, &:active {
|
||||
|
||||
@@ -83,6 +83,7 @@
|
||||
<script>
|
||||
import moment from 'moment';
|
||||
import { mapState } from '@/libs/store';
|
||||
import externalLinks from '@/mixins/externalLinks';
|
||||
import scoreTask from '@/mixins/scoreTask';
|
||||
import sync from '@/mixins/sync';
|
||||
import Task from './task';
|
||||
@@ -93,7 +94,7 @@ export default {
|
||||
Task,
|
||||
LoadingSpinner,
|
||||
},
|
||||
mixins: [scoreTask, sync],
|
||||
mixins: [externalLinks, scoreTask, sync],
|
||||
props: {
|
||||
yesterDailies: {
|
||||
type: Array,
|
||||
@@ -108,6 +109,11 @@ export default {
|
||||
dueDate: moment().subtract(1, 'days'),
|
||||
};
|
||||
},
|
||||
updated () {
|
||||
window.setTimeout(() => {
|
||||
this.handleExternalLinks();
|
||||
}, 500);
|
||||
},
|
||||
computed: {
|
||||
...mapState({ user: 'user.data' }),
|
||||
tasksByType () {
|
||||
|
||||
46
website/client/src/components/ui/closeX.vue
Normal file
@@ -0,0 +1,46 @@
|
||||
<template>
|
||||
<div
|
||||
class="modal-close"
|
||||
@click="$emit('close')"
|
||||
>
|
||||
<div
|
||||
class="svg-icon svg-close color"
|
||||
v-html="icons.close"
|
||||
>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.modal-close {
|
||||
position: absolute;
|
||||
right: 16px;
|
||||
top: 16px;
|
||||
cursor: pointer;
|
||||
|
||||
.svg-close {
|
||||
width: 18px;
|
||||
height: 18px;
|
||||
vertical-align: middle;
|
||||
opacity: 0.75;
|
||||
|
||||
&:hover {
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
<script>
|
||||
import close from '@/assets/svg/close.svg';
|
||||
|
||||
export default {
|
||||
data () {
|
||||
return {
|
||||
icons: Object.freeze({
|
||||
close,
|
||||
}),
|
||||
};
|
||||
},
|
||||
};
|
||||
</script>
|
||||
@@ -133,7 +133,7 @@
|
||||
font-size: 12px;
|
||||
font-weight: bold;
|
||||
text-align: center;
|
||||
color: $gray-400;
|
||||
color: $white !important;
|
||||
text-decoration: none !important;
|
||||
border-bottom: 2px solid transparent;
|
||||
padding: 0.5rem;
|
||||
|
||||
@@ -182,7 +182,6 @@
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</template>
|
||||
|
||||
@@ -296,10 +295,6 @@
|
||||
width: 50%;
|
||||
}
|
||||
|
||||
.challenge-link, .user-link {
|
||||
color: $blue-10 !important;
|
||||
}
|
||||
|
||||
.entry-action {
|
||||
b {
|
||||
text-transform: uppercase;
|
||||
|
||||
@@ -2,13 +2,13 @@
|
||||
<router-link
|
||||
v-if="displayName"
|
||||
v-b-tooltip.hover.top="tierTitle"
|
||||
class="leader user-link"
|
||||
class="leader user-link d-flex"
|
||||
:to="{'name': 'userProfile', 'params': {'userId': id}}"
|
||||
:class="levelStyle()"
|
||||
>
|
||||
{{ displayName }}
|
||||
<div
|
||||
class="svg-icon"
|
||||
class="svg-icon icon-12"
|
||||
v-html="tierIcon()"
|
||||
></div>
|
||||
</router-link>
|
||||
@@ -37,10 +37,15 @@
|
||||
color: $gray-50;
|
||||
}
|
||||
|
||||
&[class*="tier"] .svg-icon {
|
||||
margin-top: 5px;
|
||||
}
|
||||
&.npc .svg-icon {
|
||||
margin-top: 4px;
|
||||
}
|
||||
|
||||
.svg-icon {
|
||||
width: 10px;
|
||||
display: inline-block;
|
||||
margin-left: .5em;
|
||||
margin-left: 6px;
|
||||
|
||||
&:empty {
|
||||
display: none;
|
||||
|
||||