Improved challenge layout.

This commit is contained in:
Marvin Rabe
2018-05-01 16:10:22 +02:00
parent 5faf00d489
commit 4e4181a394
5 changed files with 294 additions and 261 deletions

View File

@@ -6,7 +6,7 @@
challenge-member-progress-modal(:memberId='progressMemberId', :challengeId='challenge._id') challenge-member-progress-modal(:memberId='progressMemberId', :challengeId='challenge._id')
.col-12.col-md-8.standard-page .col-12.col-md-8.standard-page
.row .row
.col-12.col-md-8 .col-12.col-md-6
h1(v-markdown='challenge.name') h1(v-markdown='challenge.name')
div div
strong(v-once) {{$t('createdBy')}}: strong(v-once) {{$t('createdBy')}}:
@@ -19,7 +19,7 @@
// span {{challenge.endDate}} // span {{challenge.endDate}}
.tags .tags
span.tag(v-for='tag in challenge.tags') {{tag}} span.tag(v-for='tag in challenge.tags') {{tag}}
.col-12.col-md-4 .col-12.col-md-6.text-right
.box(@click="showMemberModal()") .box(@click="showMemberModal()")
.svg-icon.member-icon(v-html="icons.memberIcon") .svg-icon.member-icon(v-html="icons.memberIcon")
| {{challenge.memberCount}} | {{challenge.memberCount}}
@@ -29,10 +29,10 @@
| {{challenge.prize}} | {{challenge.prize}}
.details(v-once) {{$t('prize')}} .details(v-once) {{$t('prize')}}
.row.challenge-actions .row.challenge-actions
.col-12.col-md-7.offset-md-5 .col-12.col-md-6
span.view-progress strong.view-progress {{ $t('viewProgressOf') }}
strong {{ $t('viewProgressOf') }}
member-search-dropdown(:text="$t('selectParticipant')", :members='members', :challengeId='challengeId', @member-selected='openMemberProgressModal') member-search-dropdown(:text="$t('selectParticipant')", :members='members', :challengeId='challengeId', @member-selected='openMemberProgressModal')
.col-12.col-md-6.text-right
span(v-if='isLeader || isAdmin') span(v-if='isLeader || isAdmin')
b-dropdown.create-dropdown(:text="$t('addTaskToChallenge')", :variant="'success'") b-dropdown.create-dropdown(:text="$t('addTaskToChallenge')", :variant="'success'")
b-dropdown-item(v-for="type in columns", :key="type", @click="createTask(type)") b-dropdown-item(v-for="type in columns", :key="type", @click="createTask(type)")
@@ -56,24 +56,25 @@
v-on:editTask="editTask", v-on:editTask="editTask",
v-if='tasksByType[column].length > 0') v-if='tasksByType[column].length > 0')
.col-12.col-md-4.sidebar.standard-page .col-12.col-md-4.sidebar.standard-page
.acitons .button-container(v-if='canJoin')
div(v-if='canJoin') button.btn.btn-success(v-once, @click='joinChallenge()') {{$t('joinChallenge')}}
button.btn.btn-success(v-once, @click='joinChallenge()') {{$t('joinChallenge')}} .button-container(v-if='isLeader || isAdmin')
div(v-if='isMember') button.btn.btn-primary(v-once, @click='edit()') {{$t('editChallenge')}}
button.btn.btn-danger(v-once, @click='leaveChallenge()') {{$t('leaveChallenge')}} .button-container(v-if='isLeader || isAdmin')
div(v-if='isLeader || isAdmin') button.btn.btn-primary(v-once, @click='cloneChallenge()') {{$t('clone')}}
button.btn.btn-secondary(v-once, @click='edit()') {{$t('editChallenge')}} .button-container(v-if='isLeader || isAdmin')
div(v-if='isLeader || isAdmin') button.btn.btn-primary(v-once, @click='exportChallengeCsv()') {{$t('exportChallengeCsv')}}
button.btn.btn-danger(v-once, @click='closeChallenge()') {{$t('endChallenge')}} .button-container(v-if='isLeader || isAdmin')
div(v-if='isLeader || isAdmin') button.btn.btn-danger(v-once, @click='closeChallenge()') {{$t('endChallenge')}}
button.btn.btn-secondary(v-once, @click='exportChallengeCsv()') {{$t('exportChallengeCsv')}} sidebar-section(:title="$t('challengeSummary')")
div(v-if='isLeader || isAdmin')
button.btn.btn-secondary(v-once, @click='cloneChallenge()') {{$t('clone')}}
.description-section
h2 {{$t('challengeSummary')}}
p(v-markdown='challenge.summary') p(v-markdown='challenge.summary')
h2 {{$t('challengeDescription')}} sidebar-section(
:title="$t('challengeDescription')"
:last="true"
)
p(v-markdown='challenge.description') p(v-markdown='challenge.description')
.text-center(v-if='isMember')
button.btn.btn-danger(v-once, @click='leaveChallenge()') {{$t('leaveChallenge')}}
</template> </template>
<style lang='scss' scoped> <style lang='scss' scoped>
@@ -91,6 +92,14 @@
margin-left: .5em; margin-left: .5em;
} }
.button-container {
margin-bottom: 1em;
button {
width: 100%;
}
}
.calendar-icon { .calendar-icon {
width: 12px; width: 12px;
display: inline-block; display: inline-block;
@@ -138,23 +147,12 @@
} }
} }
.acitons {
width: 100%;
div, button {
width: 60%;
margin: 0 auto;
margin-bottom: .5em;
text-align: center;
}
}
.description-section { .description-section {
margin-top: 2em; margin-top: 2em;
} }
.challenge-actions { .challenge-actions {
margin-top: 1em; margin-bottom: 1em;
.view-progress { .view-progress {
margin-right: .5em; margin-right: .5em;
@@ -162,14 +160,6 @@
} }
</style> </style>
<style>
.create-dropdown button {
width: 100%;
font-size: 16px !important;
font-weight: bold !important;
}
</style>
<script> <script>
const TASK_KEYS_TO_REMOVE = ['_id', 'completed', 'date', 'dateCompleted', 'history', 'id', 'streak', 'createdAt', 'challenge']; const TASK_KEYS_TO_REMOVE = ['_id', 'completed', 'date', 'dateCompleted', 'history', 'id', 'streak', 'createdAt', 'challenge'];
@@ -189,6 +179,7 @@ import challengeModal from './challengeModal';
import challengeMemberProgressModal from './challengeMemberProgressModal'; import challengeMemberProgressModal from './challengeMemberProgressModal';
import challengeMemberSearchMixin from 'client/mixins/challengeMemberSearch'; import challengeMemberSearchMixin from 'client/mixins/challengeMemberSearch';
import leaveChallengeModal from './leaveChallengeModal'; import leaveChallengeModal from './leaveChallengeModal';
import sidebarSection from '../sidebarSection';
import taskDefaults from 'common/script/libs/taskDefaults'; import taskDefaults from 'common/script/libs/taskDefaults';
@@ -208,6 +199,7 @@ export default {
challengeModal, challengeModal,
challengeMemberProgressModal, challengeMemberProgressModal,
memberSearchDropdown, memberSearchDropdown,
sidebarSection,
TaskColumn: Column, TaskColumn: Column,
TaskModal, TaskModal,
}, },

View File

@@ -6,25 +6,51 @@ div
.svg-icon.challenge-icon(v-html="icons.challengeIcon") .svg-icon.challenge-icon(v-html="icons.challengeIcon")
h4(v-once) {{ $t('haveNoChallenges') }} h4(v-once) {{ $t('haveNoChallenges') }}
p(v-once) {{ $t('challengeDetails') }} p(v-once) {{ $t('challengeDetails') }}
router-link.title(:to="{ name: 'challenge', params: { challengeId: challenge._id } }", v-for='challenge in challenges',:key='challenge._id') button.btn.btn-secondary(@click='createChallenge()') {{ $t('createChallenge') }}
.col-12.challenge-item template(v-else)
.row router-link.title(:to="{ name: 'challenge', params: { challengeId: challenge._id } }", v-for='challenge in challenges',:key='challenge._id')
.col-9 .col-12.challenge-item
router-link.title(:to="{ name: 'challenge', params: { challengeId: challenge._id } }") .row
strong(v-markdown='challenge.name') .col-9
p(v-markdown='challenge.summary || challenge.name') router-link.title(:to="{ name: 'challenge', params: { challengeId: challenge._id } }")
div strong(v-markdown='challenge.name')
.svg-icon.member-icon(v-html="icons.memberIcon") p(v-markdown='challenge.summary || challenge.name')
.member-count {{challenge.memberCount}} div
.col-3 .svg-icon.member-icon(v-html="icons.memberIcon")
div .member-count {{challenge.memberCount}}
span.svg-icon.gem(v-html="icons.gemIcon") .col-3
span.prize {{challenge.prize}} div
div.prize-title Prize span.svg-icon.gem(v-html="icons.gemIcon")
.col-12.text-center span.prize {{challenge.prize}}
button.btn.btn-secondary(@click='createChallenge()') {{ $t('createChallenge') }} div.prize-title Prize
.col-12.text-center
button.btn.btn-secondary(@click='createChallenge()') {{ $t('createChallenge') }}
</template> </template>
<style lang="scss" scoped>
@import '~client/assets/scss/colors.scss';
.no-quest-section {
padding: 2em;
color: $gray-300;
h4 {
color: $gray-300;
}
p {
margin-bottom: 2em;
}
.svg-icon {
height: 30px;
width: 30px;
margin: 0 auto;
margin-bottom: 2em;
}
}
</style>
<style scoped> <style scoped>
.title { .title {
color: #4E4A57; color: #4E4A57;
@@ -80,57 +106,57 @@ div
</style> </style>
<script> <script>
import challengeModal from './challengeModal'; import challengeModal from './challengeModal';
import { mapState } from 'client/libs/store'; import {mapState} from 'client/libs/store';
import markdownDirective from 'client/directives/markdown'; import markdownDirective from 'client/directives/markdown';
import challengeIcon from 'assets/svg/challenge.svg'; import challengeIcon from 'assets/svg/challenge.svg';
import gemIcon from 'assets/svg/gem.svg'; import gemIcon from 'assets/svg/gem.svg';
import memberIcon from 'assets/svg/member-icon.svg'; import memberIcon from 'assets/svg/member-icon.svg';
export default { export default {
props: ['groupId'], props: ['groupId'],
components: { components: {
challengeModal, challengeModal,
}, },
computed: { computed: {
...mapState({user: 'user.data'}), ...mapState({user: 'user.data'}),
}, },
data () { data() {
return { return {
challenges: [], challenges: [],
icons: Object.freeze({ icons: Object.freeze({
challengeIcon, challengeIcon,
memberIcon, memberIcon,
gemIcon, gemIcon,
}), }),
groupIdForChallenges: '', groupIdForChallenges: '',
}; };
}, },
directives: { directives: {
markdown: markdownDirective, markdown: markdownDirective,
}, },
mounted () { mounted() {
this.loadChallenges();
},
watch: {
async groupId () {
this.loadChallenges(); this.loadChallenges();
}, },
}, watch: {
methods: { async groupId() {
async loadChallenges () { this.loadChallenges();
this.groupIdForChallenges = this.groupId; },
if (this.groupId === 'party' && this.user.party._id) this.groupIdForChallenges = this.user.party._id;
this.challenges = await this.$store.dispatch('challenges:getGroupChallenges', {groupId: this.groupIdForChallenges});
}, },
createChallenge () { methods: {
this.$root.$emit('bv::show::modal', 'challenge-modal'); async loadChallenges() {
this.groupIdForChallenges = this.groupId;
if (this.groupId === 'party' && this.user.party._id) this.groupIdForChallenges = this.user.party._id;
this.challenges = await this.$store.dispatch('challenges:getGroupChallenges', {groupId: this.groupIdForChallenges});
},
createChallenge() {
this.$root.$emit('bv::show::modal', 'challenge-modal');
},
challengeCreated(challenge) {
if (challenge.group._id !== this.groupIdForChallenges) return;
this.challenges.push(challenge);
},
}, },
challengeCreated (challenge) { };
if (challenge.group._id !== this.groupIdForChallenges) return;
this.challenges.push(challenge);
},
},
};
</script> </script>

View File

@@ -61,48 +61,17 @@
// @TODO: V2 button.btn.btn-primary(v-once, v-if='!isLeader') {{$t('messageGuildLeader')}} // Suggest making the button visible to the leader too - useful for them to test how the feature works or to send a note to themself. -- Alys // @TODO: V2 button.btn.btn-primary(v-once, v-if='!isLeader') {{$t('messageGuildLeader')}} // Suggest making the button visible to the leader too - useful for them to test how the feature works or to send a note to themself. -- Alys
.button-container .button-container
// @TODO: V2 button.btn.btn-primary(v-once, v-if='isMember && !isParty') {{$t('donateGems')}} // Suggest removing the isMember restriction - it's okay if non-members donate to a public guild. Also probably allow it for parties if parties can buy imagery. -- Alys // @TODO: V2 button.btn.btn-primary(v-once, v-if='isMember && !isParty') {{$t('donateGems')}} // Suggest removing the isMember restriction - it's okay if non-members donate to a public guild. Also probably allow it for parties if parties can buy imagery. -- Alys
.section-header(v-if='isParty') quest-sidebar-section(:group='group', v-if='isParty')
quest-sidebar-section(@toggle='toggleQuestSection', :show='sections.quest', :group='group') sidebar-section(:title="$t('guildSummary')", v-if='!isParty')
.section-header(v-if='!isParty') p(v-markdown='group.summary')
.row sidebar-section(:title="$t('groupDescription')")
.col-10 p(v-markdown='group.description')
h3(v-once) {{ $t('guildSummary') }} sidebar-section(
.col-2 :title="$t('challenges')",
.toggle-up(@click="sections.summary = !sections.summary", v-if="sections.summary") :tooltip="isParty ? $t('challengeDetails') : $t('privateDescription')"
.svg-icon(v-html="icons.upIcon") :last="true"
.toggle-down(@click="sections.summary = !sections.summary", v-if="!sections.summary") )
.svg-icon(v-html="icons.downIcon") group-challenges(:groupId='searchId')
.section(v-if="sections.summary")
p(v-markdown='group.summary')
.section-header
.row
.col-10
h3 {{ $t('groupDescription') }}
.col-2
.toggle-up(@click="sections.description = !sections.description", v-if="sections.description")
.svg-icon(v-html="icons.upIcon")
.toggle-down(@click="sections.description = !sections.description", v-if="!sections.description")
.svg-icon(v-html="icons.downIcon")
.section(v-if="sections.description")
p(v-markdown='group.description')
.section-header.challenge
.row
.col-10.information-header
h3(v-once)
| {{ $t('challenges') }}
#groupPrivateDescOrChallengeInfo.icon.tooltip-wrapper(:title="isParty ? $t('challengeDetails') : $t('privateDescription')")
.svg-icon(v-html='icons.information')
b-tooltip(
:title="isParty ? $t('challengeDetails') : $t('privateDescription')",
target="groupPrivateDescOrChallengeInfo",
)
.col-2
.toggle-up(@click="sections.challenges = !sections.challenges", v-if="sections.challenges")
.svg-icon(v-html="icons.upIcon")
.toggle-down(@click="sections.challenges = !sections.challenges", v-if="!sections.challenges")
.svg-icon(v-html="icons.downIcon")
.section(v-if="sections.challenges")
group-challenges(:groupId='searchId')
div.text-center div.text-center
button.btn.btn-danger(v-if='isMember', @click='clickLeave()') {{ isParty ? $t('leaveParty') : $t('leaveGroup') }} button.btn.btn-danger(v-if='isMember', @click='clickLeave()') {{ isParty ? $t('leaveParty') : $t('leaveGroup') }}
</template> </template>
@@ -270,29 +239,6 @@
margin-right: .3em; margin-right: .3em;
} }
.information-header {
h3, .tooltip-wrapper {
display: inline-block;
}
.tooltip-wrapper {
width: 15px;
margin-left: 1.2em;
}
}
.section-header {
border-top: 1px solid #e1e0e3;
margin-top: 1em;
padding-top: 1em;
}
.section-header.challenge {
border-bottom: 1px solid #e1e0e3;
margin-bottom: 1em;
padding-bottom: 1em;
}
.hr { .hr {
width: 100%; width: 100%;
height: 20px; height: 20px;
@@ -334,6 +280,7 @@ import groupGemsModal from 'client/components/groups/groupGemsModal';
import questSidebarSection from 'client/components/groups/questSidebarSection'; import questSidebarSection from 'client/components/groups/questSidebarSection';
import markdownDirective from 'client/directives/markdown'; import markdownDirective from 'client/directives/markdown';
import communityGuidelines from './communityGuidelines'; import communityGuidelines from './communityGuidelines';
import sidebarSection from '../sidebarSection';
import deleteIcon from 'assets/svg/delete.svg'; import deleteIcon from 'assets/svg/delete.svg';
import copyIcon from 'assets/svg/copy.svg'; import copyIcon from 'assets/svg/copy.svg';
@@ -342,10 +289,7 @@ import likedIcon from 'assets/svg/liked.svg';
import reportIcon from 'assets/svg/report.svg'; import reportIcon from 'assets/svg/report.svg';
import gemIcon from 'assets/svg/gem.svg'; import gemIcon from 'assets/svg/gem.svg';
import questIcon from 'assets/svg/quest.svg'; import questIcon from 'assets/svg/quest.svg';
import informationIcon from 'assets/svg/information.svg';
import questBackground from 'assets/svg/quest-background-border.svg'; import questBackground from 'assets/svg/quest-background-border.svg';
import upIcon from 'assets/svg/up.svg';
import downIcon from 'assets/svg/down.svg';
import goldGuildBadgeIcon from 'assets/svg/gold-guild-badge-small.svg'; import goldGuildBadgeIcon from 'assets/svg/gold-guild-badge-small.svg';
import silverGuildBadgeIcon from 'assets/svg/silver-guild-badge-small.svg'; import silverGuildBadgeIcon from 'assets/svg/silver-guild-badge-small.svg';
import bronzeGuildBadgeIcon from 'assets/svg/bronze-guild-badge-small.svg'; import bronzeGuildBadgeIcon from 'assets/svg/bronze-guild-badge-small.svg';
@@ -365,6 +309,7 @@ export default {
groupGemsModal, groupGemsModal,
questSidebarSection, questSidebarSection,
communityGuidelines, communityGuidelines,
sidebarSection,
}, },
directives: { directives: {
markdown: markdownDirective, markdown: markdownDirective,
@@ -381,22 +326,13 @@ export default {
gem: gemIcon, gem: gemIcon,
liked: likedIcon, liked: likedIcon,
questIcon, questIcon,
information: informationIcon,
questBackground, questBackground,
upIcon,
downIcon,
goldGuildBadgeIcon, goldGuildBadgeIcon,
silverGuildBadgeIcon, silverGuildBadgeIcon,
bronzeGuildBadgeIcon, bronzeGuildBadgeIcon,
}), }),
members: [], members: [],
selectedQuest: {}, selectedQuest: {},
sections: {
quest: true,
summary: true,
description: true,
challenges: true,
},
newMessage: '', newMessage: '',
coords: { coords: {
TOP: 0, TOP: 0,
@@ -698,9 +634,6 @@ export default {
showGroupGems () { showGroupGems () {
this.$root.$emit('bv::show::modal', 'group-gems-modal'); this.$root.$emit('bv::show::modal', 'group-gems-modal');
}, },
toggleQuestSection () {
this.sections.quest = !this.sections.quest;
},
}, },
}; };
</script> </script>

