initial commit

This commit is contained in:
Inshal
2024-10-25 19:58:19 +05:00
commit 2046156f90
1558 changed files with 210706 additions and 0 deletions

View File

@@ -0,0 +1,63 @@
<script setup>
const bufferValue = ref(20)
const progressValue = ref(10)
const isFallbackState = ref(false)
const interval = ref()
const showProgress = ref(false)
watch([
progressValue,
isFallbackState,
], () => {
if (progressValue.value > 80 && isFallbackState.value)
progressValue.value = 82
startBuffer()
})
function startBuffer() {
clearInterval(interval.value)
interval.value = setInterval(() => {
progressValue.value += Math.random() * (15 - 5) + 5
bufferValue.value += Math.random() * (15 - 5) + 6
}, 800)
}
const fallbackHandle = () => {
showProgress.value = true
progressValue.value = 10
isFallbackState.value = true
startBuffer()
}
const resolveHandle = () => {
isFallbackState.value = false
progressValue.value = 100
setTimeout(() => {
clearInterval(interval.value)
progressValue.value = 0
bufferValue.value = 20
showProgress.value = false
}, 300)
}
defineExpose({
fallbackHandle,
resolveHandle,
})
</script>
<template>
<!-- loading state via #fallback slot -->
<div
v-if="showProgress"
class="position-fixed"
style="z-index: 9999; inset-block-start: 0; inset-inline: 0 0;"
>
<VProgressLinear
v-model="progressValue"
:buffer-value="bufferValue"
color="primary"
height="2"
bg-color="background"
/>
</div>
</template>

View File

@@ -0,0 +1,272 @@
<script setup>
import tree1 from '@images/misc/pricing-tree-1.png'
import tree2 from '@images/misc/pricing-tree-2.png'
import tree3 from '@images/misc/pricing-tree-3.png'
const props = defineProps({
title: {
type: String,
required: false,
},
cols: {
type: [
Number,
String,
],
required: false,
},
sm: {
type: [
Number,
String,
],
required: false,
},
md: {
type: [
String,
Number,
],
required: false,
},
lg: {
type: [
String,
Number,
],
required: false,
},
xl: {
type: [
String,
Number,
],
required: false,
},
})
const annualMonthlyPlanPriceToggler = ref(true)
const pricingPlans = [
{
name: 'Basic',
tagLine: 'A simple start for everyone',
logo: tree1,
monthlyPrice: 0,
yearlyPrice: 0,
isPopular: false,
current: true,
features: [
'100 responses a month',
'Unlimited forms and surveys',
'Unlimited fields',
'Basic form creation tools',
'Up to 2 subdomains',
],
},
{
name: 'Standard',
tagLine: 'For small to medium businesses',
logo: tree2,
monthlyPrice: 42,
yearlyPrice: 460,
isPopular: true,
current: false,
features: [
'Unlimited responses',
'Unlimited forms and surveys',
'Instagram profile page',
'Google Docs integration',
'Custom “Thank you” page',
],
},
{
name: 'Enterprise',
tagLine: 'Solution for big organizations',
logo: tree3,
monthlyPrice: 84,
yearlyPrice: 690,
isPopular: false,
current: false,
features: [
'PayPal payments',
'Logic Jumps',
'File upload with 5GB storage',
'Custom domain support',
'Stripe integration',
],
},
]
</script>
<template>
<!-- 👉 Title and subtitle -->
<div class="text-center mb-6">
<slot name="heading">
<h3 class="text-h3 pricing-title pb-2">
{{ props.title ? props.title : 'Pricing Plans' }}
</h3>
</slot>
<slot name="subtitle">
<p class="mb-0">
All plans include 40+ advanced tools and features to boost your product.
<br>
Choose the best plan to fit your needs.
</p>
</slot>
</div>
<!-- 👉 Annual and monthly price toggler -->
<div class="d-flex align-center justify-center mx-auto pt-sm-9 pb-sm-8 py-4">
<VLabel
for="pricing-plan-toggle"
class="me-2 font-weight-medium"
>
Monthly
</VLabel>
<div class="position-relative">
<div class="pricing-save-chip position-absolute d-sm-block d-none">
<VIcon
start
icon="ri-corner-left-down-fill"
size="24"
class="text-disabled flip-in-rtl mt-1"
/>
<VChip
size="small"
color="primary"
class="mt-n2"
>
Save up to 10%
</VChip>
</div>
<VSwitch
id="pricing-plan-toggle"
v-model="annualMonthlyPlanPriceToggler"
>
<template #label>
<div class="text-body-1 font-weight-medium">
Annually
</div>
</template>
</VSwitch>
</div>
</div>
<!-- SECTION pricing plans -->
<VRow>
<VCol
v-for="plan in pricingPlans"
:key="plan.logo"
v-bind="props"
>
<!-- 👉 Card -->
<VCard
flat
border
:class="plan.isPopular ? 'border-primary border-opacity-100' : ''"
>
<VCardText
class="text-end pt-4"
style="block-size: 3.75rem;"
>
<!-- 👉 Popular -->
<VChip
v-show="plan.isPopular"
color="primary"
size="small"
>
Popular
</VChip>
</VCardText>
<!-- 👉 Plan logo -->
<VCardText class="text-center">
<VImg
:height="120"
:src="plan.logo"
class="mx-auto mb-5"
/>
<!-- 👉 Plan name -->
<h4 class="text-h4 mb-1">
{{ plan.name }}
</h4>
<p class="mb-0 text-body-1">
{{ plan.tagLine }}
</p>
</VCardText>
<!-- 👉 Plan price -->
<VCardText class="position-relative text-center">
<div>
<div class="d-flex justify-center align-center">
<span class="text-body-1 font-weight-medium align-self-start">$</span>
<h1 class="text-h1 font-weight-medium text-primary">
{{ annualMonthlyPlanPriceToggler ? Math.floor(Number(plan.yearlyPrice) / 12) : plan.monthlyPrice }}
</h1>
<span class="text-body-1 font-weight-medium align-self-end">/month</span>
</div>
<!-- 👉 Annual Price -->
<div
v-show="annualMonthlyPlanPriceToggler"
class="text-caption"
>
{{ plan.yearlyPrice === 0 ? 'free' : `USD ${plan.yearlyPrice}/Year` }}
</div>
</div>
</VCardText>
<!-- 👉 Plan features -->
<VCardText class="pt-2">
<VList class="card-list pb-5">
<VListItem
v-for="feature in plan.features"
:key="feature"
>
<template #prepend />
<VListItemTitle class="text-body-1 d-flex align-center">
<VIcon
:size="14"
icon="ri-circle-line"
class="me-2"
/>
<div class="text-truncate">
{{ feature }}
</div>
</VListItemTitle>
</VListItem>
</VList>
<!-- 👉 Plan actions -->
<VBtn
:active="false"
block
:color="plan.current ? 'success' : 'primary'"
:variant="plan.isPopular ? 'elevated' : 'outlined'"
:to="{ name: 'front-pages-payment' }"
>
{{ plan.yearlyPrice === 0 ? 'Your Current Plan' : 'Upgrade' }}
</VBtn>
</VCardText>
</VCard>
</VCol>
</VRow>
<!-- !SECTION -->
</template>
<style lang="scss" scoped>
.card-list {
--v-card-list-gap: 1rem;
}
.pricing-save-chip {
display: flex;
inset-block-start: -2.625rem;
inset-inline-end: -6.5rem;
}
</style>

View File

@@ -0,0 +1,86 @@
<script setup>
import AppSearchHeaderBgDark from '@images/pages/app-search-header-bg-dark.png'
import AppSearchHeaderBgLight from '@images/pages/app-search-header-bg-light.png'
const props = defineProps({
title: {
type: String,
required: false,
},
subtitle: {
type: String,
required: false,
},
customClass: {
type: String,
required: false,
},
placeholder: {
type: String,
required: false,
default: 'Ask a question..',
},
})
defineOptions({
inheritAttrs: false,
})
const themeBackgroundImg = useGenerateImageVariant(AppSearchHeaderBgLight, AppSearchHeaderBgDark)
</script>
<template>
<!-- 👉 Search Banner -->
<VCard
flat
class="text-center search-header"
:class="customClass"
:style="`background: url(${themeBackgroundImg});`"
>
<VCardText>
<slot>
<h4 class="text-h4 text-primary">
{{ title }}
</h4>
<!-- 👉 Search Input -->
<VTextField
v-bind="$attrs"
:placeholder="placeholder"
class="search-header-input mx-auto my-4"
>
<template #prepend-inner>
<VIcon
icon="ri-search-line"
size="18"
/>
</template>
</VTextField>
<p class="text-body-1">
{{ subtitle }}
</p>
</slot>
</VCardText>
</VCard>
</template>
<style lang="scss">
.search-header {
padding: 4rem !important;
background-size: cover !important;
}
// search input
.search-header-input {
border-radius: 0.25rem !important;
background-color: rgb(var(--v-theme-surface));
max-inline-size: 32.125rem;
}
@media (max-width: 37.5rem) {
.search-header {
padding: 1.5rem !important;
}
}
</style>

View File

@@ -0,0 +1,53 @@
<script setup>
const props = defineProps({
statusCode: {
type: [
String,
Number,
],
required: false,
},
title: {
type: String,
required: false,
},
description: {
type: String,
required: false,
},
})
</script>
<template>
<div class="text-center mb-4">
<!-- 👉 Title and subtitle -->
<h1
v-if="props.statusCode"
class="error-title mb-2"
>
{{ props.statusCode }}
</h1>
<h4
v-if="props.title"
class="text-h4 mb-2"
>
{{ props.title }}
</h4>
<p
v-if="props.description"
class="mb-0 text-body-1"
>
{{ props.description }}
</p>
</div>
</template>
<style lang="scss" scoped>
.error-title {
font-size: 6rem;
font-weight: 500;
line-height: 1;
}
</style>

View File

@@ -0,0 +1,114 @@
<script setup>
import themeselectionQr from '@images/pages/themeselection-qr.png'
const props = defineProps({
authCode: {
type: String,
required: false,
},
isDialogVisible: {
type: Boolean,
required: true,
},
})
const emit = defineEmits([
'update:isDialogVisible',
'submit',
])
const authCode = ref(structuredClone(toRaw(props.authCode)))
const formSubmit = () => {
if (authCode.value) {
emit('submit', authCode.value)
emit('update:isDialogVisible', false)
}
}
const resetAuthCode = () => {
authCode.value = structuredClone(toRaw(props.authCode))
emit('update:isDialogVisible', false)
}
</script>
<template>
<VDialog
max-width="900"
:model-value="props.isDialogVisible"
@update:model-value="(val) => $emit('update:isDialogVisible', val)"
>
<VCard class="pa-sm-11 pa-3">
<!-- 👉 dialog close btn -->
<DialogCloseBtn
variant="text"
size="default"
@click="resetAuthCode"
/>
<VCardText class="pt-5">
<h4 class="text-h4 text-center mb-6">
Add Authenticator App
</h4>
<h5 class="text-h5 font-weight-medium mb-2">
Authenticator Apps
</h5>
<p class="mb-6">
Using an authenticator app like Google Authenticator, Microsoft Authenticator, Authy, or 1Password, scan the QR code. It will generate a 6 digit code for you to enter below.
</p>
<div class="my-6">
<VImg
width="150"
:src="themeselectionQr"
class="mx-auto"
/>
</div>
<VAlert
color="warning"
variant="tonal"
class="my-4"
>
<template #title>
ASDLKNASDA9AHS678dGhASD78AB
</template>
If you're having trouble using the QR code, select manual entry on your app
</VAlert>
<VForm @submit.prevent="() => {}">
<VTextField
v-model="authCode"
name="auth-code"
label="Enter Authentication Code"
placeholder="123 456"
class="mb-8"
/>
<div class="d-flex justify-end flex-wrap gap-4">
<VBtn
color="secondary"
variant="outlined"
@click="resetAuthCode"
>
Cancel
</VBtn>
<VBtn
type="submit"
@click="formSubmit"
>
Submit
<VIcon
end
icon="ri-check-line"
class="flip-in-rtl"
/>
</VBtn>
</div>
</VForm>
</VCardText>
</VCard>
</VDialog>
</template>

View File

@@ -0,0 +1,230 @@
<script setup>
const props = defineProps({
billingAddress: {
type: Object,
required: false,
default: () => ({
firstName: '',
lastName: '',
selectedCountry: null,
addressLine1: '',
addressLine2: '',
landmark: '',
contact: '',
country: null,
state: '',
zipCode: null,
}),
},
isDialogVisible: {
type: Boolean,
required: true,
},
})
const emit = defineEmits([
'update:isDialogVisible',
'submit',
])
const billingAddress = ref(structuredClone(toRaw(props.billingAddress)))
const resetForm = () => {
emit('update:isDialogVisible', false)
billingAddress.value = structuredClone(toRaw(props.billingAddress))
}
const onFormSubmit = () => {
emit('update:isDialogVisible', false)
emit('submit', billingAddress.value)
}
const selectedAddress = ref('Home')
const addressTypes = [
{
title: 'Home',
desc: 'Delivery Time (7am - 9pm)',
value: 'Home',
icon: 'ri-home-smile-2-line',
},
{
title: 'Office',
desc: 'Delivery Time (10am - 6pm)',
value: 'Office',
icon: 'ri-building-line',
},
]
</script>
<template>
<VDialog
:width="$vuetify.display.smAndDown ? 'auto' : 900 "
:model-value="props.isDialogVisible"
@update:model-value="val => $emit('update:isDialogVisible', val)"
>
<VCard
v-if="props.billingAddress"
class="pa-sm-11 pa-3"
>
<VCardText class="pt-5">
<!-- 👉 dialog close btn -->
<!-- 👉 Title -->
<div class="text-center mb-6">
<h4 class="text-h4 mb-2">
{{ props.billingAddress.firstName ? 'Edit' : 'Add New' }} Address
</h4>
<p class="text-body-1">
Add Address for future billing
</p>
</div>
<CustomRadios
v-model:selected-radio="selectedAddress"
:radio-content="addressTypes"
:grid-column="{ sm: '6', cols: '12' }"
class="mb-5"
>
<template #default="items">
<div class="d-flex flex-column">
<div class="d-flex mb-2 align-center gap-x-1">
<VIcon
:icon="items.item.icon"
size="20"
/>
<div class="text-body-1 font-weight-medium text-high-emphasis">
{{ items.item.title }}
</div>
</div>
<p class="text-body-2 mb-0">
{{ items.item.desc }}
</p>
</div>
</template>
</CustomRadios>
<!-- 👉 Form -->
<VForm @submit.prevent="onFormSubmit">
<VRow>
<!-- 👉 First Name -->
<VCol
cols="12"
md="6"
>
<VTextField
v-model="billingAddress.firstName"
label="First Name"
placeholder="John"
/>
</VCol>
<!-- 👉 Last Name -->
<VCol
cols="12"
md="6"
>
<VTextField
v-model="billingAddress.lastName"
label="Last Name"
placeholder="Doe"
/>
</VCol>
<!-- 👉 Select country -->
<VCol cols="12">
<VSelect
v-model="billingAddress.selectedCountry"
label="Select Country"
placeholder="Select Country"
:items="['USA', 'Canada', 'NZ', 'Aus']"
/>
</VCol>
<!-- 👉 Address Line 1 -->
<VCol cols="12">
<VTextField
v-model="billingAddress.addressLine1"
label="Address Line 1"
placeholder="1, New Street"
/>
</VCol>
<!-- 👉 Address Line 2 -->
<VCol cols="12">
<VTextField
v-model="billingAddress.addressLine2"
label="Address Line 2"
placeholder="Near hospital"
/>
</VCol>
<!-- 👉 Landmark -->
<VCol cols="12">
<VTextField
v-model="billingAddress.landmark"
label="Landmark & City"
placeholder="Near hospital, New York"
/>
</VCol>
<!-- 👉 State -->
<VCol
cols="12"
md="6"
>
<VTextField
v-model="billingAddress.state"
label="State/Province"
placeholder="New York"
/>
</VCol>
<!-- 👉 Zip Code -->
<VCol
cols="12"
md="6"
>
<VTextField
v-model="billingAddress.zipCode"
label="Zip Code"
placeholder="123123"
type="number"
/>
</VCol>
<VCol cols="12">
<VSwitch label="Make this default shipping address" />
</VCol>
<!-- 👉 Submit and Cancel button -->
<VCol
cols="12"
class="text-center"
>
<VBtn
type="submit"
class="me-3"
>
submit
</VBtn>
<VBtn
variant="outlined"
color="secondary"
@click="resetForm"
>
Cancel
</VBtn>
</VCol>
</VRow>
</VForm>
</VCardText>
</VCard>
</VDialog>
</template>

View File

@@ -0,0 +1,101 @@
<script setup>
const props = defineProps({
isDialogVisible: {
type: Boolean,
required: true,
},
permissionName: {
type: String,
required: false,
default: '',
},
})
const emit = defineEmits([
'update:isDialogVisible',
'update:permissionName',
])
const currentPermissionName = ref('')
const onReset = () => {
emit('update:isDialogVisible', false)
currentPermissionName.value = ''
}
const onSubmit = () => {
emit('update:isDialogVisible', false)
emit('update:permissionName', currentPermissionName.value)
}
watch(props, () => {
currentPermissionName.value = props.permissionName
})
</script>
<template>
<VDialog
:width="$vuetify.display.smAndDown ? 'auto' : 600"
:model-value="props.isDialogVisible"
@update:model-value="onReset"
>
<VCard class="pa-sm-8 pa-5">
<!-- 👉 dialog close btn -->
<DialogCloseBtn
variant="text"
size="default"
@click="onReset"
/>
<VCardText class="mt-5">
<!-- 👉 Title -->
<div class="text-center mb-6">
<h4 class="text-h4 mb-2">
{{ props.permissionName ? 'Edit' : 'Add' }} Permission
</h4>
<p class="text-body-1">
{{ props.permissionName ? 'Edit' : 'Add' }} permission as per your requirements.
</p>
</div>
<!-- 👉 Form -->
<VForm>
<VAlert
type="warning"
title="Warning!"
variant="tonal"
class="mb-6"
>
By editing the permission name, you might break the system permissions functionality. Please ensure you're absolutely certain before proceeding.
</VAlert>
<!-- 👉 Role name -->
<div class="d-flex align-center gap-4 mb-4">
<VTextField
v-model="currentPermissionName"
density="compact"
placeholder="Enter Permission Name"
/>
<VBtn @click="onSubmit">
Update
</VBtn>
</div>
<VCheckbox label="Set as core permission" />
</VForm>
</VCardText>
</VCard>
</VDialog>
</template>
<style lang="scss">
.permission-table {
td {
border-block-end: 1px solid rgba(var(--v-border-color), var(--v-border-opacity));
padding-block: 0.5rem;
padding-inline: 0;
}
}
</style>

View File

@@ -0,0 +1,294 @@
<script setup>
import { VForm } from 'vuetify/components/VForm'
const props = defineProps({
rolePermissions: {
type: Object,
required: false,
default: () => ({
name: '',
permissions: [],
}),
},
isDialogVisible: {
type: Boolean,
required: true,
},
})
const emit = defineEmits([
'update:isDialogVisible',
'update:rolePermissions',
])
// 👉 Permission List
const permissions = ref([
{
name: 'User Management',
read: false,
write: false,
create: false,
},
{
name: 'Content Management',
read: false,
write: false,
create: false,
},
{
name: 'Disputes Management',
read: false,
write: false,
create: false,
},
{
name: 'Database Management',
read: false,
write: false,
create: false,
},
{
name: 'Financial Management',
read: false,
write: false,
create: false,
},
{
name: 'Reporting',
read: false,
write: false,
create: false,
},
{
name: 'API Control',
read: false,
write: false,
create: false,
},
{
name: 'Repository Management',
read: false,
write: false,
create: false,
},
{
name: 'Payroll',
read: false,
write: false,
create: false,
},
])
const isSelectAll = ref(false)
const role = ref('')
const refPermissionForm = ref()
const checkedCount = computed(() => {
let counter = 0
permissions.value.forEach(permission => {
Object.entries(permission).forEach(([key, value]) => {
if (key !== 'name' && value)
counter++
})
})
return counter
})
const isIndeterminate = computed(() => checkedCount.value > 0 && checkedCount.value < permissions.value.length * 3)
// select all
watch(isSelectAll, val => {
permissions.value = permissions.value.map(permission => ({
...permission,
read: val,
write: val,
create: val,
}))
})
// if Indeterminate is false, then set isSelectAll to false
watch(isIndeterminate, () => {
if (!isIndeterminate.value)
isSelectAll.value = false
})
// if all permissions are checked, then set isSelectAll to true
watch(permissions, () => {
if (checkedCount.value === permissions.value.length * 3)
isSelectAll.value = true
}, { deep: true })
// if rolePermissions is not empty, then set permissions
watch(props, () => {
if (props.rolePermissions && props.rolePermissions.permissions.length) {
role.value = props.rolePermissions.name
permissions.value = permissions.value.map(permission => {
const rolePermission = props.rolePermissions?.permissions.find(item => item.name === permission.name)
if (rolePermission) {
return {
...permission,
...rolePermission,
}
}
return permission
})
}
})
const onSubmit = () => {
const rolePermissions = {
name: role.value,
permissions: permissions.value,
}
emit('update:rolePermissions', rolePermissions)
emit('update:isDialogVisible', false)
isSelectAll.value = false
refPermissionForm.value?.reset()
}
const onReset = () => {
emit('update:isDialogVisible', false)
isSelectAll.value = false
refPermissionForm.value?.reset()
}
</script>
<template>
<VDialog
:width="$vuetify.display.smAndDown ? 'auto' : 900"
:model-value="props.isDialogVisible"
@update:model-value="onReset"
>
<VCard class="pa-sm-8 pa-5">
<!-- 👉 dialog close btn -->
<DialogCloseBtn
variant="text"
size="default"
@click="onReset"
/>
<VCardText class="mt-5">
<!-- 👉 Title -->
<div class="text-center mb-6">
<h4 class="text-h4 mb-2">
{{ props.rolePermissions.name ? 'Edit' : 'Add' }} Role
</h4>
<p class="text-body-1">
{{ props.rolePermissions.name ? 'Edit' : 'Add' }} Role
</p>
</div>
<!-- 👉 Form -->
<VForm ref="refPermissionForm">
<!-- 👉 Role name -->
<VTextField
v-model="role"
label="Role Name"
placeholder="Enter Role Name"
/>
<h5 class="text-h5 my-6">
Role Permissions
</h5>
<!-- 👉 Role Permissions -->
<VTable class="permission-table text-no-wrap">
<!-- 👉 Admin -->
<tr>
<td class="text-h6">
Administrator Access
</td>
<td colspan="3">
<div class="d-flex justify-end">
<VCheckbox
v-model="isSelectAll"
v-model:indeterminate="isIndeterminate"
label="Select All"
/>
</div>
</td>
</tr>
<!-- 👉 Other permission loop -->
<template
v-for="permission in permissions"
:key="permission.name"
>
<tr>
<td class="text-h6">
{{ permission.name }}
</td>
<td style="inline-size: 5.75rem;">
<div class="d-flex justify-end">
<VCheckbox
v-model="permission.read"
label="Read"
/>
</div>
</td>
<td style="inline-size: 5.75rem;">
<div class="d-flex justify-end">
<VCheckbox
v-model="permission.write"
label="Write"
/>
</div>
</td>
<td style="inline-size: 5.75rem;">
<div class="d-flex justify-end">
<VCheckbox
v-model="permission.create"
label="Create"
/>
</div>
</td>
</tr>
</template>
</VTable>
<!-- 👉 Actions button -->
<div class="d-flex align-center justify-center gap-3 mt-6">
<VBtn @click="onSubmit">
Submit
</VBtn>
<VBtn
color="secondary"
variant="outlined"
@click="onReset"
>
Cancel
</VBtn>
</div>
</VForm>
</VCardText>
</VCard>
</VDialog>
</template>
<style lang="scss">
.permission-table {
td {
border-block-end: 1px solid rgba(var(--v-border-color), var(--v-border-opacity));
padding-block: 0.5rem;
.v-checkbox {
min-inline-size: 4.75rem;
}
&:not(:first-child) {
padding-inline: 0.5rem;
}
.v-label {
white-space: nowrap;
}
}
}
</style>

View File

@@ -0,0 +1,122 @@
<script setup>
import americanExDark from '@images/icons/payments/img/ae-dark.png'
import americanExLight from '@images/icons/payments/img/american-express.png'
import dcDark from '@images/icons/payments/img/dc-dark.png'
import dcLight from '@images/icons/payments/img/dc-light.png'
import jcbDark from '@images/icons/payments/img/jcb-dark.png'
import jcbLight from '@images/icons/payments/img/jcb-light.png'
import masterCardDark from '@images/icons/payments/img/master-dark.png'
import masterCardLight from '@images/icons/payments/img/mastercard.png'
import visaDark from '@images/icons/payments/img/visa-dark.png'
import visaLight from '@images/icons/payments/img/visa-light.png'
const props = defineProps({
isDialogVisible: {
type: Boolean,
required: true,
},
})
const emit = defineEmits(['update:isDialogVisible'])
const visa = useGenerateImageVariant(visaLight, visaDark)
const masterCard = useGenerateImageVariant(masterCardLight, masterCardDark)
const americanEx = useGenerateImageVariant(americanExLight, americanExDark)
const jcb = useGenerateImageVariant(jcbLight, jcbDark)
const dc = useGenerateImageVariant(dcLight, dcDark)
const dialogVisibleUpdate = val => {
emit('update:isDialogVisible', val)
}
const paymentMethodsData = [
{
title: 'Visa',
type: 'Credit Card',
img: visa,
},
{
title: 'American Express',
type: 'Credit Card',
img: americanEx,
},
{
title: 'Mastercard',
type: 'Credit Card',
img: masterCard,
},
{
title: 'JCB',
type: 'Credit Card',
img: jcb,
},
{
title: 'Diners Club',
type: 'Credit Card',
img: dc,
},
]
</script>
<template>
<VDialog
:model-value="props.isDialogVisible"
max-width="900"
@update:model-value="dialogVisibleUpdate"
>
<VCard class="refer-and-earn-dialog">
<!-- 👉 dialog close btn -->
<DialogCloseBtn
variant="text"
size="default"
@click="emit('update:isDialogVisible', false)"
/>
<VCardText class="pa-8 pa-sm-16">
<div class="mb-6">
<h4 class="text-h4 text-center mb-2">
Add payment methods
</h4>
<p class="text-sm-body-1 text-center">
Supported payment methods
</p>
</div>
<div
v-for="(item, index) in paymentMethodsData"
:key="index"
>
<div class="d-flex justify-space-between align-center py-4 gap-x-4">
<div class="d-flex align-center">
<VImg
:src="item.img.value"
height="30"
width="50"
class="me-4"
/>
<div class="text-body-1 font-weight-medium text-high-emphasis">
{{ item.title }}
</div>
</div>
<div class="d-none d-sm-block text-body-1">
{{ item.type }}
</div>
</div>
<VDivider v-show="index !== paymentMethodsData.length - 1" />
</div>
</VCardText>
</VCard>
</VDialog>
</template>
<style lang="scss">
.refer-link-input {
.v-field--appended {
padding-inline-end: 0;
}
.v-field__append-inner {
padding-block-start: 0.125rem;
}
}
</style>

View File

@@ -0,0 +1,143 @@
<script setup>
const props = defineProps({
cardDetails: {
type: Object,
required: false,
default: () => ({
number: '',
name: '',
expiry: '',
cvv: '',
isPrimary: false,
type: '',
}),
},
isDialogVisible: {
type: Boolean,
required: true,
},
})
const emit = defineEmits([
'submit',
'update:isDialogVisible',
])
const cardDetails = ref(structuredClone(toRaw(props.cardDetails)))
watch(props, () => {
cardDetails.value = structuredClone(toRaw(props.cardDetails))
})
const formSubmit = () => {
emit('submit', cardDetails.value)
}
</script>
<template>
<VDialog
:width="$vuetify.display.smAndDown ? 'auto' : 600"
:model-value="props.isDialogVisible"
@update:model-value="val => $emit('update:isDialogVisible', val)"
>
<VCard class="pa-sm-11 pa-3">
<!-- 👉 dialog close btn -->
<DialogCloseBtn
variant="text"
size="default"
@click="$emit('update:isDialogVisible', false)"
/>
<VCardText class="pt-5">
<!-- 👉 Title -->
<div class="text-center mb-6">
<h4 class="text-h4 mb-2">
{{ props.cardDetails.name ? 'Edit Card' : 'Add New Card' }}
</h4>
<div class="text-body-1">
{{ props.cardDetails.name ? 'Edit your saved card details' : 'Add your saved card details' }}
</div>
</div>
<VForm @submit.prevent="() => {}">
<VRow>
<!-- 👉 Card Number -->
<VCol cols="12">
<VTextField
v-model="cardDetails.number"
label="Card Number"
placeholder="1234 1234 1234 1234"
/>
</VCol>
<!-- 👉 Card Name -->
<VCol
cols="12"
md="6"
>
<VTextField
v-model="cardDetails.name"
label="Name"
placeholder="John Doe"
/>
</VCol>
<!-- 👉 Card Expiry -->
<VCol
cols="6"
md="3"
>
<VTextField
v-model="cardDetails.expiry"
label="Expiry"
placeholder="MM/YY"
/>
</VCol>
<!-- 👉 Card CVV -->
<VCol
cols="6"
md="3"
>
<VTextField
v-model="cardDetails.cvv"
type="number"
label="CVV"
placeholder="123"
/>
</VCol>
<!-- 👉 Card Primary Set -->
<VCol cols="12">
<VSwitch
v-model="cardDetails.isPrimary"
label="Save Card for future billing?"
/>
</VCol>
<!-- 👉 Card actions -->
<VCol
cols="12"
class="text-center"
>
<VBtn
class="me-4"
type="submit"
@click="formSubmit"
>
Submit
</VBtn>
<VBtn
color="secondary"
variant="outlined"
@click="$emit('update:isDialogVisible', false)"
>
Cancel
</VBtn>
</VCol>
</VRow>
</VForm>
</VCardText>
</VCard>
</VDialog>
</template>

View File

@@ -0,0 +1,164 @@
<script setup>
const props = defineProps({
confirmationQuestion: {
type: String,
required: true,
},
isDialogVisible: {
type: Boolean,
required: true,
},
confirmTitle: {
type: String,
required: true,
},
confirmMsg: {
type: String,
required: true,
},
cancelTitle: {
type: String,
required: true,
},
cancelMsg: {
type: String,
required: true,
},
})
const emit = defineEmits([
'update:isDialogVisible',
'confirm',
])
const unsubscribed = ref(false)
const cancelled = ref(false)
const updateModelValue = val => {
emit('update:isDialogVisible', val)
}
const onConfirmation = () => {
emit('confirm', true)
updateModelValue(false)
unsubscribed.value = true
}
const onCancel = () => {
emit('confirm', false)
emit('update:isDialogVisible', false)
cancelled.value = true
}
</script>
<template>
<!-- 👉 Confirm Dialog -->
<VDialog
max-width="500"
:model-value="props.isDialogVisible"
@update:model-value="updateModelValue"
>
<VCard class="text-center px-10 py-6">
<VCardText>
<VBtn
icon
variant="outlined"
color="warning"
class="my-4"
size="x-large"
>
<span class="text-4xl">!</span>
</VBtn>
<h6 class="text-lg font-weight-medium">
{{ props.confirmationQuestion }}
</h6>
</VCardText>
<VCardText class="d-flex align-center justify-center gap-4">
<VBtn
variant="elevated"
@click="onConfirmation"
>
Confirm
</VBtn>
<VBtn
color="secondary"
variant="outlined"
@click="onCancel"
>
Cancel
</VBtn>
</VCardText>
</VCard>
</VDialog>
<!-- Unsubscribed -->
<VDialog
v-model="unsubscribed"
max-width="500"
>
<VCard>
<VCardText class="text-center px-10 py-6">
<VBtn
icon
variant="outlined"
color="success"
class="my-4"
size="x-large"
>
<span class="text-xl">
<VIcon icon="ri-check-line" />
</span>
</VBtn>
<h1 class="text-h4 mb-4">
{{ props.confirmTitle }}
</h1>
<p>{{ props.confirmMsg }}</p>
<VBtn
color="success"
@click="unsubscribed = false"
>
Ok
</VBtn>
</VCardText>
</VCard>
</VDialog>
<!-- Cancelled -->
<VDialog
v-model="cancelled"
max-width="500"
>
<VCard>
<VCardText class="text-center px-10 py-6">
<VBtn
icon
variant="outlined"
color="error"
class="my-4"
size="x-large"
>
<span class="text-2xl font-weight-light">X</span>
</VBtn>
<h1 class="text-h4 mb-4">
{{ props.cancelTitle }}
</h1>
<p>{{ props.cancelMsg }}</p>
<VBtn
color="success"
@click="cancelled = false"
>
Ok
</VBtn>
</VCardText>
</VCard>
</VDialog>
</template>

View File

