Skip to content

Instantly share code, notes, and snippets.

@artnikbrothers
Created November 30, 2022 20:33
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save artnikbrothers/57e0bddd9b6bfdc9577e9876b71d299d to your computer and use it in GitHub Desktop.
Save artnikbrothers/57e0bddd9b6bfdc9577e9876b71d299d to your computer and use it in GitHub Desktop.
import Vue from 'vue'
import gql from 'graphql-tag'
import graphql from '@/services/graphql'
import {
FETCH_NOTE_REQUEST,
FETCH_NOTE_SUCCESS,
FETCH_NOTE_ERROR,
SAVE_NOTE_REQUEST,
SAVE_NOTE_SUCCESS,
SAVE_NOTE_ERROR,
SET_NOTE_ID,
SET_NOTE,
SET_NOTE_VALUE,
} from './types'
export const request = () => ({
isLoading: false,
error: null,
})
export const state = {
id: null,
note: null,
fetchRequest: request(),
saveRequest: request(),
isFormSubmitted: false,
}
export const mutations = {
[FETCH_NOTE_REQUEST] (state) {
state.fetchRequest.isLoading = true
},
[FETCH_NOTE_SUCCESS] (state) {
state.fetchRequest.isLoading = false
state.fetchRequest.error = null
},
[FETCH_NOTE_ERROR] (state, error) {
state.fetchRequest.isLoading = false
state.fetchRequest.error = error
},
[SAVE_NOTE_REQUEST] (state) {
state.saveRequest.isLoading = true
},
[SAVE_NOTE_SUCCESS] (state) {
state.saveRequest.isLoading = false
state.saveRequest.error = null
state.isFormSubmitted = true
},
[SAVE_NOTE_ERROR] (state, error) {
state.saveRequest.isLoading = false
state.saveRequest.error = error
},
[SET_NOTE_ID] (state, id) {
state.id = id
},
[SET_NOTE] (state, note) {
state.note = note
},
[SET_NOTE_VALUE] (state, value) {
Vue.set(state.note, 'value', value)
},
}
export const actions = {
setNoteValue ({ commit }, value) {
commit(SET_NOTE_VALUE, value)
},
async fetchNote ({ commit }, id) {
commit(SET_NOTE_ID, id)
commit(FETCH_NOTE_REQUEST)
try {
const { data } = await graphql.query({
query: gql`
query PurchaseFormNote ($id: String!) {
purchaseFormNote (id: $id) {
label
value
placeholder
}
}`,
variables: { id }
})
commit(FETCH_NOTE_SUCCESS)
commit(SET_NOTE, data.purchaseFormNote)
} catch (error) {
commit(FETCH_NOTE_ERROR, error)
throw error
}
},
async saveNote ({ state, commit }) {
const { id, note } = state
const { value } = note
commit(SAVE_NOTE_REQUEST)
try {
await graphql.mutate({
mutation: gql`
mutation ($id: String!, $value: String!) {
updatePurchaseFormNoteValue (id: $id, value: $value)
}`,
variables: { id, value }
})
commit(SAVE_NOTE_SUCCESS)
} catch (error) {
commit(SAVE_NOTE_ERROR, error)
throw error
}
},
}
export default {
state,
mutations,
actions,
}
<template>
<main-layout
:style="topBgStyle"
:background-image-top-url="backgroundImageTopUrl"
:background-image-top-small-url="backgroundImageTopSmallUrl"
:show-footer="false"
:header-bg-color="navBgColor"
:header-border-color="navBorderColor"
:header-text-color="navTextColor"
:class="notePageClass"
class="note-page"
>
<div
v-if="shouldShowNoteContent"
:style="notePageWrapperStyle"
class="note-page__wrapper"
>
<div
:style="notePageContentStyle"
class="note-page__content"
>
<h2
:style="notePageTitle"
class="note-page__title"
>
{{ noteLabel }}
</h2>
<div
:style="notePageMainStyle"
class="note-page__main"
>
<div
v-if="isUserSignedIn"
class="note-page__form__wrap"
>
<form
v-if="shouldShowForm"
class="note-page__form"
@submit.prevent="handleFormSubmit"
>
<text-area-input
v-model="noteValue"
:show-error="false"
:should-show-counter="true"
:style="noteMessageStyle"
:input-style="noteMessageStyle"
:placeholder="notePlaceholder"
name="note-message"
class="note-page__form__textarea"
/>
<ui-button
:submit="true"
:disabled="saveRequestIsLoading"
:color="submitButtonBgColor"
:style="submitButtonStyle"
:hover-color="primaryButtonBgHoverColor"
:text-color="primaryButtonColor"
:border-radius="false"
class="finish_signup-form__submit"
type="purple"
>
Submit
</ui-button>
</form>
<div
v-else
:style="formSuccessStyle"
class="note-page__form__success"
>
<peek-checkmark-icon class="note-page__form__success__icon" />
<div class="note-page__form__success__message">Thank you!</div>
</div>
</div>
<div
v-else
class="note-page__auth"
>
<h5 class="note-page__auth__title">You must be signed in</h5>
<div class="note-page__auth__description">If you do not have an account you must create one. Enter the email you used during checkout.</div>
<div class="note-page__auth__actions">
<ui-button
:border-radius="false"
:color="primaryButtonBgColor"
:style="buttonStyle"
:hover-color="primaryButtonBgHoverColor"
:text-color="primaryButtonColor"
class="note-page__auth__button note-page__auth__button--sign-in"
type="purple"
@click="handleSignInClick"
>
Sign In
</ui-button>
<ui-button
:border-radius="false"
:color="primaryButtonBgColor"
:style="buttonStyle"
:hover-color="primaryButtonBgHoverColor"
:text-color="primaryButtonColor"
class="note-page__auth__button note-page__auth__button--sign-up"
type="purple"
@click="handleSignUpClick"
>
Sign Up
</ui-button>
</div>
</div>
</div>
</div>
</div>
</main-layout>
</template>
<script>
import {
mapGetters,
mapState,
mapActions,
} from 'vuex'
import MainLayout from 'components/layout/MainLayout'
import TextAreaInput from 'components/forms/TextAreaInput'
import UiButton from 'components/forms/UiButton'
import PeekCheckmarkIcon from 'static/assets/icons/PeekCheckmarkIcon.svg'
export default {
name: 'NotePage',
components: {
MainLayout,
TextAreaInput,
UiButton,
PeekCheckmarkIcon,
},
computed: {
...mapGetters([
'isRetinaDevice',
'isUserSignedIn',
]),
...mapState({
productStyles: state => state.productStyles.styles,
note: state => state.note.note,
productStylesIsLoading: state => state.productStyles.request.isLoading,
saveRequestIsLoading: state => state.note.saveRequest.isLoading,
isFormSubmitted: state => state.note.isFormSubmitted,
}),
noteValue: {
get () { return this.$store.state.note.note.value },
set (value) { this.$store.dispatch('setNoteValue', value) }
},
noteLabel () {
return this.note?.label
},
notePlaceholder () {
return this.note?.placeholder
},
shouldShowForm () {
return !this.isFormSubmitted
},
shouldShowNoteContent () {
return !this.productStylesIsLoading
},
productId () {
// TODO: figure out how to fetch styles for note page
return '2650430701686'
},
noteId () {
return this.$route?.params?.noteId
},
backgroundImageTopUrl () {
return this.productStyles?.backgroundImageTop?.url
},
backgroundImageTopSmallUrl () {
return this.productStyles?.backgroundImageTopSmall?.url
},
inputBorderColor () {
return this.productStyles?.inputBorderColor
},
inputPlaceholderColor () {
return this.productStyles?.inputPlaceholderColor
},
navBgColor () {
return this.productStyles?.navBgColor
},
navBorderColor () {
return this.productStyles?.navBorderColor
},
navTextColor () {
return this.productStyles?.navTextColor
},
primaryBgColor () {
return this.productStyles?.primaryBgColor
},
primaryButtonBgColor () {
return this.productStyles?.primaryButtonBgColor
},
primaryButtonBgHoverColor () {
return this.productStyles?.primaryButtonBgHoverColor
},
primaryButtonDisabledBg () {
return this.productStyles?.primaryButtonDisabledBg
},
primaryButtonDisabledColor () {
return this.productStyles?.primaryButtonDisabledColor
},
primaryButtonColor () {
return this.productStyles?.primaryButtonColor
},
primaryTextColor () {
return this.productStyles?.primaryTextColor
},
productTitleColor () {
return this.productStyles?.productTitleColor
},
topBgStyle () {
const backgroundColor = this.primaryBgColor
const color = this.primaryTextColor
return { backgroundColor, color }
},
notePageContentStyle () {
return { color: this.primaryBgColor }
},
notePageMainStyle () {
return { color: this.primaryTextColor }
},
notePageTitle () {
return { color: this.productTitleColor }
},
notePageClass () {
return { 'note-page--signed-in': this.isUserSignedIn }
},
notePageWrapperStyle () {
return { color: this.primaryTextColor }
},
submitButtonBgColor () {
return this.saveRequestIsLoading ? this.primaryButtonDisabledBg : this.primaryButtonBgColor
},
submitButtonColor () {
return this.saveRequestIsLoading ? this.primaryButtonDisabledColor : this.primaryButtonColor
},
submitButtonStyle () {
const borderColor = this.saveRequestIsLoading ? this.primaryButtonDisabledBg : this.primaryButtonBgColor
return { borderColor }
},
noteMessageStyle () {
return {
color: this.inputPlaceholderColor,
borderColor: this.inputBorderColor,
}
},
buttonStyle () {
return { borderColor: this.primaryButtonBgColor }
},
formSuccessStyle () {
return { color: this.primaryTextColor }
},
},
methods: {
...mapActions([
'fetchProductStyles',
'fetchNote',
'saveNote',
]),
handleSignInClick () {
const { fullPath } = this.$route
const url = `/login?redirect=${encodeURIComponent(fullPath)}`
this.$router.push(url)
},
handleSignUpClick () {
this.$router.push('/signup')
},
async handleFormSubmit () {
await this.saveNote()
},
},
mounted () {
this.fetchNote(this.noteId)
this.fetchProductStyles(this.productId)
},
}
</script>
<style lang="stylus" scoped>
@import '~styles/shared'
.note-page--signed-in
.note-page__content
margin-top: 18px
+tablet()
margin-top: -37px
+desktop()
margin-top: 0
+widescreen()
margin-top: -49px
.note-page__main
+tablet()
margin-top: 8px
.note-page__wrapper
min-height: 500px
background: 50% top no-repeat
background-size: 100% auto
display: flex
flex-direction: column
justify-content: center
align-items: center
overflow-x: hidden
overflow-y: auto
width: 100%
height: 100%
position: relative
z-index: 0
+tablet()
min-height: 600px
.note-page__content
max-width: 500px
min-height: 398px
width: 100%
display: flex
flex-direction: column
align-items: center
padding: 19px
color: currentColor
text-align: center
margin-top: -47px
position: relative
+tablet()
max-width: 550px
min-height: 373px
padding: 32px 37px
margin-top: -84px
+desktop()
margin-top: -44px
+widescreen()
margin-top: -95px
&:after
+tablet()
content: ''
position: absolute
left: 0
right: 0
top: 0
bottom: 0
z-index: -1
display: block
background-color: currentColor
opacity: .7
.note-page__title
font: 500 20px/22px $font-family-secondary
letter-spacing: .1px
margin-top: 0
.note-page__main
width: 100%
margin-top: 4px
min-height: 292px
+tablet()
min-height: 242px
margin-top: 0
.note-page__form
width: 100%
.finish_signup-form__submit.button
width: 100%
margin-top: 6px
padding: 8px
font-size: 18px
font-weight: 600
text-transform: uppercase
letter-spacing: .3px
.note-page__form__success
margin-top: 57px
.note-page__form__success__icon
width: 65px
fill: currentColor
.note-page__form__success__message
font: 600 20px $font-family-secondary
margin-top: 5px
color: currentColor
.note-page__auth
margin-top: 48px
.note-page__auth__title
margin: 0
font-weight: 600
font-size: 16px
letter-spacing: .2px
.note-page__auth__description
margin-top: 11px
margin-bottom: 26px
letter-spacing: .2px
font-weight: 300
padding: 0 11px
line-height: 23px
+tablet()
padding: 0 32px
margin-bottom: 23px
.note-page__auth__actions
.note-page__auth__button.button
font-size: 17px
letter-spacing: .2px
width: 101px
height: 48px
margin: 0 7px
</style>
<style lang="stylus">
@import '~styles/shared'
.note-page
&.main-layout
min-height: 500px
height: 100%
width: 100%
overflow: hidden
position: relative
z-index: 0
.main-layout__wrapper,
.main-content
height: 100%
#note-message
min-height: 217px
border-radius: 0
border-width: 1px
border-style: solid
border-color: currentColor
background: transparent
color: currentColor
resize: none
padding: 13px 20px
margin: 0
font-size: 15px
letter-spacing: .45px
line-height: 23px
-webkit-appearance: none
+tablet()
min-height: 167px
padding: 13px 17px 13px 19px
&::placeholder
color: currentColor
</style>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment