Skip to content

Commit

Permalink
feat: add activity modal
Browse files Browse the repository at this point in the history
  • Loading branch information
y0000ga committed Nov 14, 2023
1 parent 08c0919 commit 818aa62
Show file tree
Hide file tree
Showing 13 changed files with 162 additions and 76 deletions.
9 changes: 9 additions & 0 deletions assets/image/cursor.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
5 changes: 2 additions & 3 deletions assets/scss/style.scss
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@
@import url('https://fonts.googleapis.com/css2?family=Inter:wght@100;200;300;400;500;600;700;800;900&family=Noto+Sans+TC:wght@100;200;300;400;500;600;700;800;900&display=swap');



@font-face {
font-family: 'mantou-sans';
src: url('/assets/fonts/MantouSans-Regular.ttf') format('truetype');
Expand Down Expand Up @@ -174,7 +173,7 @@ position:absolute,
}

.cursor-pointer{
cursor: pointer;
cursor: url('~/assets/image/cursor.svg'),auto;
&:hover{
background: linear-gradient(90deg, #E6793B 1.54%, #FF4185 97.86%);
background: -webkit-linear-gradient(90deg, #E6793B 1.54%, #FF4185 97.86%);
Expand All @@ -184,4 +183,4 @@ position:absolute,
}
}

}
}
12 changes: 7 additions & 5 deletions components/UI/BaseButton.vue
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
<template>
<v-btn variant="flat" plain :class="['baseButton', 'rounded-pill', 'pa-0', props.fullWidth ? 'w-100' : '']">
<p
:class="[props.fullWidth ? '':'text-h6', 'my-5', 'ml-6', props.icon ? 'mr-2' : 'mr-6', props.theme === 'primary' ? 'text-white' : 'text-text-primary']" :style="{'fontWeight': props.fullWidth ? '600':''}">
<p :class="[props.fullWidth ? '' : 'text-h6', 'my-5', 'ml-6', props.icon ? 'mr-2' : 'mr-6', props.theme === 'primary' ? 'text-white' : 'text-text-primary']"
:style="{ 'fontWeight': props.fullWidth ? '600' : '' }">
{{
props.title }}</p>
<v-icon v-if="props.icon" :icon="props.icon"
Expand Down Expand Up @@ -38,17 +38,19 @@ const color = computed(() => props.theme === 'primary' ? "#DA7D4A" : props.theme
</script>

<style scoped lang="scss">
.v-btn--variant-tonal .v-btn__underlay{
background: white
.v-btn--variant-tonal .v-btn__underlay {
background: white;
}
.v-btn.baseButton {
width: fit-content;
height: fit-content;
background-color: v-bind(color) !important;
cursor: url('~/assets/image/cursor.svg'), auto;
.v-btn__underlay {
background: none;
}
}
</style>
89 changes: 67 additions & 22 deletions components/UI/BaseSwiper.vue
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
<template>
<swiper :effect="'coverflow'" :spaceBetween="0" :grabCursor="true" :centeredSlides="true" :slidesPerView="'auto'"
:pagination="customPagination" :modules="modules" :loop="true" class="mySwiper">
<swiper :navigation="customNavigation" :effect="'coverflow'" :spaceBetween="0" :grabCursor="true" :centeredSlides="true"
:slidesPerView="'auto'" :pagination="customPagination" :modules="modules" :loop="true" class="mySwiper">
<swiper-slide v-for="policy in [...POLICY, ...POLICY] " :key="policy.id" class="bg-white d-flex">
<v-img :src="policy.imgSrc" width="428px" class="ga-6" />
<v-container class="pa-0 ml-lg-8 d-flex flex-column justify-center">
Expand All @@ -11,18 +11,27 @@
}}</h4>
<base-button title="查看" theme="primary" icon="mdi-arrow-right" @click="activateDialog(policy.id)"></base-button>
</v-container></swiper-slide>
<div class="swiper-pagination"></div>
<div class="actions mt-3">
<div class="swiper-button-prev"><v-btn class="ma-2" variant="outlined" icon="mdi-arrow-left"></v-btn></div>
<div class="swiper-pagination"></div>
<div class="swiper-button-next"><v-btn class="ma-2" variant="outlined" icon="mdi-arrow-right"></v-btn></div>
</div>