@@ -0,0 +1,446 @@
<script setup>
import illustrationJohn from '@images/pages/illustration-john.png'
import angularIcon from '@images/icons/brands/angular.png'
import laravelIcon from '@images/icons/brands/laravel.png'
import reactIcon from '@images/icons/brands/react.png'
import vueIcon from '@images/icons/brands/vue.png'
import awsIcon from '@images/icons/brands/aws.png'
import firebaseIcon from '@images/icons/brands/firebase.png'
import mysqlIcon from '@images/icons/brands/mysql.png'
const props = defineProps({
isDialogVisible: {
type: Boolean,
required: true,
},
})
const emit = defineEmits([
'update:isDialogVisible',
'updatedData',
])
const currentStep = ref(0)
const createApp = [
{
icon: 'ri-file-text-line',
title: 'Details',
subtitle: 'Enter Details',
},
{
icon: 'ri-star-smile-line',
title: 'Frameworks',
subtitle: 'Select Framework',
},
{
icon: 'ri-pie-chart-2-line',
title: 'Database',
subtitle: 'Select Database',
},
{
icon: 'ri-bank-card-line',
title: 'Billing',
subtitle: 'Payment Details',
},
{
icon: 'ri-check-double-line',
title: 'Submit',
subtitle: 'submit',
},
]
const categories = [
{
icon: 'ri-bar-chart-box-line',
color: 'info',
title: 'CRM Application',
subtitle: 'Scales with any business',
slug: 'crm-application',
},
{
icon: 'ri-shopping-cart-line',
color: 'success',
title: 'Ecommerce Platforms',
subtitle: 'Grow Your Business With App',
slug: 'ecommerce-application',
},
{
icon: 'ri-video-upload-line',
color: 'error',
title: 'Online Learning platform',
subtitle: 'Start learning today',
slug: 'online-learning-application',
},
]
const frameworks = [
{
icon: reactIcon,
color: 'info',
title: 'React Native',
subtitle: 'Create truly native apps',
slug: 'react-framework',
},
{
icon: angularIcon,
color: 'error',
title: 'Angular',
subtitle: 'Most suited for your application',
slug: 'angular-framework',
},
{
icon: vueIcon,
color: 'success',
title: 'Vue',
subtitle: 'Progressive Framework',
slug: 'vue-framework',
},
{
icon: laravelIcon,
color: 'warning',
title: 'Laravel',
subtitle: 'PHP web frameworks',
slug: 'laravel-framework',
},
]
const databases = [
{
icon: firebaseIcon,
color: 'warning',
title: 'Firebase',
subtitle: 'Cloud Firestore',
slug: 'firebase-database',
},
{
icon: awsIcon,
color: 'secondary',
title: 'AWS',
subtitle: 'Amazon Fast NoSQL Database',
slug: 'aws-database',
},
{
icon: mysqlIcon,
color: 'info',
title: 'MySQL',
subtitle: 'Basic MySQL database',
slug: 'mysql-database',
},
]
const createAppData = ref({
category: 'crm-application',
framework: 'vue-framework',
database: 'firebase-database',
cardNumber: null,
cardName: '',
cardExpiry: '',
cardCvv: '',
isSave: false,
})
const dialogVisibleUpdate = val => {
emit('update:isDialogVisible', val)
currentStep.value = 0
}
watch(props, () => {
if (!props.isDialogVisible)
currentStep.value = 0
})
const onSubmit = () => {
alert('submitted...!!')
emit('updatedData', createAppData.value)
}
</script>
<template>
<VDialog
:model-value="props.isDialogVisible"
max-width="900"
@update:model-value="dialogVisibleUpdate"
>
<VCard class="create-app-dialog pa-sm-11 pa-3">
<!-- 👉 dialog close btn -->
<DialogCloseBtn
variant="text"
size="default"
@click="emit('update:isDialogVisible', false)"
/>
<VCardText class="pt-5">
<div class="text-center mb-6">
<h4 class="text-h4 text-center mb-2">
Create App
</h4>
<div class="text-body-1">
Provide data with this form to create your app.
</div>
</div>
<VRow>
<VCol
cols="12"
sm="5"
md="4"
>
<AppStepper
v-model:current-step="currentStep"
direction="vertical"
:items="createApp"
icon-size="24"
class="stepper-icon-step-bg"
/>
</VCol>
<VCol
cols="12"
sm="7"
md="8"
>
<VWindow
v-model="currentStep"
class="disable-tab-transition stepper-content"
>
<!-- 👉 category -->
<VWindowItem>
<VTextField
label="Application Name"
placeholder="myRider"
/>
<h5 class="text-h5 mb-4 mt-8">
Category
</h5>
<VRadioGroup v-model="createAppData.category">
<VList class="card-list">
<VListItem
v-for="category in categories"
:key="category.title"
@click="createAppData.category = category.slug"
>
<template #prepend>
<VAvatar
size="46"
rounded
variant="tonal"
:color="category.color"
:icon="category.icon"
/>
</template>
<VListItemTitle class="font-weight-medium mb-1">
{{ category.title }}
</VListItemTitle>
<VListItemSubtitle class="text-body-2 me-2">
{{ category.subtitle }}
</VListItemSubtitle>
<template #append>
<VRadio :value="category.slug" />
</template>
</VListItem>
</VList>
</VRadioGroup>
</VWindowItem>
<!-- 👉 Frameworks -->
<VWindowItem>
<h5 class="text-h5 mb-4">
Select Framework
</h5>
<VRadioGroup v-model="createAppData.framework">
<VList class="card-list">
<VListItem
v-for="framework in frameworks"
:key="framework.title"
@click="createAppData.framework = framework.slug"
>
<template #prepend>
<VAvatar
size="46"
rounded
variant="tonal"
:color="framework.color"
>
<img :src="framework.icon">
</VAvatar>
</template>
<VListItemTitle class="mb-1 font-weight-medium">
{{ framework.title }}
</VListItemTitle>
<VListItemSubtitle class="me-2">
{{ framework.subtitle }}
</VListItemSubtitle>
<template #append>
<VRadio :value="framework.slug" />
</template>
</VListItem>
</VList>
</VRadioGroup>
</VWindowItem>
<!-- 👉 Database Engine -->
<VWindowItem>
<VTextField
label="Database Name"
placeholder="userDB"
/>
<h5 class="text-h5 mt-8 mb-4">
Select Database Engine
</h5>
<VRadioGroup v-model="createAppData.database">
<VList class="card-list">
<VListItem
v-for="database in databases"
:key="database.title"
@click="createAppData.database = database.slug"
>
<template #prepend>
<VAvatar
size="46"
rounded
variant="tonal"
:color="database.color"
>
<img :src="database.icon">
</VAvatar>
</template>
<VListItemTitle class="mb-1 font-weight-medium">
{{ database.title }}
</VListItemTitle>
<VListItemSubtitle class="me-2">
{{ database.subtitle }}
</VListItemSubtitle>
<template #append>
<VRadio :value="database.slug" />
</template>
</VListItem>
</VList>
</VRadioGroup>
</VWindowItem>
<!-- 👉 Billing form -->
<VWindowItem>
<VForm>
<VRow>
<VCol cols="12">
<VTextField
v-model="createAppData.cardNumber"
label="Card Number"
placeholder="1234 1234 1234 1234"
type="number"
/>
</VCol>
<VCol
cols="12"
md="6"
>
<VTextField
v-model="createAppData.cardName"
label="Name on Card"
placeholder="John Doe"
/>
</VCol>
<VCol
cols="6"
md="3"
>
<VTextField
v-model="createAppData.cardExpiry"
label="Expiry"
placeholder="MM/YY"
/>
</VCol>
<VCol
cols="6"
md="3"
>
<VTextField
v-model="createAppData.cardCvv"
label="CVV"
placeholder="123"
/>
</VCol>
<VCol cols="12">
<VSwitch
v-model="createAppData.isSave"
label="Save Card for future billing?"
/>
</VCol>
</VRow>
</VForm>
</VWindowItem>
<VWindowItem class="text-center">
<h5 class="text-h5 mb-2">
Submit 🥳
</h5>
<p class="text-body-2 mb-4">
Submit to kickstart your project.
</p>
<VImg
:src="illustrationJohn"
width="252"
class="mx-auto"
/>
</VWindowItem>
</VWindow>
<div class="d-flex justify-space-between mt-6">
<VBtn
variant="outlined"
color="secondary"
:disabled="currentStep === 0"
@click="currentStep--"
>
<VIcon
icon="ri-arrow-left-line"
start
class="flip-in-rtl"
/>
Previous
</VBtn>
<VBtn
v-if="createApp.length - 1 === currentStep"
color="success"
append-icon="ri-check-line"
@click="onSubmit"
>
submit
</VBtn>
<VBtn
v-else
@click="currentStep++"
>
Next
<VIcon
icon="ri-arrow-right-line"
end
class="flip-in-rtl"
/>
</VBtn>
</div>
</VCol>
</VRow>
</VCardText>
</VCard>
</VDialog>
</template>
<style lang="scss">
.stepper-content .card-list {
--v-card-list-gap: 1rem;
}
</style>

