Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
51 changes: 51 additions & 0 deletions .storybook/stories/MyKivaImpactInsightModal.stories.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
import MyKivaImpactInsightModal from '#src/components/MyKiva/ImpactInsight/MyKivaImpactInsightModal.vue';

export default {
title: 'MyKiva/ImpactInsight/ImpactInsightModal',
component: MyKivaImpactInsightModal,
};

const story = (args) => {
const template = (_args, { argTypes }) => ({
props: Object.keys(argTypes),
components: { MyKivaImpactInsightModal },
setup() { return { args }; },
template: `
<div>
<MyKivaImpactInsightModal
v-bind="args"
/>
</div>
`,
});
template.args = args;
return template;
};

export const Default = story({
visible: true,
latestLoan: {
id: 1975833,
name: 'Mayram',
image: {
hash: '9673d0722a7675b9b8d11f90849d9b44',
},
geocode: {
country: {
geocode:{
latitude: -16,
longitude: 167
},
id: 231,
isoCode: 'VU',
name: 'Vanuatu',
ppp: '$89,599'
}
},
amount: 100,
whySpecial: 'She is a community leader.',
gender: 'female',
otherLoans: [],
amount: '-75.00'
},
});
3 changes: 2 additions & 1 deletion src/components/Contentful/JourneyCardCarousel.vue
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,7 @@
<MyKivaLatestLoanCard
v-else-if="slide?.isLatestLoan"
:loan="latestLoan"
@open-impact-insight-modal="$emit('open-impact-insight-modal')"
/>
<MyKivaCard
v-else-if="isCustomCard(slide)"
Expand Down Expand Up @@ -185,7 +186,7 @@ const {

const { getCategoryLoansLastYear } = useGoalData();

const emit = defineEmits(['update-journey', 'open-goal-modal']);
const emit = defineEmits(['update-journey', 'open-goal-modal', 'open-impact-insight-modal']);

const props = defineProps({
userInfo: {
Expand Down
226 changes: 226 additions & 0 deletions src/components/MyKiva/ImpactInsight/MyKivaImpactInsightModal.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,226 @@
<template>
<KvLightbox
:visible="show"
title=""
@lightbox-closed="handleClose"
class="impact-insight-modal"
>
<template #header>
<h2
v-if="!isMobile"
class="tw-mb-3 !tw-text-left"
>
A closer look at <u>{{ borrowerName }} world</u>
</h2>
</template>
<h2
v-if="isMobile"
class="tw-mb-3 !tw-text-left"
>
A closer look at <u>{{ borrowerName }} world</u>
</h2>
<div class="tw-flex tw-flex-col tw-items-center tw-w-full md:!tw-relative">
<KvCarousel
ref="carouselRef"
:is-dotted="true"
:new-index="carouselIndex"
:slide-max-width="''"
:controls-top-right="false"
:multiple-slides-visible="false"
:embla-options="{ loop: false, startIndex: 0 }"
class="impact-insight-carousel"
@change="handleUserInteraction"
>
<template #slide1>
<MyKivaImpactInsightScreen1 :latest-loan="latestLoan" />
</template>
<template #slide2>
<MyKivaImpactInsightScreen2 :latest-loan="latestLoan" />
</template>
<template #slide3>
<MyKivaImpactInsightScreen3 :latest-loan="latestLoan" />
</template>
<template #slide4>
<MyKivaImpactInsightScreen4 :latest-loan="latestLoan" />
</template>
</KvCarousel>

<div
class="tw-static tw-w-full md:tw-w-auto md:tw-absolute tw-self-end tw-bottom-0"
>
<div
class="tw-relative tw-justify-end tw-items-end tw-gap-1.5 tw-w-xs impact-insight-footer"
>
<div
class="tw-flex tw-justify-self-end tw-w-full tw-h-6
tw-gap-2 tw-float-end secondary-navigation-buttons"
>
<button
v-if="currentSlide > 0 && !isMobile"
class="tw-w-11 tw-text-center tw-border tw-rounded-lg
tw-bg-white tw-text-gray-900 tw-font-medium"
:disabled="currentSlide === 0"
@click="goToPrev"
>
Back
</button>
<button
class="tw-w-full md:tw-w-11 tw-text-center tw-rounded-lg tw-bg-action tw-text-white
tw-font-medium hover:tw-bg-action-highlight"
@click="handleNextOrDone"
>
{{ isLastSlide ? 'Done' : 'Next' }}
</button>
</div>
</div>
</div>
</div>
</KvLightbox>
</template>

<script setup lang="ts">
import {
ref, computed, defineProps, defineEmits,
inject, onMounted
} from 'vue';

import { KvLightbox, KvCarousel } from '@kiva/kv-components';

import useBreakpoints from '#src/composables/useBreakpoints';
import { formatPossessiveName } from '#src/util/stringParserUtils';
import MyKivaImpactInsightScreen1 from './MyKivaImpactInsightScreen1';
import MyKivaImpactInsightScreen2 from './MyKivaImpactInsightScreen2';
import MyKivaImpactInsightScreen3 from './MyKivaImpactInsightScreen3';
import MyKivaImpactInsightScreen4 from './MyKivaImpactInsightScreen4';

const props = defineProps({
show: {
type: Boolean,
default: false,
},
latestLoan: {
type: Object,
default: null,
},
});

const emit = defineEmits(['close']);
const $kvTrackEvent = inject('$kvTrackEvent');

const currentSlide = ref(0);
const carouselRef = ref(null);

const totalSlides = 4;
const { isMobile } = useBreakpoints();

const borrowerName = computed(() => {
return formatPossessiveName(props.latestLoan?.name) || '';
});

const isLastSlide = computed(() => currentSlide.value === totalSlides - 1);

const handleTrackEvent = () => {
$kvTrackEvent('portfolio', 'view', `impact-education-screen-${currentSlide.value + 1}`);
};

const handleClose = () => {
emit('close');
currentSlide.value = 0;
};

const goToPrev = () => {
if (currentSlide.value > 0) {
const newIndex = currentSlide.value - 1;
carouselRef.value?.goToSlide(newIndex);
currentSlide.value = newIndex;
$kvTrackEvent('portfolio', 'click', 'next-step-impact-education-back');
handleTrackEvent();
}
};

const goToNext = () => {
if (currentSlide.value < totalSlides - 1) {
const newIndex = currentSlide.value + 1;
carouselRef.value?.goToSlide(newIndex);
currentSlide.value = newIndex;
}
};

const handleNextOrDone = () => {
if (isLastSlide.value) {
handleClose();
} else {
goToNext();
$kvTrackEvent('portfolio', 'click', 'next-step-impact-education-next');
handleTrackEvent();
}
};

const handleUserInteraction = interaction => {
const newIndex = interaction.value;
if (typeof newIndex === 'number' && newIndex !== currentSlide.value) {
currentSlide.value = newIndex;
handleTrackEvent();
}
};

onMounted(() => {
$kvTrackEvent('portfolio', 'view', 'impact-education-screen-1');
});

</script>

<style lang="postcss">
.impact-insight-modal ::v-deep #kvLightboxBody {
height: 771px;
width: 100%;

@screen md {
height: 384px;
width: 952px;
}
}

.impact-insight-modal {
.impact-insight-carousel {
@apply md:!tw-mb-2
}

.tw-bg-primary:has(#kvLightboxBody) {
max-height: 528px;
}

.impact-insight-carousel div:has(.impact-insight-slide) {
@apply tw-self-start md:tw-self-auto;
}

.impact-insight-carousel div:first-child {
@apply !tw-items-center;
}

.kv-carousel__controls {
gap: 10px;
flex-wrap: wrap;

@apply !tw-flex tw-items-center tw-gap-1 tw-mb-1.5 tw-z-sticky md:!tw-mt-5 md:!tw-mb-0;

@screen md {
max-width: 50%;
}
}

.impact-insight-footer {
max-height: 48px;

.secondary-navigation-buttons {
@apply md:!tw-absolute;

@screen md {
width: auto;
bottom: 21%;
}

}
}
}
</style>
42 changes: 27 additions & 15 deletions src/components/MyKiva/ImpactInsight/MyKivaImpactInsightScreen1.vue
Original file line number Diff line number Diff line change
@@ -1,13 +1,9 @@
<template>
<section class="tw-w-full tw-px-2 md:!tw-py-10 md:!tw-px-10">
<div class="tw-mx-auto tw-max-w-6xl">
<!-- Title -->
<h2 class="">
A closer look at <u>{{ borrowerName }} world</u>
</h2>
<section class="tw-w-full tw-px-2 md:!tw-pr-3 impact-insight-slide">
<div class="tw-mx-auto md:!tw-max-w-4xl">
<div
class="tw-mt-10 tw-flex tw-flex-col tw-items-center tw-gap-10
md:tw-mt-14 md:tw-flex-row md:tw-items-center md:!tw-justify-center"
class="tw-flex tw-flex-col tw-items-center
md:tw-flex-row md:tw-items-center md:!tw-justify-center"
>
<div
class="tw-flex tw-items-center tw-justify-center tw-rounded-full tw-border-4 tw-border-brand-500
Expand Down Expand Up @@ -35,7 +31,7 @@
</div>
</div>
<div
class="tw-w-full tw-max-w-xl tw-px-4 md:!tw-px-0"
class="tw-px-4 md:!tw-px-0 screen-description"
>
<p
v-html="loanDescription"
Expand All @@ -55,19 +51,13 @@ import {
import { computed } from 'vue';
import numeral from 'numeral';

import { formatPossessiveName } from '#src/util/stringParserUtils';

const props = defineProps({
latestLoan: {
type: Object,
default: null,
}
});

const borrowerName = computed(() => {
return formatPossessiveName(props.latestLoan?.name) || '';
});

const name = computed(() => {
return props.latestLoan?.name || '';
});
Expand Down Expand Up @@ -134,4 +124,26 @@ const loanDescription = computed(() => {
width: 60px;
}
}

.impact-insight-slide {
@screen md {
padding-left: 130px;
}
}

div:has(.screen-description) {
gap: 105px;

@screen md {
gap: 10rem;
}
}

.screen-description {
width: 289px;

@screen md {
width: 400px;
}
}
</style>
Loading
Loading