| @@ -9,9 +9,9 @@ | |||||
| "lint": "vue-cli-service lint" | "lint": "vue-cli-service lint" | ||||
| }, | }, | ||||
| "dependencies": { | "dependencies": { | ||||
| "@mdi/js": "^7.0.96", | |||||
| "@jamescoyle/vue-icon": "^0.1.2", | |||||
| "@mdi/js": "^7.1.96", | |||||
| "@vueuse/core": "^9.5.0", | "@vueuse/core": "^9.5.0", | ||||
| "bulma": "^0.9.4", | |||||
| "core-js": "^3.8.3", | "core-js": "^3.8.3", | ||||
| "jenesius-vue-modal": "^1.8.2", | "jenesius-vue-modal": "^1.8.2", | ||||
| "jwt-decode": "^3.1.2", | "jwt-decode": "^3.1.2", | ||||
| @@ -1,34 +1,14 @@ | |||||
| <template> | <template> | ||||
| <nav class="navbar has-background-grey-dark" role="navigation" aria-label="main navigation"> | |||||
| <div class="navbar-brand"> | |||||
| <RouterLink to="/" class="navbar-item"> | |||||
| <span class="signet-logo title is-3-desktop is-4-mobile"> | |||||
| <nav role="navigation" aria-label="main navigation"> | |||||
| <div class="signet-logo"> | |||||
| <RouterLink to="/"> | |||||
| <span> | |||||
| <template v-for="(element, i) in logoElements" v-bind:key="i"> | <template v-for="(element, i) in logoElements" v-bind:key="i"> | ||||
| <span :style="`color: #${element.color}`">{{ element.letter }}</span> | |||||
| <span :style="`color: ${element.color}`">{{ element.letter }}</span> | |||||
| </template> | </template> | ||||
| </span> | </span> | ||||
| </RouterLink> | </RouterLink> | ||||
| </div> | </div> | ||||
| <div class="navbar-end"> | |||||
| <div class="navbar-item"> | |||||
| <div class="buttons is-hidden-mobile is-hidden-tablet-only"> | |||||
| <div class="authentication" v-if="!hasToken"> | |||||
| <RouterLink to="/login" class="button is-primary"> | |||||
| Log in | |||||
| </RouterLink> | |||||
| </div> | |||||
| <div v-else> | |||||
| <RouterLink to="/addfund" class="button is-primary"> | |||||
| Add Fund | |||||
| </RouterLink> | |||||
| <RouterLink to="/register" class="button is-white"> | |||||
| Register | |||||
| </RouterLink> | |||||
| </div> | |||||
| </div> | |||||
| </div> | |||||
| </div> | |||||
| </nav> | </nav> | ||||
| <div id="content"> | <div id="content"> | ||||
| @@ -37,9 +17,11 @@ | |||||
| <Component :is="Component"/> | <Component :is="Component"/> | ||||
| <template #fallback> | <template #fallback> | ||||
| <div class="is-flex is-flex-direction-row is-justify-content-center" | |||||
| style="height: 90vh"> | |||||
| <span style="font-size: 1.25em; color: greenyellow; margin: auto 0">Loading...</span> | |||||
| <div | |||||
| style="height: 90vh"> | |||||
| <span style="font-size: 1.25em; color: greenyellow; margin: auto 0"> | |||||
| Loading... | |||||
| </span> | |||||
| </div> | </div> | ||||
| </template> | </template> | ||||
| </Suspense> | </Suspense> | ||||
| @@ -49,7 +31,7 @@ | |||||
| <footer> | <footer> | ||||
| <div> | <div> | ||||
| Proudly made in Michigan | Proudly made in Michigan | ||||
| <div class="michigan-icon"></div> | |||||
| <div></div> | |||||
| </div> | </div> | ||||
| </footer> | </footer> | ||||
| </template> | </template> | ||||
| @@ -83,42 +65,65 @@ interface LogoElement { | |||||
| color: string; | color: string; | ||||
| } | } | ||||
| const logoElements: LogoElement[] = [ | |||||
| { | |||||
| color: '9fe82c', | |||||
| letter: 'B', | |||||
| }, | |||||
| { | |||||
| color: '8ee045', | |||||
| letter: 'e', | |||||
| }, | |||||
| { | |||||
| color: '7dd95c', | |||||
| letter: 'i', | |||||
| }, | |||||
| { | |||||
| color: '6dd373', | |||||
| letter: 'g', | |||||
| }, | |||||
| { | |||||
| color: '5dcb8a', | |||||
| letter: 'n', | |||||
| }, | |||||
| { | |||||
| color: '4cc4a2', | |||||
| letter: 'e', | |||||
| }, | |||||
| { | |||||
| color: '3dbeb8', | |||||
| letter: 't', | |||||
| }, | |||||
| ]; | |||||
| const gradientize = (text: string, start: string, end: string): LogoElement[] => { | |||||
| const extractChannels = (hex: string): { 'r': number, 'g': number, 'b': number } => { | |||||
| const h = ref(hex); | |||||
| if (h.value.startsWith('#')) { | |||||
| h.value = hex.slice(1); | |||||
| } else { | |||||
| h.value = hex; | |||||
| } | |||||
| const [r, g, b] = [ | |||||
| parseInt(h.value.slice(0, 2), 16), | |||||
| parseInt(h.value.slice(2, 4), 16), | |||||
| parseInt(h.value.slice(4, 6), 16), | |||||
| ]; | |||||
| return { | |||||
| r, | |||||
| g, | |||||
| b, | |||||
| }; | |||||
| }; | |||||
| const composeHex = (r: number, g: number, b: number) => { | |||||
| const padIfNeeded = (hex: string) => (hex.length === 1 ? `0${hex}` : hex); | |||||
| const [rHex, gHex, bHex] = [ | |||||
| `${padIfNeeded(r.toString(16))}`, | |||||
| `${padIfNeeded(g.toString(16))}`, | |||||
| `${padIfNeeded(b.toString(16))}`, | |||||
| ]; | |||||
| return `#${rHex}${gHex}${bHex}`; | |||||
| }; | |||||
| const logoElements = ref([] as LogoElement[]); | |||||
| const startChannels = extractChannels(start); | |||||
| const endChannels = extractChannels(end); | |||||
| const differences = { | |||||
| r: endChannels.r - startChannels.r, | |||||
| g: endChannels.g - startChannels.g, | |||||
| b: endChannels.b - startChannels.b, | |||||
| }; | |||||
| const [r, g, b] = [ref(startChannels.r), ref(startChannels.g), ref(startChannels.b)]; | |||||
| for (let i = 0; i < text.length; i += 1) { | |||||
| r.value += differences.r / text.length; | |||||
| g.value += differences.g / text.length; | |||||
| b.value += differences.b / text.length; | |||||
| logoElements.value.push({ | |||||
| color: composeHex(Math.round(r.value), Math.round(g.value), Math.round(b.value)), | |||||
| letter: text[i], | |||||
| }); | |||||
| } | |||||
| return logoElements.value; | |||||
| }; | |||||
| const logoElements: LogoElement[] = gradientize('Beignet', '#f23525', '#e99406'); | |||||
| </script> | </script> | ||||
| <style lang="stylus"> | <style lang="stylus"> | ||||
| @import "../node_modules/bulma/css/bulma.min.css" | |||||
| @import "assets/styles/general.styl" | |||||
| #content | #content | ||||
| margin-top 1.5em | |||||
| min-height 80vh | min-height 80vh | ||||
| #app | #app | ||||
| @@ -132,8 +137,8 @@ html, body | |||||
| body | body | ||||
| min-height 100vh | min-height 100vh | ||||
| color #e8dbca | |||||
| background-color #313538 | |||||
| color text-color | |||||
| background-color bg-color | |||||
| footer | footer | ||||
| color #707070 | color #707070 | ||||
| @@ -144,9 +149,18 @@ footer | |||||
| vertical-align middle | vertical-align middle | ||||
| text-align center | text-align center | ||||
| nav | |||||
| background-color bg-color | |||||
| padding 0.15em 0.7em | |||||
| filter signet-shadow | |||||
| a | |||||
| text-decoration none | |||||
| .signet-logo | .signet-logo | ||||
| font-family Paytone | font-family Paytone | ||||
| letter-spacing 1px | letter-spacing 1px | ||||
| font-size 3em | |||||
| .michigan-icon | .michigan-icon | ||||
| display inline-block | display inline-block | ||||
| @@ -158,10 +172,25 @@ footer | |||||
| background-size 28px | background-size 28px | ||||
| margin-left 4px | margin-left 4px | ||||
| .navbar-burger > * | |||||
| background-color #fff !important | |||||
| .layout-section | |||||
| margin 0 auto | |||||
| width 61.8034% | |||||
| @media screen and (max-width: 1080px) | |||||
| width 82% | |||||
| @media screen and (max-width: 860px) | |||||
| width 96% | |||||
| @font-face | @font-face | ||||
| font-family Paytone | font-family Paytone | ||||
| src url("./assets/PaytoneOne-Regular.ttf") | src url("./assets/PaytoneOne-Regular.ttf") | ||||
| @font-face | |||||
| font-family "Passion One" | |||||
| src url("./assets/PassionOne-Regular.ttf") | |||||
| @font-face | |||||
| font-family "Passion One Bold" | |||||
| src url("./assets/PassionOne-Bold.ttf") | |||||
| </style> | </style> | ||||
| @@ -0,0 +1,9 @@ | |||||
| text-color = #383838 | |||||
| bg-color = #fffbfa | |||||
| primary = #f23525 | |||||
| secondary = #e99406 | |||||
| signet-shadow = drop-shadow(0 0 3px #222222) | |||||
| .heading | |||||
| font-size 2em | |||||
| @@ -1,5 +1,5 @@ | |||||
| <template> | <template> | ||||
| <div class="is-flex is-flex-direction-row is-justify-content-space-between"> | |||||
| <div> | |||||
| <div class="select mr-1"> | <div class="select mr-1"> | ||||
| <select | <select | ||||
| ref="queueOptions" | ref="queueOptions" | ||||
| @@ -25,13 +25,13 @@ | |||||
| > | > | ||||
| </div> | </div> | ||||
| <div v-else-if="queueSelection >= 0" class="is-flex-grow-1 ml-1"> | <div v-else-if="queueSelection >= 0" class="is-flex-grow-1 ml-1"> | ||||
| <Draggable :list="queueMembers" tag="div" class="edit-queue-list" @change="reorder"> | |||||
| <Draggable :list="queueMembers" tag="div" @change="reorder"> | |||||
| <div | <div | ||||
| class="p-2 has-background-grey-dark edit-queue-list-item" | class="p-2 has-background-grey-dark edit-queue-list-item" | ||||
| v-for="element in queueMembers" | v-for="element in queueMembers" | ||||
| :key="element.order" | :key="element.order" | ||||
| > | > | ||||
| <div class="is-flex is-flex-direction-row is-justify-content-space-between"> | |||||
| <div> | |||||
| <div>{{ element.title }} ({{ element.asset }})</div> | <div>{{ element.title }} ({{ element.asset }})</div> | ||||
| <div>{{ element.order }}</div> | <div>{{ element.order }}</div> | ||||
| </div> | </div> | ||||
| @@ -65,7 +65,7 @@ interface QueueMember { | |||||
| } | } | ||||
| // eslint-disable-next-line no-undef | // eslint-disable-next-line no-undef | ||||
| const props = defineProps<{ newMember: RewardFund & { order: number; } }>(); | |||||
| const props = defineProps<{ newMember: RewardFund & { order: number; } | undefined }>(); | |||||
| // eslint-disable-next-line no-undef | // eslint-disable-next-line no-undef | ||||
| const emits = defineEmits(['selected', 'created']); | const emits = defineEmits(['selected', 'created']); | ||||
| @@ -111,17 +111,20 @@ const populateQueueMembers = async (id: number) => { | |||||
| asset: m.asset, | asset: m.asset, | ||||
| order: m.order, | order: m.order, | ||||
| })); | })); | ||||
| serverQueues.value = queueMembers.value.length; | |||||
| if (queueMembers.value && props.newMember.title && props.newMember.asset) { | |||||
| const newMember = { | |||||
| id: undefined, | |||||
| title: props.newMember.title, | |||||
| asset: props.newMember.asset, | |||||
| order: queueMembers.value.length + 1, | |||||
| }; | |||||
| if (props.newMember) { | |||||
| serverQueues.value = queueMembers.value.length; | |||||
| if (queueMembers.value && props.newMember.title && props.newMember.asset) { | |||||
| const newMember = { | |||||
| id: undefined, | |||||
| title: props.newMember.title, | |||||
| asset: props.newMember.asset, | |||||
| order: queueMembers.value.length + 1, | |||||
| }; | |||||
| queueMembers.value.push(newMember); | |||||
| queueMembers.value.push(newMember); | |||||
| } | |||||
| } | } | ||||
| }; | }; | ||||
| @@ -134,7 +137,7 @@ watch(queueSelection, async (newValue) => { | |||||
| const addedMember = computed(() => props.newMember); | const addedMember = computed(() => props.newMember); | ||||
| watch(addedMember, (newVal) => { | watch(addedMember, (newVal) => { | ||||
| if (newVal.title && newVal.asset) { | |||||
| if (newVal && newVal.title && newVal.asset) { | |||||
| const assembleNewMember = (order: number) => ({ | const assembleNewMember = (order: number) => ({ | ||||
| id: undefined, | id: undefined, | ||||
| title: newVal.title, | title: newVal.title, | ||||
| @@ -1,9 +1,9 @@ | |||||
| <template> | <template> | ||||
| <article class="message is-danger"> | |||||
| <div class="message-header"> | |||||
| <article> | |||||
| <div> | |||||
| <p>Errors</p> | <p>Errors</p> | ||||
| </div> | </div> | ||||
| <div class="message-body"> | |||||
| <div> | |||||
| <ol class="ml-2"> | <ol class="ml-2"> | ||||
| <template v-for="(err, i) in props.errors" v-bind:key="i"> | <template v-for="(err, i) in props.errors" v-bind:key="i"> | ||||
| <li v-show="err.condition"> | <li v-show="err.condition"> | ||||
| @@ -1,25 +1,24 @@ | |||||
| <template> | <template> | ||||
| <div class="card py-2 px-4 has-text-dark" | |||||
| :style="generateBackgroundStyle(`${fund.asset} ${fund.title}`)"> | |||||
| <div class="is-size-2-desktop is-size-2-tablet is-size-3-mobile"> | |||||
| <div class="fund-link"> | |||||
| <div class="fund-name"> | |||||
| {{ fund.asset }} | {{ fund.asset }} | ||||
| </div> | </div> | ||||
| <div> | <div> | ||||
| <ul class="is-flex is-flex-direction-row is-justify-content-space-between"> | |||||
| <li class="is-size-7 is-inline-block px-2"> | |||||
| <span class="stellar-icon-base coin"></span> | |||||
| <ul class="fund-details"> | |||||
| <li> | |||||
| <svg-icon type="mdi" height="18" width="18" :path="mdiCircleMultipleOutline"/> | |||||
| <span class="fund-label">{{ props.fund.minContribution.toLocaleString() }}</span> | <span class="fund-label">{{ props.fund.minContribution.toLocaleString() }}</span> | ||||
| </li> | </li> | ||||
| <li class="is-size-7 is-inline-block px-2"> | |||||
| <span class="stellar-icon-base goal"></span> | |||||
| <li> | |||||
| <svg-icon type="mdi" height="18" width="18" :path="mdiBullseyeArrow"/> | |||||
| <span class="fund-label">{{ props.fund.amountAvailable.toLocaleString() }}</span> | <span class="fund-label">{{ props.fund.amountAvailable.toLocaleString() }}</span> | ||||
| </li> | </li> | ||||
| <li class="is-size-7 is-inline-block px-2"> | |||||
| <span class="stellar-icon-base memo"></span> | |||||
| <li> | |||||
| <svg-icon type="mdi" height="18" width="18" :path="mdiNoteTextOutline"/> | |||||
| <span class="fund-label">{{ props.fund.memo }}</span> | <span class="fund-label">{{ props.fund.memo }}</span> | ||||
| </li> | </li> | ||||
| <li class="is-size-7 is-inline-block px-2"> | |||||
| <span class="stellar-icon-base wallet"></span> | |||||
| <li> | |||||
| <svg-icon type="mdi" height="18" width="18" :path="mdiWalletOutline"/> | |||||
| <span class="fund-label"> | <span class="fund-label"> | ||||
| {{ truncateWallet(props.fund.fundWallet, 5, undefined) }} | {{ truncateWallet(props.fund.fundWallet, 5, undefined) }} | ||||
| </span> | </span> | ||||
| @@ -30,43 +29,69 @@ | |||||
| </template> | </template> | ||||
| <script setup lang="ts"> | <script setup lang="ts"> | ||||
| import { truncateWallet } from '@/lib/helpers'; | import { truncateWallet } from '@/lib/helpers'; | ||||
| import { | |||||
| FundInfo, | |||||
| } from '@/api/types'; | |||||
| import { FundInfo } from '@/api/types'; | |||||
| import { PropType } from 'vue'; | import { PropType } from 'vue'; | ||||
| import SvgIcon from '@jamescoyle/vue-icon'; | |||||
| import { | |||||
| mdiBullseyeArrow, | |||||
| mdiCircleMultipleOutline, | |||||
| mdiNoteTextOutline, | |||||
| mdiWalletOutline, | |||||
| } from '@mdi/js'; | |||||
| // eslint-disable-next-line no-undef | // eslint-disable-next-line no-undef | ||||
| const props = defineProps({ fund: Object as PropType<FundInfo> }); | const props = defineProps({ fund: Object as PropType<FundInfo> }); | ||||
| const generateHue = (seed: string) => seed.split('').map((c) => c.charCodeAt(0)).reduce((v1, v2) => v1 + v2) % 256; | |||||
| const generateHue = (seed: string) => seed.split('') | |||||
| .map((c) => c.charCodeAt(0)) | |||||
| .reduce((v1, v2) => v1 + v2) % 256; | |||||
| const generateBackgroundStyle = (hueSeed: string) => { | const generateBackgroundStyle = (hueSeed: string) => { | ||||
| const hue = generateHue(hueSeed); | const hue = generateHue(hueSeed); | ||||
| return `background-color: hsl(${hue}deg, 54%, 76%)`; | |||||
| return `background-color: hsl(${hue}deg, 32%, 47%)`; | |||||
| }; | }; | ||||
| </script> | </script> | ||||
| <style scoped lang="stylus"> | <style scoped lang="stylus"> | ||||
| @import "../assets/styles/general.styl" | |||||
| .fund-link | |||||
| background-color bg-color | |||||
| border-radius 8px | |||||
| overflow hidden | |||||
| filter signet-shadow | |||||
| .fund-name | |||||
| font-size 3em | |||||
| margin 0.4em | |||||
| color text-color | |||||
| font-family "Passion One Bold" | |||||
| font-weight 900 | |||||
| .fund-label | .fund-label | ||||
| color text-color | |||||
| vertical-align top | vertical-align top | ||||
| margin-left 6px | |||||
| .stellar-icon-base | |||||
| display inline-block | |||||
| height 20px | |||||
| width 20px | |||||
| margin-right 4px | |||||
| background-position center | |||||
| background-size 16px | |||||
| background-repeat no-repeat | |||||
| &.coin | |||||
| background-image url("../assets/icons8-expensive-24.png") | |||||
| .fund-details | |||||
| background-color secondary | |||||
| display flex | |||||
| flex-direction row | |||||
| justify-content space-between | |||||
| list-style none | |||||
| padding 4px 10px 2px 10px | |||||
| margin 0 | |||||
| vertical-align middle | |||||
| &.goal | |||||
| background-image url("../assets/icons8-goal-48.png") | |||||
| svg | |||||
| color text-color | |||||
| &.memo | |||||
| background-image url("../assets/icons8-note-24.png") | |||||
| @media screen and (max-width: 780px) | |||||
| .fund-label | |||||
| display inline-block | |||||
| font-size 12px | |||||
| vertical-align text-top | |||||
| &.wallet | |||||
| background-image url("../assets/icons8-wallet-24.png") | |||||
| @media screen and (max-width: 300px) | |||||
| .fund-label | |||||
| font-size 10px | |||||
| </style> | </style> | ||||
| @@ -1,36 +1,36 @@ | |||||
| <template> | <template> | ||||
| <div> | <div> | ||||
| <table class="table is-fullwidth"> | |||||
| <table> | |||||
| <thead> | <thead> | ||||
| <tr> | |||||
| <th>Goal Amount</th> | |||||
| <th>Percent Bonus</th> | |||||
| </tr> | |||||
| <tr> | |||||
| <th>Goal Amount</th> | |||||
| <th>Percent Bonus</th> | |||||
| </tr> | |||||
| </thead> | </thead> | ||||
| <tbody> | <tbody> | ||||
| <tr v-for="kv in bonuses" v-bind:key="kv.id"> | |||||
| <td class="p-0"> | |||||
| <input | |||||
| type="text" | |||||
| class="input is-small" | |||||
| v-model="kv.goal" | |||||
| :aria-label="`Goal #${bonuses.length}`" | |||||
| @input="checkInputs" | |||||
| @blur="saveValues" | |||||
| > | |||||
| </td> | |||||
| <td class="p-0"> | |||||
| <input | |||||
| type="text" | |||||
| class="input is-small" | |||||
| :class="kv.percent < 1 ? 'is-danger' : ''" | |||||
| v-model="kv.percent" | |||||
| :aria-label="`Cashback percent #${bonuses.length}`" | |||||
| @input="checkInputs" | |||||
| @blur="saveValues" | |||||
| > | |||||
| </td> | |||||
| </tr> | |||||
| <tr v-for="kv in bonuses" v-bind:key="kv.id"> | |||||
| <td class="p-0"> | |||||
| <input | |||||
| type="text" | |||||
| v-model="kv.goal" | |||||
| :aria-label="`Goal #${bonuses.length}`" | |||||
| @input="checkInputs" | |||||
| @blur="saveValues" | |||||
| > | |||||
| </td> | |||||
| <td class="p-0"> | |||||
| <input | |||||
| type="text" | |||||
| :class="kv.percent < 1 ? 'is-danger' : ''" | |||||
| v-model="kv.percent" | |||||
| :aria-label="`Cashback percent #${bonuses.length}`" | |||||
| @input="checkInputs" | |||||
| @blur="saveValues" | |||||
| > | |||||
| </td> | |||||
| </tr> | |||||
| </tbody> | </tbody> | ||||
| </table> | </table> | ||||
| </div> | </div> | ||||
| @@ -48,22 +48,33 @@ interface Bonus { | |||||
| // eslint-disable-next-line no-undef | // eslint-disable-next-line no-undef | ||||
| const emits = defineEmits(['save']); | const emits = defineEmits(['save']); | ||||
| const bonuses = ref([{ id: 1, goal: undefined, percent: undefined }] as Bonus[]); | |||||
| const bonuses = ref([{ | |||||
| id: 1, | |||||
| goal: undefined, | |||||
| percent: undefined, | |||||
| }] as Bonus[]); | |||||
| const getNextId = () => bonuses.value.length + 1; | const getNextId = () => bonuses.value.length + 1; | ||||
| const checkInputs = () => { | const checkInputs = () => { | ||||
| if (bonuses.value.every((b) => Object.values(b).every((v) => !!v))) { | |||||
| if (bonuses.value.every((b) => Object.values(b) | |||||
| .every((v) => !!v))) { | |||||
| bonuses.value.push({ | bonuses.value.push({ | ||||
| id: getNextId(), goal: undefined, percent: undefined, | |||||
| id: getNextId(), | |||||
| goal: undefined, | |||||
| percent: undefined, | |||||
| }); | }); | ||||
| } | } | ||||
| }; | }; | ||||
| const saveValues = () => { | const saveValues = () => { | ||||
| emits('save', bonuses.value.filter((b) => !!b.goal && !!b.percent).map((b) => ( | |||||
| { goal: parseFloat(b.goal as string), percent: parseFloat(b.percent as string) } | |||||
| ))); | |||||
| emits('save', bonuses.value.filter((b) => !!b.goal && !!b.percent) | |||||
| .map((b) => ( | |||||
| { | |||||
| goal: parseFloat(b.goal as string), | |||||
| percent: parseFloat(b.percent as string), | |||||
| } | |||||
| ))); | |||||
| }; | }; | ||||
| </script> | </script> | ||||
| @@ -1,5 +1,5 @@ | |||||
| <template> | <template> | ||||
| <div class="hello"> | |||||
| <div> | |||||
| <h1>{{ msg }}</h1> | <h1>{{ msg }}</h1> | ||||
| <p> | <p> | ||||
| For a guide and recipes on how to configure / customize this project,<br> | For a guide and recipes on how to configure / customize this project,<br> | ||||
| @@ -8,12 +8,18 @@ | |||||
| </p> | </p> | ||||
| <h3>Installed CLI Plugins</h3> | <h3>Installed CLI Plugins</h3> | ||||
| <ul> | <ul> | ||||
| <li><a href="https://github.com/vuejs/vue-cli/tree/dev/packages/%40vue/cli-plugin-babel" target="_blank" rel="noopener">babel</a></li> | |||||
| <li><a href="https://github.com/vuejs/vue-cli/tree/dev/packages/%40vue/cli-plugin-router" target="_blank" rel="noopener">router</a></li> | |||||
| <li><a href="https://github.com/vuejs/vue-cli/tree/dev/packages/%40vue/cli-plugin-vuex" target="_blank" rel="noopener">vuex</a></li> | |||||
| <li><a href="https://github.com/vuejs/vue-cli/tree/dev/packages/%40vue/cli-plugin-eslint" target="_blank" rel="noopener">eslint</a></li> | |||||
| <li><a href="https://github.com/vuejs/vue-cli/tree/dev/packages/%40vue/cli-plugin-unit-mocha" target="_blank" rel="noopener">unit-mocha</a></li> | |||||
| <li><a href="https://github.com/vuejs/vue-cli/tree/dev/packages/%40vue/cli-plugin-typescript" target="_blank" rel="noopener">typescript</a></li> | |||||
| <li><a href="https://github.com/vuejs/vue-cli/tree/dev/packages/%40vue/cli-plugin-babel" | |||||
| target="_blank" rel="noopener">babel</a></li> | |||||
| <li><a href="https://github.com/vuejs/vue-cli/tree/dev/packages/%40vue/cli-plugin-router" | |||||
| target="_blank" rel="noopener">router</a></li> | |||||
| <li><a href="https://github.com/vuejs/vue-cli/tree/dev/packages/%40vue/cli-plugin-vuex" | |||||
| target="_blank" rel="noopener">vuex</a></li> | |||||
| <li><a href="https://github.com/vuejs/vue-cli/tree/dev/packages/%40vue/cli-plugin-eslint" | |||||
| target="_blank" rel="noopener">eslint</a></li> | |||||
| <li><a href="https://github.com/vuejs/vue-cli/tree/dev/packages/%40vue/cli-plugin-unit-mocha" | |||||
| target="_blank" rel="noopener">unit-mocha</a></li> | |||||
| <li><a href="https://github.com/vuejs/vue-cli/tree/dev/packages/%40vue/cli-plugin-typescript" | |||||
| target="_blank" rel="noopener">typescript</a></li> | |||||
| </ul> | </ul> | ||||
| <h3>Essential Links</h3> | <h3>Essential Links</h3> | ||||
| <ul> | <ul> | ||||
| @@ -27,9 +33,11 @@ | |||||
| <ul> | <ul> | ||||
| <li><a href="https://router.vuejs.org" target="_blank" rel="noopener">vue-router</a></li> | <li><a href="https://router.vuejs.org" target="_blank" rel="noopener">vue-router</a></li> | ||||
| <li><a href="https://vuex.vuejs.org" target="_blank" rel="noopener">vuex</a></li> | <li><a href="https://vuex.vuejs.org" target="_blank" rel="noopener">vuex</a></li> | ||||
| <li><a href="https://github.com/vuejs/vue-devtools#vue-devtools" target="_blank" rel="noopener">vue-devtools</a></li> | |||||
| <li><a href="https://github.com/vuejs/vue-devtools#vue-devtools" target="_blank" | |||||
| rel="noopener">vue-devtools</a></li> | |||||
| <li><a href="https://vue-loader.vuejs.org" target="_blank" rel="noopener">vue-loader</a></li> | <li><a href="https://vue-loader.vuejs.org" target="_blank" rel="noopener">vue-loader</a></li> | ||||
| <li><a href="https://github.com/vuejs/awesome-vue" target="_blank" rel="noopener">awesome-vue</a></li> | |||||
| <li><a href="https://github.com/vuejs/awesome-vue" target="_blank" | |||||
| rel="noopener">awesome-vue</a></li> | |||||
| </ul> | </ul> | ||||
| </div> | </div> | ||||
| </template> | </template> | ||||
| @@ -1,31 +1,31 @@ | |||||
| <template> | <template> | ||||
| <div class="container is-max-desktop"> | |||||
| <section class="section is-small"> | |||||
| <div> | |||||
| <section> | |||||
| <div class="title is-4 has-text-white-ter has-text-centered">Add Fund</div> | <div class="title is-4 has-text-white-ter has-text-centered">Add Fund</div> | ||||
| <section class="section px-0 py-4"> | <section class="section px-0 py-4"> | ||||
| <div class="title is-5 has-text-white-ter">Post</div> | <div class="title is-5 has-text-white-ter">Post</div> | ||||
| <div class="control my-2"> | <div class="control my-2"> | ||||
| <input class="input is-normal has-background-white has-text-black" type="text" | |||||
| <input type="text" | |||||
| placeholder="Title" aria-label="Title" v-model="title"> | placeholder="Title" aria-label="Title" v-model="title"> | ||||
| </div> | </div> | ||||
| <div class="control my-2"> | <div class="control my-2"> | ||||
| <textarea class="textarea is-normal has-background-white has-text-black" | |||||
| placeholder="Description" aria-label="Description" v-model="description"> | |||||
| <textarea | |||||
| placeholder="Description" aria-label="Description" v-model="description"> | |||||
| </textarea> | </textarea> | ||||
| </div> | </div> | ||||
| </section> | </section> | ||||
| <section class="section px-0 py-4"> | <section class="section px-0 py-4"> | ||||
| <div class="title is-5 has-text-white-ter">Wallet</div> | <div class="title is-5 has-text-white-ter">Wallet</div> | ||||
| <div class="control my-2"> | <div class="control my-2"> | ||||
| <input class="input is-normal has-background-white has-text-black" type="text" | |||||
| <input type="text" | |||||
| placeholder="Fund Wallet" aria-label="Fund Wallet" v-model="fundWallet"> | placeholder="Fund Wallet" aria-label="Fund Wallet" v-model="fundWallet"> | ||||
| </div> | </div> | ||||
| <div class="control my-2"> | <div class="control my-2"> | ||||
| <input class="input is-normal has-background-white has-text-black" type="text" | |||||
| <input type="text" | |||||
| placeholder="Selling Wallet" aria-label="Selling Wallet" v-model="sellWallet"> | placeholder="Selling Wallet" aria-label="Selling Wallet" v-model="sellWallet"> | ||||
| </div> | </div> | ||||
| <div class="control my-2"> | <div class="control my-2"> | ||||
| <input class="input is-normal has-background-white has-text-black" type="text" | |||||
| <input type="text" | |||||
| placeholder="Issuer Wallet" aria-label="Issuer Wallet" v-model="issuerWallet"> | placeholder="Issuer Wallet" aria-label="Issuer Wallet" v-model="issuerWallet"> | ||||
| </div> | </div> | ||||
| </section> | </section> | ||||
| @@ -56,7 +56,7 @@ | |||||
| </section> | </section> | ||||
| <div class="buttons is-flex is-justify-content-end mt-5"> | <div class="buttons is-flex is-justify-content-end mt-5"> | ||||
| <button | <button | ||||
| class="button is-success" | |||||
| :class="requesting ? 'is-loading' : ''" | :class="requesting ? 'is-loading' : ''" | ||||
| @click="submit" | @click="submit" | ||||
| >Submit | >Submit | ||||
| @@ -1,8 +1,8 @@ | |||||
| <template> | <template> | ||||
| <!-- Unused --> | <!-- Unused --> | ||||
| <div class="is-flex is-flex-direction-row"> | |||||
| <nav class="is-hidden-tablet-only is-hidden-mobile has-background-white-ter"> | |||||
| <div class="has-background-primary"> | |||||
| <div> | |||||
| <nav> | |||||
| <div> | |||||
| <span class="has-text-white has-text-weight-bold my-4 mx-2">Administration</span> | <span class="has-text-white has-text-weight-bold my-4 mx-2">Administration</span> | ||||
| </div> | </div> | ||||
| <ul class="p-2"> | <ul class="p-2"> | ||||
| @@ -11,7 +11,7 @@ | |||||
| </li> | </li> | ||||
| </ul> | </ul> | ||||
| </nav> | </nav> | ||||
| <div class="container is-max-desktop"> | |||||
| <div> | |||||
| <RouterView></RouterView> | <RouterView></RouterView> | ||||
| </div> | </div> | ||||
| </div> | </div> | ||||
| @@ -19,9 +19,18 @@ | |||||
| <script setup lang="ts"> | <script setup lang="ts"> | ||||
| const links = [ | const links = [ | ||||
| { text: 'Add Fund', to: '/admin/addfund' }, | |||||
| { text: 'Modify Fund', to: '' }, | |||||
| { text: 'Create Tag', to: '' }, | |||||
| { | |||||
| text: 'Add Fund', | |||||
| to: '/admin/addfund', | |||||
| }, | |||||
| { | |||||
| text: 'Modify Fund', | |||||
| to: '', | |||||
| }, | |||||
| { | |||||
| text: 'Create Tag', | |||||
| to: '', | |||||
| }, | |||||
| ]; | ]; | ||||
| </script> | </script> | ||||
| @@ -0,0 +1,11 @@ | |||||
| <template> | |||||
| </template> | |||||
| <script setup lang="ts"> | |||||
| </script> | |||||
| <style scoped lang="stylus"> | |||||
| </style> | |||||
| @@ -0,0 +1,14 @@ | |||||
| <template> | |||||
| <EditQueue :new-member="member"/> | |||||
| </template> | |||||
| <script setup lang="ts"> | |||||
| import EditQueue from '@/components/EditQueue.vue'; | |||||
| const member = null; | |||||
| </script> | |||||
| <style scoped lang="stylus"> | |||||
| </style> | |||||
| @@ -1,48 +1,43 @@ | |||||
| <template> | <template> | ||||
| <div class="container is-max-desktop pb-4"> | |||||
| <section class="section is-small"> | |||||
| <div class="title is-size-4 has-text-white-ter has-text-centered"> | |||||
| <div> | |||||
| <section class="layout-section"> | |||||
| <div class="heading"> | |||||
| {{ fund.fundInfo.title }} | {{ fund.fundInfo.title }} | ||||
| </div> | </div> | ||||
| <div | |||||
| class="is-block-mobile | |||||
| is-flex-tablet-only | |||||
| is-flex-desktop | |||||
| is-flex-direction-row | |||||
| is-justify-content-space-between"> | |||||
| <div class="fund-description pr-5" v-html="fixNewlines(fund.fundInfo.description)"> | |||||
| </div> | |||||
| <div | |||||
| class="fund-details is-flex is-flex-direction-row is-justify-content-end my-auto py-6"> | |||||
| <ul> | |||||
| <li v-for="(detail, i) in fundDetails" v-bind:key="i"> | |||||
| <span class="has-text-weight-bold is-size-6 mr-2">{{ detail.title }}</span> | |||||
| <span class="is-size-6">{{ detail.val }}</span> | |||||
| <div> | |||||
| <p v-html="fixNewlines(fund.fundInfo.description)"></p> | |||||
| <div> | |||||
| <ul class="fund-details"> | |||||
| <li v-for="(detail, i) in fundDetails" :key="i" class="fund-detail"> | |||||
| <div class="detail-icon"> | |||||
| <svg-icon type="mdi" height="22" width="22" :path="detail.icon"/> | |||||
| </div> | |||||
| <div class="detail-text"> | |||||
| {{ detail.val }} | |||||
| </div> | |||||
| </li> | </li> | ||||
| </ul> | </ul> | ||||
| </div> | </div> | ||||
| </div> | </div> | ||||
| </section> | |||||
| <section> | |||||
| <div class="box"> | |||||
| <div class="title is-size-4 has-text-grey-dark has-text-centered"> | |||||
| <div> | |||||
| <div class="heading"> | |||||
| Tracker | Tracker | ||||
| </div> | </div> | ||||
| <div class="level" v-if="fund.fundInfo.bonuses.length > 0"> | |||||
| <div class="level-item has-text-centered" | |||||
| v-for="bonus in fund.fundInfo.bonuses.sort((v1, v2) => v1.goal - v2.goal)" | |||||
| v-bind:key="bonus.goal" | |||||
| <div v-if="fund.fundInfo.bonuses.length > 0"> | |||||
| <div | |||||
| v-for="bonus in fund.fundInfo.bonuses.sort((v1, v2) => v1.goal - v2.goal)" | |||||
| v-bind:key="bonus.goal" | |||||
| > | > | ||||
| <div> | <div> | ||||
| <p | <p | ||||
| class="heading" | |||||
| :class="amountHeld >= bonus.goal | :class="amountHeld >= bonus.goal | ||||
| ? 'has-text-success' : 'has-text-grey-dark'" | ? 'has-text-success' : 'has-text-grey-dark'" | ||||
| > | > | ||||
| {{ bonus.goal.toLocaleString() }} XLM | {{ bonus.goal.toLocaleString() }} XLM | ||||
| </p> | </p> | ||||
| <p | <p | ||||
| class="title" | |||||
| :class="amountHeld >= bonus.goal | :class="amountHeld >= bonus.goal | ||||
| ? 'has-text-success' : 'has-text-grey-dark'" | ? 'has-text-success' : 'has-text-grey-dark'" | ||||
| > | > | ||||
| @@ -52,15 +47,8 @@ | |||||
| </div> | </div> | ||||
| </div> | </div> | ||||
| </div> | </div> | ||||
| <div | |||||
| class="is-flex | |||||
| is-flex-direction-row | |||||
| is-justify-content-space-around | |||||
| is-size-4 | |||||
| has-text-white | |||||
| mb-3" | |||||
| > | |||||
| <div class="total"> | |||||
| <div> | |||||
| <div> | |||||
| <span class="total-label is-size-3 pr-2 has-text-weight-light"> | <span class="total-label is-size-3 pr-2 has-text-weight-light"> | ||||
| Raised | Raised | ||||
| </span> | </span> | ||||
| @@ -68,7 +56,7 @@ | |||||
| {{ amountHeld.toLocaleString() }} XLM | {{ amountHeld.toLocaleString() }} XLM | ||||
| </span> | </span> | ||||
| </div> | </div> | ||||
| <div class="remaining"> | |||||
| <div> | |||||
| <span class="remaining-label is-size-3 pr-2 has-text-weight-light"> | <span class="remaining-label is-size-3 pr-2 has-text-weight-light"> | ||||
| Remaining | Remaining | ||||
| </span> | </span> | ||||
| @@ -77,19 +65,17 @@ | |||||
| </span> | </span> | ||||
| </div> | </div> | ||||
| </div> | </div> | ||||
| </section> | |||||
| <section class="section is-small"> | |||||
| <div class="title is-size-4 has-text-white-ter has-text-centered"> | <div class="title is-size-4 has-text-white-ter has-text-centered"> | ||||
| Contribute | Contribute | ||||
| </div> | </div> | ||||
| <ErrorDisplay :errors="errs" v-if="invalidContributionForm"/> | <ErrorDisplay :errors="errs" v-if="invalidContributionForm"/> | ||||
| <div class="control my-2"> | <div class="control my-2"> | ||||
| <input class="input is-normal has-background-white has-text-black" type="text" | |||||
| <input type="text" | |||||
| placeholder="Private Key" aria-label="Wallet" v-model="pk" @blur="queryAccount"> | placeholder="Private Key" aria-label="Wallet" v-model="pk" @blur="queryAccount"> | ||||
| </div> | </div> | ||||
| <div class="control my-2" :class="loading.balance ? 'is-loading' : null"> | <div class="control my-2" :class="loading.balance ? 'is-loading' : null"> | ||||
| <input | <input | ||||
| class="input is-normal has-background-white has-text-black" | |||||
| type="number" | type="number" | ||||
| placeholder="Amount" | placeholder="Amount" | ||||
| aria-label="Amount" | aria-label="Amount" | ||||
| @@ -98,90 +84,89 @@ | |||||
| :disabled="loading.balance" | :disabled="loading.balance" | ||||
| > | > | ||||
| </div> | </div> | ||||
| <div class="is-flex is-justify-content-end"> | |||||
| <div> | |||||
| <button | <button | ||||
| class="button is-primary" | |||||
| :class="loading.contribution ? 'is-loading' : ''" | :class="loading.contribution ? 'is-loading' : ''" | ||||
| :disabled="invalidContributionForm" | :disabled="invalidContributionForm" | ||||
| @click="makeContribution" | @click="makeContribution" | ||||
| >Submit | >Submit | ||||
| </button> | </button> | ||||
| </div> | </div> | ||||
| </section> | |||||
| <section class="section is-small" v-if="contributions.length > 0"> | |||||
| <div class="title is-size-4 has-text-white-ter has-text-centered"> | |||||
| Contributions | |||||
| </div> | |||||
| <div class="is-flex is-justify-content-space-between is-rounded my-2"> | |||||
| <div class="select"> | |||||
| <select v-model="selectedDate" aria-label="Filter by date"> | |||||
| <option v-for="date in selectableDates" v-bind:key="date" :value="date"> | |||||
| {{ date ?? 'Cutoff Date' }} | |||||
| </option> | |||||
| </select> | |||||
| <section v-if="contributions.length > 0"> | |||||
| <div class="title is-size-4 has-text-white-ter has-text-centered"> | |||||
| Contributions | |||||
| </div> | </div> | ||||
| <div class="consolidate-option has-background-white px-4 py-1 my-auto"> | |||||
| <label for="consolidate" class="checkbox has-text-dark is-size-6"> | |||||
| <span class="consolidate-label is-inline-block"> | |||||
| <div class="is-flex is-justify-content-space-between is-rounded my-2"> | |||||
| <div> | |||||
| <select v-model="selectedDate" aria-label="Filter by date"> | |||||
| <option v-for="date in selectableDates" v-bind:key="date" :value="date"> | |||||
| {{ date ?? 'Cutoff Date' }} | |||||
| </option> | |||||
| </select> | |||||
| </div> | |||||
| <div class="consolidate-option has-background-white px-4 py-1 my-auto"> | |||||
| <label for="consolidate" class="checkbox has-text-dark is-size-6"> | |||||
| <span> | |||||
| Consolidate wallets | Consolidate wallets | ||||
| </span> | </span> | ||||
| <input | |||||
| type="checkbox" | |||||
| class="ml-2" | |||||
| id="consolidate" | |||||
| aria-label="Consolidate wallets" | |||||
| v-model="enableConsolidation" | |||||
| > | |||||
| </label> | |||||
| <input | |||||
| type="checkbox" | |||||
| class="ml-2" | |||||
| id="consolidate" | |||||
| aria-label="Consolidate wallets" | |||||
| v-model="enableConsolidation" | |||||
| > | |||||
| </label> | |||||
| </div> | |||||
| </div> | </div> | ||||
| </div> | |||||
| <div id="contribution-container" @scroll="loadMoreIfNeeded"> | |||||
| <table class="contribution-table table is-fullwidth"> | |||||
| <thead> | |||||
| <tr> | |||||
| <th>Wallet</th> | |||||
| <th>Amount</th> | |||||
| <th v-if="!enableConsolidation">Time</th> | |||||
| <th v-else>Tokens</th> | |||||
| </tr> | |||||
| </thead> | |||||
| <tbody> | |||||
| <tr v-for="(contribution, i) in contributions" v-bind:key="i"> | |||||
| <td>{{ truncateWallet(contribution.wallet, 6, undefined) }}</td> | |||||
| <td>{{ contribution.amount }}</td> | |||||
| <td v-if="!enableConsolidation"> | |||||
| <span class="transaction-date" :title="formatDate(contribution.createdAt, true)"> | |||||
| <div id="contribution-container" @scroll="loadMoreIfNeeded"> | |||||
| <table> | |||||
| <thead> | |||||
| <tr> | |||||
| <th>Wallet</th> | |||||
| <th>Amount</th> | |||||
| <th v-if="!enableConsolidation">Time</th> | |||||
| <th v-else>Tokens</th> | |||||
| </tr> | |||||
| </thead> | |||||
| <tbody> | |||||
| <tr v-for="(contribution, i) in contributions" v-bind:key="i"> | |||||
| <td>{{ truncateWallet(contribution.wallet, 6, undefined) }}</td> | |||||
| <td>{{ contribution.amount }}</td> | |||||
| <td v-if="!enableConsolidation"> | |||||
| <span :title="formatDate(contribution.createdAt, true)"> | |||||
| {{ formatDate(contribution.createdAt, true) }} | {{ formatDate(contribution.createdAt, true) }} | ||||
| </span> | </span> | ||||
| </td> | |||||
| <td v-else> | |||||
| <span>{{ calculateReward(contribution.amount / fund.fundInfo.price) }}</span> | |||||
| </td> | |||||
| </tr> | |||||
| </tbody> | |||||
| </table> | |||||
| </div> | |||||
| </section> | |||||
| <section v-if="store.getters.getToken && hasPermission(Privileges.AdminPlus)"> | |||||
| <div class="title is-size-4 has-text-white-ter has-text-centered"> | |||||
| Close Group Fund | |||||
| </div> | |||||
| <div class="box is-flex is-flex-direction-row is-justify-content-space-between"> | |||||
| <div class="my-auto"> | |||||
| <label class="checkbox" for="delete-confirm"> | |||||
| <input type="checkbox" id="delete-confirm" v-model="allowDelete"> Close | |||||
| </label> | |||||
| </td> | |||||
| <td v-else> | |||||
| <span>{{ calculateReward(contribution.amount / fund.fundInfo.price) }}</span> | |||||
| </td> | |||||
| </tr> | |||||
| </tbody> | |||||
| </table> | |||||
| </div> | |||||
| </section> | |||||
| <section v-if="store.getters.getToken && hasPermission(Privileges.AdminPlus)"> | |||||
| <div class="title is-size-4 has-text-white-ter has-text-centered"> | |||||
| Close Group Fund | |||||
| </div> | </div> | ||||
| <div> | <div> | ||||
| <button | |||||
| class="button is-danger" | |||||
| :disabled="!allowDelete" | |||||
| @click="deleteFund" | |||||
| > | |||||
| Close | |||||
| </button> | |||||
| <div> | |||||
| <label for="delete-confirm"> | |||||
| <input type="checkbox" id="delete-confirm" v-model="allowDelete"> Close | |||||
| </label> | |||||
| </div> | |||||
| <div> | |||||
| <button | |||||
| :disabled="!allowDelete" | |||||
| @click="deleteFund" | |||||
| > | |||||
| Close | |||||
| </button> | |||||
| </div> | |||||
| </div> | </div> | ||||
| </div> | |||||
| </section> | |||||
| </section> | </section> | ||||
| </div> | </div> | ||||
| </template> | </template> | ||||
| @@ -220,6 +205,13 @@ import { | |||||
| getContributions, | getContributions, | ||||
| getRewardFund, | getRewardFund, | ||||
| } from '@/api/composed'; | } from '@/api/composed'; | ||||
| import SvgIcon from '@jamescoyle/vue-icon'; | |||||
| import { | |||||
| mdiCircleMultipleOutline, | |||||
| mdiGreaterThanOrEqual, | |||||
| mdiNoteTextOutline, | |||||
| mdiTarget, | |||||
| } from '@mdi/js'; | |||||
| const route = useRoute(); | const route = useRoute(); | ||||
| const router = useRouter(); | const router = useRouter(); | ||||
| @@ -260,7 +252,7 @@ const fund = ref( | |||||
| } as GetRewardFundResponse | null, | } as GetRewardFundResponse | null, | ||||
| ); | ); | ||||
| const fundDetails = ref([{ | const fundDetails = ref([{ | ||||
| title: '', | |||||
| icon: '', | |||||
| val: '', | val: '', | ||||
| }]); | }]); | ||||
| @@ -271,19 +263,19 @@ if (!fund.value) { | |||||
| } | } | ||||
| fundDetails.value = [ | fundDetails.value = [ | ||||
| { | { | ||||
| title: 'Asset', | |||||
| icon: mdiCircleMultipleOutline, | |||||
| val: fund.value.fundInfo.asset, | val: fund.value.fundInfo.asset, | ||||
| }, | }, | ||||
| { | { | ||||
| title: 'Min', | |||||
| icon: mdiGreaterThanOrEqual, | |||||
| val: `${fund.value.fundInfo.minContribution.toLocaleString()}`, | val: `${fund.value.fundInfo.minContribution.toLocaleString()}`, | ||||
| }, | }, | ||||
| { | { | ||||
| title: 'Goal', | |||||
| icon: mdiTarget, | |||||
| val: `${fund.value.fundInfo.amountAvailable.toLocaleString()}`, | val: `${fund.value.fundInfo.amountAvailable.toLocaleString()}`, | ||||
| }, | }, | ||||
| { | { | ||||
| title: 'Memo', | |||||
| icon: mdiNoteTextOutline, | |||||
| val: `"${fund.value.fundInfo.memo}"`, | val: `"${fund.value.fundInfo.memo}"`, | ||||
| }, | }, | ||||
| ]; | ]; | ||||
| @@ -528,14 +520,27 @@ watch(data, (newVal) => { | |||||
| min-height 280px | min-height 280px | ||||
| .fund-details | .fund-details | ||||
| width 182px | |||||
| display flex | |||||
| flex-direction row | |||||
| justify-content space-around | |||||
| background-color darkorange | |||||
| border-radius 4px | |||||
| list-style-type none | |||||
| margin 0 | |||||
| padding 8px 4px | |||||
| .detail-icon | |||||
| display flex | |||||
| justify-content center | |||||
| color #fff | |||||
| margin-bottom 8px | |||||
| .detail-text | |||||
| font-size 16px | |||||
| text-align center | |||||
| color #fff | |||||
| font-family "Passion One" | |||||
| #consolidate | #consolidate | ||||
| vertical-align middle | vertical-align middle | ||||
| @media screen and (min-width: 1024px) | |||||
| .fund-details | |||||
| max-width 14vw | |||||
| border-left 1px #777 solid | |||||
| padding-left 10px | |||||
| </style> | </style> | ||||
| @@ -1,8 +1,8 @@ | |||||
| <template> | <template> | ||||
| <div class="container is-max-desktop"> | |||||
| <section class="section is-small px-0"> | |||||
| <div> | |||||
| <section class="layout-section"> | |||||
| <div class="container-grid" v-if="rewardFunds"> | <div class="container-grid" v-if="rewardFunds"> | ||||
| <template v-for="fund in rewardFunds" v-bind:key="fund.id"> | |||||
| <template v-for="fund in rewardFunds" :key="fund.id"> | |||||
| <RouterLink :to="`/fund/${fund.id}`"> | <RouterLink :to="`/fund/${fund.id}`"> | ||||
| <FundLink :fund="fund"/> | <FundLink :fund="fund"/> | ||||
| </RouterLink> | </RouterLink> | ||||
| @@ -36,11 +36,14 @@ offset.value = total; | |||||
| <style scoped lang="stylus"> | <style scoped lang="stylus"> | ||||
| .container-grid | .container-grid | ||||
| display grid | display grid | ||||
| grid-template-columns: repeat(2, 1fr); | |||||
| gap: 10px; | |||||
| grid-auto-rows: 120px; | |||||
| grid-template-columns: repeat(2, 1fr) | |||||
| gap: 10px | |||||
| grid-auto-rows: 120px | |||||
| @media screen and (max-width: 768px) | |||||
| a | |||||
| text-decoration none | |||||
| @media screen and (max-width: 680px) | |||||
| .container-grid | .container-grid | ||||
| display flex | display flex | ||||
| flex-direction column | flex-direction column | ||||
| @@ -1,17 +1,17 @@ | |||||
| <template> | <template> | ||||
| <div class="container is-max-desktop"> | |||||
| <section class="section is-large"> | |||||
| <div> | |||||
| <section> | |||||
| <div class="title is-4 has-text-white-ter has-text-centered">Login</div> | <div class="title is-4 has-text-white-ter has-text-centered">Login</div> | ||||
| <div class="control my-2"> | <div class="control my-2"> | ||||
| <input class="input is-medium" type="text" placeholder="Username" | |||||
| <input type="text" placeholder="Username" | |||||
| aria-label="Username" v-model="username" @keyup.enter="submit"> | aria-label="Username" v-model="username" @keyup.enter="submit"> | ||||
| </div> | </div> | ||||
| <div class="control my-2"> | <div class="control my-2"> | ||||
| <input class="input is-medium" type="password" placeholder="Password" | |||||
| <input type="password" placeholder="Password" | |||||
| aria-label="Password" v-model="password" @keyup.enter="submit"> | aria-label="Password" v-model="password" @keyup.enter="submit"> | ||||
| </div> | </div> | ||||
| <div class="buttons is-flex is-justify-content-end mt-5"> | <div class="buttons is-flex is-justify-content-end mt-5"> | ||||
| <button class="button is-success" @click="submit">Submit</button> | |||||
| <button @click="submit">Submit</button> | |||||
| </div> | </div> | ||||
| </section> | </section> | ||||
| </div> | </div> | ||||
| @@ -1,17 +1,17 @@ | |||||
| <template> | <template> | ||||
| <div class="container is-max-desktop"> | |||||
| <section class="section is-large"> | |||||
| <div> | |||||
| <section> | |||||
| <div class="title is-4 has-text-white-ter has-text-centered">Register</div> | <div class="title is-4 has-text-white-ter has-text-centered">Register</div> | ||||
| <div class="control my-2"> | <div class="control my-2"> | ||||
| <input class="input is-medium" type="text" placeholder="Username" | |||||
| <input type="text" placeholder="Username" | |||||
| aria-label="Username" v-model="username"> | aria-label="Username" v-model="username"> | ||||
| </div> | </div> | ||||
| <div class="control my-2"> | <div class="control my-2"> | ||||
| <input class="input is-medium" type="password" placeholder="Password" | |||||
| <input type="password" placeholder="Password" | |||||
| aria-label="Password" v-model="password"> | aria-label="Password" v-model="password"> | ||||
| </div> | </div> | ||||
| <div class="buttons is-flex is-justify-content-end mt-5"> | <div class="buttons is-flex is-justify-content-end mt-5"> | ||||
| <button class="button is-success" @click="submit">Submit</button> | |||||
| <button @click="submit">Submit</button> | |||||
| </div> | </div> | ||||
| </section> | </section> | ||||
| </div> | </div> | ||||
| @@ -1002,6 +1002,11 @@ | |||||
| resolved "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-1.2.1.tgz" | resolved "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-1.2.1.tgz" | ||||
| integrity sha512-ZnQMnLV4e7hDlUvw8H+U8ASL02SS2Gn6+9Ac3wGGLIe7+je2AeAOxPY+izIPJDfFDb7eDjev0Us8MO1iFRN8hA== | integrity sha512-ZnQMnLV4e7hDlUvw8H+U8ASL02SS2Gn6+9Ac3wGGLIe7+je2AeAOxPY+izIPJDfFDb7eDjev0Us8MO1iFRN8hA== | ||||
| "@jamescoyle/vue-icon@^0.1.2": | |||||
| version "0.1.2" | |||||
| resolved "https://registry.yarnpkg.com/@jamescoyle/vue-icon/-/vue-icon-0.1.2.tgz#b9e254187de6716b81bf9e0e8400ec012231bd05" | |||||
| integrity sha512-KFrImXx5TKIi6iQXlnyLEBl4rNosNKbTeRnr70ucTdUaciVmd9qK9d/pZAaKt1Ob/8xNnX2GMp8LisyHdKtEgw== | |||||
| "@jridgewell/gen-mapping@^0.1.0": | "@jridgewell/gen-mapping@^0.1.0": | ||||
| version "0.1.1" | version "0.1.1" | ||||
| resolved "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.1.1.tgz" | resolved "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.1.1.tgz" | ||||
| @@ -1055,10 +1060,10 @@ | |||||
| resolved "https://registry.npmjs.org/@leichtgewicht/ip-codec/-/ip-codec-2.0.4.tgz" | resolved "https://registry.npmjs.org/@leichtgewicht/ip-codec/-/ip-codec-2.0.4.tgz" | ||||
| integrity sha512-Hcv+nVC0kZnQ3tD9GVu5xSMR4VVYOteQIr/hwFPVEvPdlXqgGEuRjiheChHgdM+JyqdgNcmzZOX/tnl0JOiI7A== | integrity sha512-Hcv+nVC0kZnQ3tD9GVu5xSMR4VVYOteQIr/hwFPVEvPdlXqgGEuRjiheChHgdM+JyqdgNcmzZOX/tnl0JOiI7A== | ||||
| "@mdi/js@^7.0.96": | |||||
| version "7.0.96" | |||||
| resolved "https://registry.npmjs.org/@mdi/js/-/js-7.0.96.tgz" | |||||
| integrity sha512-lNqhkV3cpPfYb/Avh+vXLFukUTbHbyHoFo4Jdc7Oc9UvURGVhamFIpgOVvEf2bNA78zvjXTZeVWExUTR+DLBfQ== | |||||
| "@mdi/js@^7.1.96": | |||||
| version "7.1.96" | |||||
| resolved "https://registry.yarnpkg.com/@mdi/js/-/js-7.1.96.tgz#9c5a7f8a20ea63c03b09a0dba1768fe8b70eeaf9" | |||||
| integrity sha512-wlrJs6Ryhaa5CqhK3FjTfMRnb/s7HeLkKMFqwQySkK86cdN1TGdzpSM3O4tsmzCA1dYBeTbXvOwSE/Y42cUrvA== | |||||
| "@node-ipc/js-queue@2.0.3": | "@node-ipc/js-queue@2.0.3": | ||||
| version "2.0.3" | version "2.0.3" | ||||
| @@ -2440,11 +2445,6 @@ buffer@^5.5.0: | |||||
| base64-js "^1.3.1" | base64-js "^1.3.1" | ||||
| ieee754 "^1.1.13" | ieee754 "^1.1.13" | ||||
| bulma@^0.9.4: | |||||
| version "0.9.4" | |||||
| resolved "https://registry.npmjs.org/bulma/-/bulma-0.9.4.tgz" | |||||
| integrity sha512-86FlT5+1GrsgKbPLRRY7cGDg8fsJiP/jzTqXXVqiUZZ2aZT8uemEOHlU1CDU+TxklPEZ11HZNNWclRBBecP4CQ== | |||||
| bytes@3.0.0: | bytes@3.0.0: | ||||
| version "3.0.0" | version "3.0.0" | ||||
| resolved "https://registry.npmjs.org/bytes/-/bytes-3.0.0.tgz" | resolved "https://registry.npmjs.org/bytes/-/bytes-3.0.0.tgz" | ||||