View File

@@ -0,0 +1,91 @@
<script setup>
const props = defineProps({
mobileNumber: {
type: String,
required: false,
},
isDialogVisible: {
type: Boolean,
required: true,
},
})
const emit = defineEmits([
'update:isDialogVisible',
'submit',
])
const phoneNumber = ref(structuredClone(toRaw(props.mobileNumber)))
const formSubmit = () => {
if (phoneNumber.value) {
emit('submit', phoneNumber.value)
emit('update:isDialogVisible', false)
}
}
const resetPhoneNumber = () => {
phoneNumber.value = structuredClone(toRaw(props.mobileNumber))
emit('update:isDialogVisible', false)
}
</script>
<template>
<VDialog
max-width="900"
:model-value="props.isDialogVisible"
@update:model-value="(val) => $emit('update:isDialogVisible', val)"
>
<VCard class="pa-5 pa-sm-11">
<!-- 👉 dialog close btn -->
<DialogCloseBtn
variant="text"
size="default"
@click="resetPhoneNumber"
/>
<VCardText class="pt-5">
<div class="mb-6">
<h5 class="text-h5 mb-2">
Verify Your Mobile Number for SMS
</h5>
<div>
Enter your mobile phone number with country code and we will send you a verification code.
</div>
</div>
<VForm @submit.prevent="() => {}">
<VTextField
v-model="phoneNumber"
name="mobile"
label="Phone Number"
placeholder="+1 123 456 7890"
class="mb-8"
/>
<div class="d-flex flex-wrap justify-end gap-3">
<VBtn
color="secondary"
variant="outlined"
@click="resetPhoneNumber"
>
Cancel
</VBtn>
<VBtn
color="success"
type="submit"
@click="formSubmit"
>
Submit
<VIcon
end
icon="ri-check-line"
class="flip-in-rtl"
/>
</VBtn>
</div>
</VForm>
</VCardText>
</VCard>
</VDialog>
</template>

View File

@@ -0,0 +1,165 @@
<script setup>
import americanExDark from '@images/icons/payments/img/ae-dark.png'
import americanExLight from '@images/icons/payments/img/american-express.png'
import dcDark from '@images/icons/payments/img/dc-dark.png'
import dcLight from '@images/icons/payments/img/dc-light.png'
import jcbDark from '@images/icons/payments/img/jcb-dark.png'
import jcbLight from '@images/icons/payments/img/jcb-light.png'
import masterCardDark from '@images/icons/payments/img/master-dark.png'
import masterCardLight from '@images/icons/payments/img/mastercard.png'
import visaDark from '@images/icons/payments/img/visa-dark.png'
import visaLight from '@images/icons/payments/img/visa-light.png'
const props = defineProps({
isDialogVisible: {
type: Boolean,
required: true,
},
})
const emit = defineEmits(['update:isDialogVisible'])
const visa = useGenerateImageVariant(visaLight, visaDark)
const masterCard = useGenerateImageVariant(masterCardLight, masterCardDark)
const americanEx = useGenerateImageVariant(americanExLight, americanExDark)
const jcb = useGenerateImageVariant(jcbLight, jcbDark)
const dc = useGenerateImageVariant(dcLight, dcDark)
const dialogVisibleUpdate = val => {
emit('update:isDialogVisible', val)
}
const paymentProvidersData = [
{
title: 'Adyen',
providers: [
visa,
masterCard,
americanEx,
jcb,
dc,
],
},
{
title: '2Checkout',
providers: [
visa,
americanEx,
jcb,
dc,
],
},
{
title: 'Airpay',
providers: [
visa,
americanEx,
masterCard,
jcb,
],
},
{
title: 'Authorize.net',
providers: [
americanEx,
jcb,
dc,
],
},
{
title: 'Bambora',
providers: [
masterCard,
americanEx,
jcb,
],
},
{
title: 'Bambora',
providers: [
visa,
masterCard,
americanEx,
jcb,
dc,
],
},
{
title: 'Chase Paymentech (Orbital)',
providers: [
visa,
americanEx,
jcb,
dc,
],
},
{
title: 'Checkout.com',
providers: [
visa,
masterCard,
],
},
]
</script>
<template>
<VDialog
:model-value="props.isDialogVisible"
max-width="900"
@update:model-value="dialogVisibleUpdate"
>
<VCard class="refer-and-earn-dialog pa-3 pa-sm-11">
<!-- 👉 dialog close btn -->
<DialogCloseBtn
variant="text"
size="default"
@click="emit('update:isDialogVisible', false)"
/>
<VCardText class="pt-5">
<div class="mb-6">
<h4 class="text-h4 text-center mb-2">
Select Payment Providers
</h4>
<p class="text-sm-body-1 text-center">
Third-party payment providers
</p>
</div>
<div
v-for="(item, index) in paymentProvidersData"
:key="index"
>
<div class="d-flex flex-column flex-sm-row justify-space-between align-sm-center align-start gap-4 flex-wrap py-4">
<div class="text-high-emphasis font-weight-medium">
{{ item.title }}
</div>
<div class="d-flex gap-x-4 gap-y-2 flex-wrap">
<img
v-for="(img, iterator) in item.providers"
:key="iterator"
:src="img.value"
height="30"
width="50"
>
</div>
</div>
<VDivider v-show="index !== paymentProvidersData.length - 1" />
</div>
</VCardText>
</VCard>
</VDialog>
</template>
<style lang="scss">
.refer-link-input {
.v-field--appended {
padding-inline-end: 0;
}
.v-field__append-inner {
padding-block-start: 0.125rem;
}
}
</style>

View File

@@ -0,0 +1,50 @@
<script setup>
const props = defineProps({
isDialogVisible: {
type: Boolean,
required: true,
},
})
const emit = defineEmits(['update:isDialogVisible'])
const dialogVisibleUpdate = val => {
emit('update:isDialogVisible', val)
}
</script>
<template>
<VDialog
:model-value="props.isDialogVisible"
class="v-dialog-xl"
@update:model-value="dialogVisibleUpdate"
>
<VCard class="pricing-dialog pa-2 pa-sm-11">
<!-- 👉 dialog close btn -->
<DialogCloseBtn
variant="text"
size="default"
@click="emit('update:isDialogVisible', false)"
/>
<VCardText class="pt-5">
<AppPricing
title="Pricing Plan"
md="4"
cols="12"
>
<template #heading>
<h4 class="text-h4 pb-2">
Pricing Plans
</h4>
</template>
<template #subtitle>
<div class="text-body-1">
All plans include 40+ advanced tools and features to boost your product. Choose the best plan to fit your needs.
</div>
</template>
</AppPricing>
</VCardText>
</VCard>
</VDialog>
</template>

View File