</swiper>
</template>
<script lang="ts">
import { Swiper, SwiperSlide } from 'swiper/vue'
import 'swiper/css'
import 'swiper/css/pagination'
import { Pagination } from 'swiper/modules'
import 'swiper/css/navigation';
import { Pagination, Navigation } from 'swiper/modules'
import { POLICY } from '~/utils/constant'
import BaseButton from '~/components/UI/BaseButton.vue';
import { useHomeStore } from '~/stores/home'
export default {
components: {
Swiper,
Expand All @@ -31,20 +40,26 @@ export default {
},
setup() {
const homeStore = useHomeStore()
const activateDialog = (id:string) => {
homeStore.handleActiveDialog(Dialog.POLICY,id)
const activateDialog = (id: string) => {
homeStore.handleActiveDialog(Dialog.POLICY, id)
}
const customPagination = {
el: '.swiper-pagination',
renderBullet: (index:number, className:string) => {
return `<span class="${className} mx-2 bg-primary" style="width:12px;height:12px" key={${index}} value={${index}}></span>`
renderBullet: (index: number, className: string) => {
return `<span class="${className} mx-2 bg-primary" style="width:12px;height:12px" key={${index}} value={${index}}></span>`
}
}
const customNavigation = {
nextEl: '.swiper-button-next',
prevEl: '.swiper-button-prev'
}
return {
modules: [Pagination],
modules: [Pagination, Navigation],
customPagination,
activateDialog
activateDialog,
customNavigation
}
},
}
Expand All @@ -67,28 +82,58 @@ export default {
border-radius: 32px;
overflow: hidden;
transform: scale(0.9);
&.swiper-slide-active {
transform: scale(1);
}
img {
display: block;
width: 100%;
}
display: block;
width: 100%;
}
}
.swiper-pagination {
bottom: var(--swiper-pagination-bottom, 8px);
top: var(--swiper-pagination-top, auto);
left: 0;
width: 100%;
width: fit-content;
position: static;
display: flex;
align-items: center;
}
.actions {
display: flex;
justify-content: center;
}
@media(max-width: 960px){
.swiper-slide{
.swiper-button-next,
.swiper-button-prev {
position: static;
display: block;
width: fit-content;
height: fit-content;
margin-top: 0px;
.v-btn--variant-outlined {
border: none;
background-color: white;
color: #DA7D4A
}
&::after {
content: "";
display: none;
}
}
@media(max-width: 960px) {
.swiper-slide {
width: 311px;
height:508px;
display:flex;
height: 508px;
display: flex;
flex-direction: column;
}
}
Expand Down
39 changes: 22 additions & 17 deletions components/UI/Dialog/ActivityContent.vue
Original file line number Diff line number Diff line change
@@ -1,31 +1,32 @@
<template>
<div :class="['d-flex', props.isDesktop ? 'flex-row' : 'flex-column', 'ga-8']">
<div :class="['d-flex', props.isDesktop ? 'flex-row' : 'flex-column', 'ga-8', 'h-100']">
<div :class="['d-flex', 'flex-column', 'text-text-primary', 'text-body-1']"
:style="{ width: props.isDesktop ? '40%' : '' }"><img :src="activities.main?.imgSrc" class="rounded-lg"
:style="{ 'width': '100%', 'aspect-ratio': '507/400' }" />
<p :class="['mt-4', 'mb-2', props.isDesktop ? 'text-caption' : 'text-body-1']">{{ activities.main?.title}}
:style="{ width: props.isDesktop ? '40%' : '', position: props.isDesktop ? 'sticky' : undefined, height: '100%', top: '0px' }">
<img :src="activities.main?.imgSrc" class="rounded-lg"
:style="{ 'width': '100%', 'aspect-ratio': '343/251', 'objectFit': 'cover' }" />
<p :class="['mt-4', 'mb-2', props.isDesktop ? 'text-caption' : 'text-body-1']">{{ activities.main?.title }}
</p>
<div class="d-flex align-center ga-2">
<p>分享</p><v-btn class="rounded-pill px-0 bg-white" style="height:32px;min-width:32px" variant="text"
v-for="item in SOCIAL"><v-icon style="font-size:24px" :color="item.color" :icon="'mdi-' + item.icon"
:class="item.class || ''"></v-icon></v-btn>
</div>
</div>
<div :style="{ width: props.isDesktop ? '60%' : '' }">
<div class="h-100" :style="{ width: props.isDesktop ? '60%' : '' }">
<div>
<h4 class="text-primary text-h4 mb-10">{{ activities.main?.title }}</h4>
<!-- <div v-for="item in activities.main?.content" class="mb-6">
<h5 class="text-h5 mb-2">{{ item.title }}</h5>
<p>{{ item.content }}</p>
</div> -->
<v-card class="bg-gray-50 rounded-lg pa-4 d-flex flex-column w-100" style="margin-top:88px;box-shadow: none">
<h4 class="text-primary text-h4 mb-2">{{ activities.main?.title }}</h4>
<p class="text-text-caption mb-10">{{ activities.main?.date }}</p>
<p class="text-text-body-1 text-text-primary mb-6">{{ activities.main?.content }}</p>
<p class="text-text-body-1 text-text-primary mb-6" v-for="sub in activities.main?.subContent">{{ sub }}</p>
<v-card class="bg-gray-50 rounded-lg pa-4 d-flex flex-column w-100 mt-16" style="box-shadow: none">
<p class="text-body-1 mb-4" style="font-weight: 600;">更多政策議題</p>
<div class="d-flex ga-4"><v-card class="bg-transparent"
:style="{ 'box-shadow': 'none', 'max-width': props.isDesktop ? '244px' : '' }"
v-for="policy in activities.other">
<img :src="policy.imgSrc" class="rounded-lg w-100"
:style="{ height: props.isDesktop ? '134px' : undefined, objectFit: props.isDesktop ? 'cover' : undefined }" />
<p class="text-body-1 mt-3 text-text-primary">{{ policy.title }}</p>
:style="{ 'box-shadow': 'none', 'max-width': props.isDesktop ? '244px' : '', 'width': props.isDesktop ? '' : '50%' }"
v-for="activity in activities.other">
<img :src="activity.imgSrc" class="rounded-lg w-100"
:style="{ height: props.isDesktop ? '134px' : undefined, aspectRatio: '244/134', objectFit: 'cover' }" />
<p class="text-body-1 mt-3 text-text-primary cursor-pointer" @click="handleSelectActivity(activity.id)">{{
activity.title }}</p>
</v-card>
</div>
</v-card>
Expand All @@ -45,6 +46,10 @@ const props = defineProps({
}
})
const activities = computed(() => {
return { main: ACTIVITY.find(policy => policy.id === homeStore.activeDialog.id), other: ACTIVITY.filter(policy => policy.id !== homeStore.activeDialog.id) }
return { main: ACTIVITY.find(activity => activity.id === homeStore.activeDialog.id), other: ACTIVITY.filter(activity => activity.id !== homeStore.activeDialog.id) }
})
const handleSelectActivity = (id: string) => {
homeStore.handleActiveDialog(Dialog.ACTIVITY, id)
}
</script>
24 changes: 20 additions & 4 deletions components/UI/Dialog/BaseDialog.vue
Original file line number Diff line number Diff line change
@@ -1,15 +1,15 @@
<template>
<v-row justify="center">
<v-dialog scrollable v-model="isActive" :width="props.isDesktop ? '95%' : undefined" style="max-width: 1440px"
<v-dialog scrollable v-model="isActive" :width="props.isDesktop ? '100%' : undefined" style="max-width: 1440px"
:fullscreen="props.isDesktop ? false : true" :scrim="props.isDesktop ? true : false"
@close="homeStore.handleActiveDialog(Dialog.NULL)" :attach="true" transition="dialog-bottom-transition">
<v-card class="rounded-xl pa-4" style="height:95%;box-shadow: none;">
<v-card :class="['rounded-xl', props.isDesktop ? 'pt-6 px-12 pb-12' : 'pa-4']" style="height:95%;box-shadow: none;">
<v-card-title class="d-flex align-center justify-space-between pa-0">
<h4 class="text-h5" style="font-weight: 700;">{{ title }}</h4><v-icon
@click="homeStore.handleActiveDialog(Dialog.NULL)" icon="mdi-close-circle"
:style="{ 'font-size': props.isDesktop ? '32px' : '24px' }"></v-icon>
</v-card-title>
<v-card-text :class="['pa-0', props.isDesktop ? 'mt-4' : 'mt-2']">
<v-card-text :class="['pa-0', props.isDesktop ? 'mt-4' : 'mt-2']" ref="contentRef">
<service-content :isDesktop="props.isDesktop"
v-if="homeStore.activeDialog.type === Dialog.SERVICE"></service-content>
<donate-content :isDesktop="props.isDesktop"
Expand All @@ -31,7 +31,10 @@ import DonateContent from '~/components/UI/Dialog/DonateContent.vue';
import ActivityContent from '~/components/UI/Dialog/ActivityContent.vue';
import PolicyContent from '~/components/UI/Dialog/PolicyContent.vue';
import { DIALOG_TITLE } from '~/utils/constant';
import { ref, watch } from 'vue';
const homeStore = useHomeStore()
const contentRef = ref<HTMLDivElement & { $el: HTMLDivElement } | null>(null)
const isActive = computed(() => { return homeStore.activeDialog.type !== Dialog.NULL })
const props = defineProps({
isDesktop: {
Expand All @@ -40,8 +43,21 @@ const props = defineProps({
}
})
watch(() => [homeStore.activeDialog.id, homeStore.activeDialog.type, contentRef.value], () => {
if (homeStore.activeDialog.id && (homeStore.activeDialog.type === Dialog.ACTIVITY || homeStore.activeDialog.type === Dialog.POLICY) && contentRef.value) {
contentRef.value.$el.scrollTop = 0
}
})
const title = computed(() => {
return DIALOG_TITLE[`${homeStore.activeDialog.type as keyof typeof DIALOG_TITLE}`]
})
</script>
</script>

<style lang="scss" scoped>
.v-card-text{
scroll-behavior: smooth;
}
</style>
19 changes: 12 additions & 7 deletions components/UI/Dialog/PolicyContent.vue
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
<template>
<div :class="['d-flex', props.isDesktop ? 'flex-row' : 'flex-column', 'ga-8']">
<div :class="['d-flex', 'flex-column', 'text-text-primary', 'text-body-1']"
:style="{ width: props.isDesktop ? '40%' : '' }"><img :src="policies.main?.imgSrc" class="rounded-lg"
<div :class="['d-flex', props.isDesktop ? 'flex-row' : 'flex-column', 'ga-8','h-100']" >
<div :class="['d-flex', 'flex-column', 'text-text-primary', 'text-body-1','h-100']"
:style="{ width: props.isDesktop ? '40%' : '',position: props.isDesktop ? 'sticky':undefined,top:'0px'}"><img :src="policies.main?.imgSrc" class="rounded-lg"
:style="{ 'width': '100%', 'aspect-ratio': '507/400' }" />
<p :class="['mt-4', 'mb-2', props.isDesktop ? 'text-caption' : 'text-body-1']">{{ policies.main?.title.join("") }}
</p>
Expand All @@ -11,8 +11,8 @@
:class="item.class || ''"></v-icon></v-btn>
</div>
</div>
<div :style="{ width: props.isDesktop ? '60%' : '' }">
<div>
<div :style="{ width: props.isDesktop ? '60%' : '' }" >

<h4 class="text-primary text-h4 mb-10">{{ policies.main?.title.join("") }}</h4>
<div v-for="item in policies.main?.list" class="mb-6">
<h5 class="text-h5 mb-2">{{ item.title }}</h5>
Expand All @@ -24,11 +24,10 @@
v-for="policy in policies.other">
<img :src="policy.imgSrc" class="rounded-lg w-100"
:style="{ height: props.isDesktop ? '134px' : undefined, objectFit: props.isDesktop ? 'cover' : undefined }" />
<p class="text-body-1 mt-3 text-text-primary">{{ policy.title.join("") }}</p>
<p class="text-body-1 mt-3 text-text-primary cursor-pointer" @click="handleSelectItem(policy.id)" >{{ policy.title.join("") }}</p>
</v-card>
</div>
</v-card>
</div>
</div>
</div>
</template>
Expand All @@ -46,4 +45,10 @@ const props = defineProps({
const policies = computed(() => {
return { main: POLICY.find(policy => policy.id === homeStore.activeDialog.id), other: POLICY.filter(policy => policy.id !== homeStore.activeDialog.id) }
})
const handleSelectItem = (id:string) => {
homeStore.handleActiveDialog(Dialog.POLICY, id)
}
</script>
2 changes: 1 addition & 1 deletion components/UI/Dialog/ServiceContent.vue
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@

<base-button title="送出意見" theme="primary" :fullWidth="true" :disabled="false" @click="handleMail"></base-button>
</v-col>
<v-col v-else class="d-flex flex-column align-center h-100 justify-center ga-8">
<v-col v-else :class="['d-flex' ,'flex-column' ,'align-center', props.isDesktop? '': 'h-100', 'justify-center', 'ga-8']">
<h3 class="text-h3">感謝您的意見</h3><v-img :src="donate_finish" :width="187"
style="max-height:166px"></v-img><base-button style="width: 187px" title="關閉" theme="gray"
@click="homeStore.handleActiveDialog(Dialog.NULL)"></base-button>
Expand Down
3 changes: 3 additions & 0 deletions layouts/BaseFooter.vue
Original file line number Diff line number Diff line change
Expand Up @@ -61,5 +61,8 @@ import { LEGISLATOR } from '~/utils/constant';
max-width: 100%;
}
}
.v-application .px-26{
padding:104px 0px 172px 0px
}
}
</style>
Loading

0 comments on commit 818aa62

Please sign in to comment.