View File

@@ -1,74 +1,65 @@
<template lang="pug"> <template lang="pug">
div sidebar-section(:title="$t('questDetailsTitle')")
.row .row.no-quest-section(v-if='!onPendingQuest && !onActiveQuest')
.col-10 .col-12.text-center
h3(v-once) {{ $t('questDetailsTitle') }} .svg-icon(v-html="icons.questIcon")
h4(v-once) {{ $t('youAreNotOnQuest') }}
p(v-once) {{ $t('questDescription') }}
button.btn.btn-secondary(v-once, @click="openStartQuestModal()") {{ $t('startAQuest') }}
.row.quest-active-section(v-if='onPendingQuest && !onActiveQuest')
.col-2 .col-2
.toggle-up(@click="toggle()", v-if="show") .quest(:class='`inventory_quest_scroll_${questData.key}`')
.svg-icon(v-html="icons.upIcon") .col-6.titles
.toggle-down(@click="toggle()", v-if="!show") strong {{ questData.text() }}
.svg-icon(v-html="icons.downIcon") p {{acceptedCount}} / {{group.memberCount}}
.section(v-if="show") .col-4
.row.no-quest-section(v-if='!onPendingQuest && !onActiveQuest') button.btn.btn-secondary(@click="openQuestDetails()") {{ $t('details') }}
.col-12.text-center .row.quest-active-section.quest-invite(v-if='user.party.quest && user.party.quest.RSVPNeeded')
.svg-icon(v-html="icons.questIcon") span {{ $t('wouldYouParticipate') }}
h4(v-once) {{ $t('youAreNotOnQuest') }} button.btn.btn-primary.accept(@click='questAccept(group._id)') {{$t('accept')}}
p(v-once) {{ $t('questDescription') }} button.btn.btn-primary.reject(@click='questReject(group._id)') {{$t('reject')}}
button.btn.btn-secondary(v-once, @click="openStartQuestModal()") {{ $t('startAQuest') }} .row.quest-active-section(v-if='!onPendingQuest && onActiveQuest')
.row.quest-active-section(v-if='onPendingQuest && !onActiveQuest') .col-12.text-center
.col-2 .quest-boss(:class="'quest_' + questData.key")
.quest(:class='`inventory_quest_scroll_${questData.key}`') h3(v-once) {{ questData.text() }}
.col-6.titles .quest-box
strong {{ questData.text() }} .collect-info(v-if='questData.collect')
p {{acceptedCount}} / {{group.memberCount}} .row(v-for='(value, key) in questData.collect')
.col-4 .col-2
button.btn.btn-secondary(@click="openQuestDetails()") {{ $t('details') }} div(:class="'quest_' + questData.key + '_' + key")
.row.quest-active-section.quest-invite(v-if='user.party.quest && user.party.quest.RSVPNeeded') .col-10
span {{ $t('wouldYouParticipate') }} strong {{value.text()}}
button.btn.btn-primary.accept(@click='questAccept(group._id)') {{$t('accept')}} .grey-progress-bar
button.btn.btn-primary.reject(@click='questReject(group._id)') {{$t('reject')}} .collect-progress-bar(:style="{width: (group.quest.progress.collect[key] / value.count) * 100 + '%'}")
.row.quest-active-section(v-if='!onPendingQuest && onActiveQuest') strong {{group.quest.progress.collect[key]}} / {{value.count}}
.col-12.text-center div.text-right {{parseFloat(user.party.quest.progress.collectedItems) || 0}} items found
.quest-boss(:class="'quest_' + questData.key") .boss-info(v-if='questData.boss')
h3(v-once) {{ questData.text() }} .row
.quest-box .col-6
.collect-info(v-if='questData.collect') h4.float-left(v-once) {{ questData.boss.name() }}
.row(v-for='(value, key) in questData.collect') .col-6
.col-2 span.float-right(v-once) {{ $t('participantsTitle') }}
div(:class="'quest_' + questData.key + '_' + key") .row
.col-10 .col-12
strong {{value.text()}} .grey-progress-bar
.grey-progress-bar .boss-health-bar(:style="{width: (group.quest.progress.hp / questData.boss.hp) * 100 + '%'}")
.collect-progress-bar(:style="{width: (group.quest.progress.collect[key] / value.count) * 100 + '%'}") .row.boss-details
strong {{group.quest.progress.collect[key]}} / {{value.count}} .col-6
div.text-right {{parseFloat(user.party.quest.progress.collectedItems) || 0}} items found span.float-left
.boss-info(v-if='questData.boss') | {{ Math.ceil(parseFloat(group.quest.progress.hp) * 100) / 100 }} / {{ parseFloat(questData.boss.hp).toFixed(2) }}
.row // current boss hp uses ceil so you don't underestimate damage needed to end quest
.col-6(v-if='userIsOnQuest')
// @TODO: Why do we not sync quest progress on the group doc? Each user could have different progress.
span.float-right {{ user.party.quest.progress.up | floor(10) }} {{ $t('pendingDamageLabel') }}
// player's pending damage uses floor so you don't overestimate damage you've already done
.row.rage-bar-row(v-if='questData.boss.rage')
.col-12
.grey-progress-bar
.boss-health-bar.rage-bar(:style="{width: (group.quest.progress.rage / questData.boss.rage.value) * 100 + '%'}")
.row.boss-details.rage-details(v-if='questData.boss.rage')
.col-6 .col-6
h4.float-left(v-once) {{ questData.boss.name() }} span.float-left {{ $t('rage') }} {{ parseFloat(group.quest.progress.rage).toFixed(2) }} / {{ questData.boss.rage.value }}
.col-6 button.btn.btn-secondary(v-once, @click="questAbort()", v-if='canEditQuest') {{ $t('abort') }}
span.float-right(v-once) {{ $t('participantsTitle') }}
.row
.col-12
.grey-progress-bar
.boss-health-bar(:style="{width: (group.quest.progress.hp / questData.boss.hp) * 100 + '%'}")
.row.boss-details
.col-6
span.float-left
| {{ Math.ceil(parseFloat(group.quest.progress.hp) * 100) / 100 }} / {{ parseFloat(questData.boss.hp).toFixed(2) }}
// current boss hp uses ceil so you don't underestimate damage needed to end quest
.col-6(v-if='userIsOnQuest')
// @TODO: Why do we not sync quest progress on the group doc? Each user could have different progress.
span.float-right {{ user.party.quest.progress.up | floor(10) }} {{ $t('pendingDamageLabel') }}
// player's pending damage uses floor so you don't overestimate damage you've already done
.row.rage-bar-row(v-if='questData.boss.rage')
.col-12
.grey-progress-bar
.boss-health-bar.rage-bar(:style="{width: (group.quest.progress.rage / questData.boss.rage.value) * 100 + '%'}")
.row.boss-details.rage-details(v-if='questData.boss.rage')
.col-6
span.float-left {{ $t('rage') }} {{ parseFloat(group.quest.progress.rage).toFixed(2) }} / {{ questData.boss.rage.value }}
button.btn.btn-secondary(v-once, @click="questAbort()", v-if='canEditQuest') {{ $t('abort') }}
</template> </template>
<style lang="scss" scoped> <style lang="scss" scoped>
@@ -193,18 +184,18 @@ import { mapState } from 'client/libs/store';
import quests from 'common/script/content/quests'; import quests from 'common/script/content/quests';
import percent from 'common/script/libs/percent'; import percent from 'common/script/libs/percent';
import sidebarSection from '../sidebarSection';
import upIcon from 'assets/svg/up.svg';
import downIcon from 'assets/svg/down.svg';
import questIcon from 'assets/svg/quest.svg'; import questIcon from 'assets/svg/quest.svg';
export default { export default {
props: ['show', 'group'], props: ['group'],
components: {
sidebarSection,
},
data () { data () {
return { return {
icons: Object.freeze({ icons: Object.freeze({
upIcon,
downIcon,
questIcon, questIcon,
}), }),
}; };
@@ -261,9 +252,6 @@ export default {
}, },
}, },
methods: { methods: {
toggle () {
this.$emit('toggle');
},
openStartQuestModal () { openStartQuestModal () {
this.$root.$emit('bv::show::modal', 'start-quest-modal'); this.$root.$emit('bv::show::modal', 'start-quest-modal');
}, },

View File

@@ -0,0 +1,94 @@
<template lang="pug">
.section(:class="{'section-last': last}")
.section-header.d-flex.align-items-center
h3.mb-0(v-once)
| {{ title }}
.section-info.mx-1(
v-if="tooltip !== null"
)
.svg-icon(
v-html='icons.information',
:id="tooltipId",
:title="tooltip"
)
b-tooltip(
:title="tooltip",
:target="tooltipId",
)
.section-toggle.ml-auto(@click="toggle")
.svg-icon(v-html="icons.upIcon", v-if="visible")
.svg-icon(v-html="icons.downIcon", v-else)
.section-body(v-show="visible")
slot
</template>
<style lang="scss" scoped>
.section {
border-top: 1px solid #e1e0e3;
margin-top: 1em;
padding-top: 1em;
}
.section-last {
border-bottom: 1px solid #e1e0e3;
margin-bottom: 1em;
padding-bottom: 1em;
}
.section-body {
margin-top: 1em;
}
.section-toggle {
cursor: pointer;
}
.section-info {
cursor: help;
}
.section-info .svg-icon,
.section-toggle .svg-icon {
width: 16px;
}
</style>
<script>
import uuid from 'uuid/v4';
import upIcon from 'assets/svg/up.svg';
import downIcon from 'assets/svg/down.svg';
import informationIcon from 'assets/svg/information.svg';
export default {
props: {
title: {
required: true,
},
tooltip: {
default: null,
},
show: {
default: true,
},
last: {
default: false,
},
},
data () {
return {
tooltipId: uuid(),
visible: this.show,
icons: {
upIcon,
downIcon,
information: informationIcon
},
};
},
methods: {
toggle () {
this.visible = !this.visible;
},
},
};
</script>