@@ -0,0 +1,186 @@
<script setup>
const props = defineProps({
isDialogVisible: {
type: Boolean,
required: true,
},
})
const emit = defineEmits(['update:isDialogVisible'])
const dialogVisibleUpdate = val => {
emit('update:isDialogVisible', val)
}
const referAndEarnSteps = [
{
icon: 'ri-send-plane-2-line',
title: 'Send Invitation 👍🏻',
subtitle: 'Send your referral link to your friend',
},
{
icon: 'ri-pages-line',
title: 'Registration 😎',
subtitle: 'Let them register to our services',
},
{
icon: 'ri-gift-line',
title: 'Free Trial 🎉',
subtitle: 'Your friend will get 30 days free trial',
},
]
</script>
<template>
<VDialog
:model-value="props.isDialogVisible"
max-width="900"
@update:model-value="dialogVisibleUpdate"
>
<VCard class="refer-and-earn-dialog pa-sm-11 pa-3">
<!-- 👉 dialog close btn -->
<DialogCloseBtn
variant="text"
size="default"
@click="emit('update:isDialogVisible', false)"
/>
<VCardText class="pt-5">
<div class="text-center pb-3">
<h4 class="text-h4 pb-2">
Refer & Earn
</h4>
<div class="text-body-1">
Invite your friend to Materio, if they sign up, you and your friend will get 30 days free trial
</div>
</div>
<VRow class="text-center my-6">
<VCol
v-for="step in referAndEarnSteps"
:key="step.title"
cols="12"
sm="4"
>
<div>
<VAvatar
variant="tonal"
size="88"
color="primary"
class="mb-4"
>
<VIcon
size="40"
:icon="step.icon"
/>
</VAvatar>
<div class="text-body-1 font-weight-medium mb-2 text-high-emphasis">
{{ step.title }}
</div>
<div class="text-body-1">
{{ step.subtitle }}
</div>
</div>
</VCol>
</VRow>
<VDivider class="mt-9 mb-6" />
<h5 class="text-h5 mb-5">
Invite your friends
</h5>
<p class="mb-2">
Enter your friend's email address and invite them to join Materio 😍
</p>
<VForm
class="d-flex align-center gap-4 mb-6"
@submit.prevent="() => {}"
>
<VTextField
placeholder="johnDoe@gmail.com"
density="compact"
/>
<VBtn type="submit">
Submit
</VBtn>
</VForm>
<h5 class="text-h5 mb-5">
Share the referral link
</h5>
<p class="mb-2">
You can also copy and send it or share it on your social media. 🚀
</p>
<VForm
class="d-flex align-center flex-wrap gap-4"
@submit.prevent="() => {}"
>
<VTextField
placeholder="http://referral.link"
class="refer-link-input"
density="compact"
>
<template #append-inner>
<VBtn variant="text">
COPY LINK
</VBtn>
</template>
</VTextField>
<div class="d-flex gap-1">
<VBtn
icon
class="rounded"
color="#3B5998"
>
<VIcon
color="white"
icon="ri-facebook-circle-line"
/>
</VBtn>
<VBtn
icon
class="rounded"
color="#55ACEE"
>
<VIcon
color="white"
icon="ri-twitter-line"
/>
</VBtn>
<VBtn
icon
class="rounded"
color="#007BB6"
>
<VIcon
color="white"
icon="ri-linkedin-line"
/>
</VBtn>
</div>
</VForm>
</VCardText>
</VCard>
</VDialog>
</template>
<style lang="scss">
.refer-link-input {
.v-field--appended {
padding-inline-end: 0;
}
.v-field__append-inner {
padding-block-start: 0.125rem;
}
}
</style>

View File

@@ -0,0 +1,204 @@
<script setup>
import avatar1 from '@images/avatars/avatar-1.png'
import avatar2 from '@images/avatars/avatar-2.png'
import avatar3 from '@images/avatars/avatar-3.png'
import avatar4 from '@images/avatars/avatar-4.png'
import avatar5 from '@images/avatars/avatar-5.png'
import avatar6 from '@images/avatars/avatar-6.png'
import avatar7 from '@images/avatars/avatar-7.png'
import avatar8 from '@images/avatars/avatar-8.png'
const props = defineProps({
isDialogVisible: {
type: Boolean,
required: true,
},
})
const emit = defineEmits(['update:isDialogVisible'])
const dialogVisibleUpdate = val => {
emit('update:isDialogVisible', val)
}
const membersList = [
{
avatar: avatar1,
name: 'Lester Palmer',
email: 'jerrod98@gmail.com',
permission: 'Can Edit',
},
{
avatar: avatar2,
name: 'Mattie Blair',
email: 'prudence.boehm@yahoo.com',
permission: 'Owner',
},
{
avatar: avatar3,
name: 'Marvin Wheeler',
email: 'rumet@jujpejah.net',
permission: 'Can Comment',
},
{
avatar: avatar4,
name: 'Nannie Ford',
email: 'negza@nuv.io',
permission: 'Can View',
},
{
avatar: avatar5,
name: 'Julian Murphy',
email: 'lunebame@umdomgu.net',
permission: 'Can Edit',
},
{
avatar: avatar6,
name: 'Sophie Gilbert',
email: 'ha@sugit.gov',
permission: 'Can View',
},
{
avatar: avatar7,
name: 'Chris Watkins',
email: 'zokap@mak.org',
permission: 'Can Comment',
},
{
avatar: avatar8,
name: 'Adelaide Nichols',
email: 'ujinomu@jigo.com',
permission: 'Can Edit',
},
]
</script>
<template>
<VDialog
:model-value="props.isDialogVisible"
max-width="900"
@update:model-value="dialogVisibleUpdate"
>
<VCard class="share-project-dialog pa-sm-11 pa-3">
<!-- 👉 dialog close btn -->
<DialogCloseBtn
size="default"
variant="text"
@click="emit('update:isDialogVisible', false)"
/>
<VCardText class="pt-5">
<div class="text-center mb-6">
<h4 class="text-h4 mb-2">
Share Project
</h4>
<p class="text-body-1">
Share project with the team members
</p>
</div>
<div class="mb-6">
<h5 class="text-h5 mb-2">
Add Members
</h5>
<VAutocomplete
:items="membersList"
item-title="name"
item-value="name"
density="compact"
placeholder="Add project members..."
>
<template #item="{ props: listItemProp, item }">
<VListItem v-bind="listItemProp">
<template #prepend>
<VAvatar
:image="item.raw.avatar"
size="30"
/>
</template>
</VListItem>
</template>
</VAutocomplete>
</div>
<h6 class="text-h6 mb-4">
8 Members
</h6>
<VList class="card-list mb-6">
<VListItem
v-for="member in membersList"
:key="member.name"
>
<template #prepend>
<VAvatar :image="member.avatar" />
</template>
<VListItemTitle class="text-high-emphasis">
{{ member.name }}
</VListItemTitle>
<VListItemSubtitle>
{{ member.email }}
</VListItemSubtitle>
<template #append>
<VBtn
variant="text"
color="secondary"
:icon="$vuetify.display.xs"
>
<template v-if="!$vuetify.display.xs">
{{ member.permission }}
</template>
<VIcon
end
icon="ri-arrow-down-s-line"
size="16"
:class="$vuetify.display.xs ? 'ms-0' : ''"
/>
<VMenu activator="parent">
<VList :selected="[member.permission]">
<VListItem
v-for="(item, index) in ['Owner', 'Can Edit', 'Can Comment', 'Can View']"
:key="index"
:value="item"
>
<VListItemTitle>{{ item }}</VListItemTitle>
</VListItem>
</VList>
</VMenu>
</VBtn>
</template>
</VListItem>
</VList>
<div class="d-flex justify-space-between align-center flex-wrap gap-3">
<div class="text-body-1 text-high-emphasis font-weight-medium d-flex align-center">
<VIcon
icon="ri-group-line"
size="20"
class="me-2"
/>
<span>Public to Master - ThemeSelection</span>
</div>
<VBtn
variant="outlined"
prepend-icon="ri-link"
size="small"
>
Copy Project Link
</VBtn>
</div>
</VCardText>
</VCard>
</VDialog>
</template>
<style lang="scss">
.share-project-dialog {
.card-list {
--v-card-list-gap: 1rem;
}
}
</style>

View File

@@ -0,0 +1,149 @@
<script setup>
const props = defineProps({
isDialogVisible: {
type: Boolean,
required: true,
default: false,
},
smsCode: {
type: String,
required: false,
default: '',
},
authAppCode: {
type: String,
required: false,
default: '',
},
})
const emit = defineEmits(['update:isDialogVisible'])
const authMethods = [
{
icon: 'ri-settings-4-line',
title: 'Authenticator Apps',
desc: 'Get code from an app like Google Authenticator or Microsoft Authenticator.',
value: 'authApp',
},
{
icon: 'ri-wechat-line',
title: 'SMS',
desc: 'We will send a code via SMS if you need to use your backup login method.',
value: 'sms',
},
]
const selectedMethod = ref('authApp')
const isAuthAppDialogVisible = ref(false)
const isSmsDialogVisible = ref(false)
const openSelectedMethodDialog = () => {
if (selectedMethod.value === 'authApp') {
isAuthAppDialogVisible.value = true
isSmsDialogVisible.value = false
emit('update:isDialogVisible', false)
}
if (selectedMethod.value === 'sms') {
isAuthAppDialogVisible.value = false
isSmsDialogVisible.value = true
emit('update:isDialogVisible', false)
}
}
</script>
<template>
<VDialog
max-width="800"
:model-value="props.isDialogVisible"
@update:model-value="(val) => $emit('update:isDialogVisible', val)"
>
<VCard class="pa-sm-11 pa-3">
<!-- 👉 dialog close btn -->
<DialogCloseBtn
variant="text"
size="default"
@click="$emit('update:isDialogVisible', false)"
/>
<VCardText class="pt-5">
<div class="mb-6">
<div class="text-center mb-6">
<h4 class="text-h4 mb-2">
Select Authentication Method
</h4>
<div class="text-body-1">
You also need to select a method by which the proxy authenticates to the directory serve.
</div>
</div>
<CustomRadios
v-model:selected-radio="selectedMethod"
:radio-content="authMethods"
:grid-column="{ cols: '12' }"
>
<template #default="items">
<div class="d-flex flex-column">
<div class="d-flex mb-2 align-center gap-x-1">
<VIcon
:icon="items.item.icon"
size="20"
/>
<div class="text-body-1 font-weight-medium text-high-emphasis">
{{ items.item.title }}
</div>
</div>
<p class="text-body-2 mb-0">
{{ items.item.desc }}
</p>
</div>
</template>
</CustomRadios>
</div>
<div class="text-end">
<VBtn @click="openSelectedMethodDialog">
continue
<VIcon
end
icon="ri-arrow-right-line"
class="flip-in-rtl"
/>
</VBtn>
</div>
</VCardText>
</VCard>
</VDialog>
<AddAuthenticatorAppDialog
v-model:isDialogVisible="isAuthAppDialogVisible"
:auth-code="props.authAppCode"
/>
<EnableOneTimePasswordDialog
v-model:isDialogVisible="isSmsDialogVisible"
:mobile-number="props.smsCode"
/>
</template>
<style lang="scss">
.auth-method-card {
&.card-list .v-list-item {
padding-block: 20px !important;
padding-inline: 30px !important;
}
&.responsive-card {
.v-list-item {
display: flex;
flex-direction: column;
gap: 0.5rem;
text-align: center;
.v-list-item__prepend {
svg {
margin: 0;
}
}
}
}
}
</style>

View File

@@ -0,0 +1,228 @@
<script setup>
const props = defineProps({
userData: {
type: Object,
required: false,
default: () => ({
avatar: '',
company: '',
contact: '',
country: null,
currentPlan: '',
email: '',
fullName: '',
id: 0,
role: '',
status: null,
username: '',
language: [],
projectDone: 0,
taskDone: 0,
taxId: '',
}),
},
isDialogVisible: {
type: Boolean,
required: true,
},
})
const emit = defineEmits([
'submit',
'update:isDialogVisible',
])
const userData = ref(structuredClone(toRaw(props.userData)))
watch(props, () => {
userData.value = structuredClone(toRaw(props.userData))
})
const onFormSubmit = () => {
emit('update:isDialogVisible', false)
emit('submit', userData.value)
}
const onFormReset = () => {
userData.value = structuredClone(toRaw(props.userData))
emit('update:isDialogVisible', false)
}
const dialogVisibleUpdate = val => {
emit('update:isDialogVisible', val)
}
</script>
<template>
<VDialog
:width="$vuetify.display.smAndDown ? 'auto' : 900 "
:model-value="props.isDialogVisible"
@update:model-value="dialogVisibleUpdate"
>
<VCard class="pa-sm-11 pa-3">
<!-- 👉 dialog close btn -->
<DialogCloseBtn
variant="text"
size="default"
@click="onFormReset"
/>
<VCardText class="pt-5">
<div class="text-center pb-6">
<h4 class="text-h4 mb-2">
Edit User Information
</h4>
<div class="text-body-1">
Updating user details will receive a privacy audit.
</div>
</div>
<!-- 👉 Form -->
<VForm
class="mt-4"
@submit.prevent="onFormSubmit"
>
<VRow>
<!-- 👉 First Name -->
<VCol
cols="12"
md="6"
>
<VTextField
v-model="userData.fullName.split(' ')[0]"
label="First Name"
placeholder="John"
/>
</VCol>
<!-- 👉 Last Name -->
<VCol
cols="12"
md="6"
>
<VTextField
v-model="userData.fullName.split(' ')[1]"
label="Last Name"
placeholder="doe"
/>
</VCol>
<!-- 👉 User Name -->
<VCol cols="12">
<VTextField
v-model="userData.username"
label="Username"
placeholder="John Doe"
/>
</VCol>
<!-- 👉 Billing Email -->
<VCol
cols="12"
md="6"
>
<VTextField
v-model="userData.email"
label="Billing Email"
placeholder="johndoe@email.com"
/>
</VCol>
<!-- 👉 Status -->
<VCol
cols="12"
md="6"
>
<VSelect
v-model="userData.status"
:items="['Active', 'Inactive', 'Pending']"
label="Status"
placeholder="Status"
/>
</VCol>
<!-- 👉 Tax Id -->
<VCol
cols="12"
md="6"
>
<VTextField
v-model="userData.taxId"
label="Tax Id"
placeholder="Tax-3456789"
/>
</VCol>
<!-- 👉 Contact -->
<VCol
cols="12"
md="6"
>
<VTextField
v-model="userData.contact"
label="Contact"
placeholder="+1 9876543210"
/>
</VCol>
<!-- 👉 Language -->
<VCol
cols="12"
md="6"
>
<VSelect
v-model="userData.language"
:items="['English', 'Spanish', 'French']"
label="Language"
placeholder="English"
chips
closable-chips
multiple
/>
</VCol>
<!-- 👉 Country -->
<VCol
cols="12"
md="6"
>
<VSelect
v-model="userData.country"
:items="['United States', 'United Kingdom', 'France']"
label="Country"
placeholder="United States"
/>
</VCol>
<!-- 👉 Switch -->
<VCol cols="12">
<VSwitch
density="compact"
label="Use as a billing address?"
/>
</VCol>
<!-- 👉 Submit and Cancel -->
<VCol
cols="12"
class="d-flex flex-wrap justify-center gap-4"
>
<VBtn type="submit">
Submit
</VBtn>
<VBtn
color="secondary"
variant="outlined"
@click="onFormReset"
>
Cancel
</VBtn>
</VCol>
</VRow>
</VForm>
</VCardText>
</VCard>
</VDialog>
</template>

View File

@@ -0,0 +1,114 @@
<script setup>
const props = defineProps({
isDialogVisible: {
type: Boolean,
required: true,
},
})
const emit = defineEmits(['update:isDialogVisible'])
const selectedPlan = ref('basic')
const plansList = [
{
desc: 'Standard - $99/month',
title: 'Standard',
value: 'standard',
},
{
desc: 'Basic - $0/month',
title: 'Basic',
value: 'basic',
},
{
desc: 'Enterprise - $499/month',
title: 'Enterprise',
value: 'enterprice',
},
{
desc: 'Company - $999/month',
title: 'Company',
value: 'company',
},
]
const isConfirmDialogVisible = ref(false)
</script>
<template>
<!-- 👉 upgrade plan -->
<VDialog
:width="$vuetify.display.smAndDown ? 'auto' : 650"
:model-value="props.isDialogVisible"
@update:model-value="val => $emit('update:isDialogVisible', val)"
>
<VCard class="py-sm-11 py-3">
<!-- 👉 dialog close btn -->
<DialogCloseBtn
variant="text"
size="default"
@click="$emit('update:isDialogVisible', false)"
/>
<VCardItem class="text-center pb-10">
<div class="text-center">
<h4 class="text-h4 mb-2">
Upgrade Plan
</h4>
<div class="text-body-1">
Choose the best plan for user.
</div>
</div>
</VCardItem>
<VCardText class="d-flex justify-space-between flex-column flex-sm-row gap-4 px-15">
<VSelect
v-model="selectedPlan"
:items="plansList"
density="compact"
label="Choose a plan"
placeholder="Basic"
/>
<VBtn>
Upgrade
</VBtn>
</VCardText>
<VDivider class="mb-5" />
<VCardText class="px-15">
<p class="font-weight-medium mb-2">
User current plan is standard plan
</p>
<div class="d-flex justify-space-between flex-wrap">
<div class="d-flex align-center me-3">
<sup class="text-base text-primary">$</sup>
<h1 class="text-h1 text-primary">
99
</h1>
<sub class="text-body-2 mt-3">/month</sub>
</div>
<VBtn
color="error"
variant="outlined"
class="mt-3"
@click="isConfirmDialogVisible = true"
>
Cancel Subscription
</VBtn>
</div>
</VCardText>
<!-- 👉 Confirm Dialog -->
<ConfirmDialog
v-model:isDialogVisible="isConfirmDialogVisible"
cancel-title="Cancelled"
confirm-title="Unsubscribed!"
confirm-msg="Your subscription cancelled successfully."
confirmation-question="Are you sure to cancel your subscription?"
cancel-msg="Unsubscription Cancelled!!"
/>
</VCard>
</VDialog>
</template>