@mixd-id/web-scaffold 0.1.230406088 → 0.1.230406089
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +1 -1
- package/src/components/Alert.vue +3 -2
- package/src/components/Button.vue +4 -0
- package/src/components/CitySelector.vue +59 -0
- package/src/components/Datepicker.vue +46 -27
- package/src/components/Textbox.vue +20 -1
- package/src/index.js +9 -0
- package/src/widgets/ContactForm.vue +70 -25
- package/src/widgets/ContactFormSetting.vue +75 -18
- package/src/widgets/WebPageBuilder.vue +7 -2
package/package.json
CHANGED
package/src/components/Alert.vue
CHANGED
|
@@ -22,14 +22,14 @@
|
|
|
22
22
|
</div>
|
|
23
23
|
|
|
24
24
|
<div class="mt-4" v-if="mode === 'alert'">
|
|
25
|
-
<Button @click="$emit('dismiss')" class="min-w-[88px]">
|
|
25
|
+
<Button ref="btnOK" @click="$emit('dismiss')" class="min-w-[88px]">
|
|
26
26
|
<strong class="px-4">
|
|
27
27
|
{{ text }}
|
|
28
28
|
</strong>
|
|
29
29
|
</Button>
|
|
30
30
|
</div>
|
|
31
31
|
<div class="mt-4 flex flex-row gap-2" v-else-if="mode === 'confirm'">
|
|
32
|
-
<Button @click="$emit('confirm')" class="min-w-[88px]">
|
|
32
|
+
<Button ref="btnOK" @click="$emit('confirm')" class="min-w-[88px]" tabindex="0">
|
|
33
33
|
<strong class="px-4">
|
|
34
34
|
{{ text }}
|
|
35
35
|
</strong>
|
|
@@ -123,6 +123,7 @@ export default{
|
|
|
123
123
|
methods: {
|
|
124
124
|
|
|
125
125
|
onAfterAppear(){
|
|
126
|
+
this.$refs.btnOK.focus()
|
|
126
127
|
this.$emit('appear')
|
|
127
128
|
}
|
|
128
129
|
|
|
@@ -136,6 +136,10 @@ export default{
|
|
|
136
136
|
outline: solid 1px rgb(var(--primary-700));
|
|
137
137
|
border: solid 1px rgb(var(--primary-400));
|
|
138
138
|
}
|
|
139
|
+
.button-primary:focus{
|
|
140
|
+
outline-color: rgb(var(--primary-800));
|
|
141
|
+
border-color: rgb(var(--primary-600));
|
|
142
|
+
}
|
|
139
143
|
.button-primary:hover{
|
|
140
144
|
@apply bg-primary-600;
|
|
141
145
|
outline-color: rgb(var(--primary-800))
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<Modal :state="isOpen" width="480" height="480">
|
|
3
|
+
<template v-slot:head>
|
|
4
|
+
<div class="relative p-5">
|
|
5
|
+
<h3>Pilih Kota</h3>
|
|
6
|
+
<div class="absolute top-0 right-0">
|
|
7
|
+
<button type="button" class="p-2" @click="close">
|
|
8
|
+
<svg width="24" height="24" viewBox="0 0 24 24" class="fill-text-300" xmlns="http://www.w3.org/2000/svg">
|
|
9
|
+
<path d="M6.53034 5.46965C6.23745 5.17676 5.76257 5.17676 5.46968 5.46965C5.17679 5.76255 5.17679 6.23742 5.46968 6.53031L10.9393 12L5.46967 17.4697C5.17678 17.7626 5.17678 18.2374 5.46967 18.5303C5.76256 18.8232 6.23744 18.8232 6.53033 18.5303L12 13.0606L17.4697 18.5303C17.7626 18.8232 18.2375 18.8232 18.5303 18.5303C18.8232 18.2374 18.8232 17.7626 18.5303 17.4697L13.0607 12L18.5303 6.53032C18.8232 6.23743 18.8232 5.76256 18.5303 5.46966C18.2374 5.17677 17.7626 5.17677 17.4697 5.46966L12 10.9393L6.53034 5.46965Z"/>
|
|
10
|
+
</svg>
|
|
11
|
+
</button>
|
|
12
|
+
</div>
|
|
13
|
+
</div>
|
|
14
|
+
</template>
|
|
15
|
+
<template v-slot:foot>
|
|
16
|
+
<div class="p-5">
|
|
17
|
+
|
|
18
|
+
</div>
|
|
19
|
+
</template>
|
|
20
|
+
<div class="flex-1 p-5">
|
|
21
|
+
</div>
|
|
22
|
+
</Modal>
|
|
23
|
+
</template>
|
|
24
|
+
|
|
25
|
+
<script>
|
|
26
|
+
|
|
27
|
+
export default{
|
|
28
|
+
|
|
29
|
+
inject: [ 'socketEmit2' ],
|
|
30
|
+
|
|
31
|
+
data(){
|
|
32
|
+
return {
|
|
33
|
+
isOpen: false
|
|
34
|
+
}
|
|
35
|
+
},
|
|
36
|
+
|
|
37
|
+
methods: {
|
|
38
|
+
|
|
39
|
+
open(id){
|
|
40
|
+
this.isOpen = true
|
|
41
|
+
},
|
|
42
|
+
|
|
43
|
+
close(){
|
|
44
|
+
this.isOpen = false
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
</script>
|
|
52
|
+
|
|
53
|
+
<style module>
|
|
54
|
+
|
|
55
|
+
.comp{
|
|
56
|
+
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
</style>
|
|
@@ -1,23 +1,23 @@
|
|
|
1
1
|
<template>
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
<
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
</
|
|
10
|
-
<
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
</
|
|
14
|
-
<
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
<div v-
|
|
3
|
+
<div v-if="mode === ''" :class="compClass">
|
|
4
|
+
<select v-model="DD">
|
|
5
|
+
<option disabled selected>Tanggal</option>
|
|
6
|
+
<option v-for="d in 31" :value="d.toString().padStart(2, '0')">{{ d }}</option>
|
|
7
|
+
</select>
|
|
8
|
+
<select v-model="MM">
|
|
9
|
+
<option disabled selected>Bulan</option>
|
|
10
|
+
<option v-for="mmm in months" :value="mmm[0]">{{ mmm[1] }}</option>
|
|
11
|
+
</select>
|
|
12
|
+
<select v-model="YYYY">
|
|
13
|
+
<option disabled selected>Tahun</option>
|
|
14
|
+
<option v-for="yyyy in years" :value="yyyy">{{ yyyy }}</option>
|
|
15
|
+
</select>
|
|
16
|
+
</div>
|
|
17
|
+
|
|
18
|
+
<div v-else :class="compClass">
|
|
19
|
+
|
|
20
|
+
<div v-if="mode === 'popup'" ref="popup"
|
|
21
21
|
@click="!readonly ? contextMenu = { caller:$refs.popup, value:this.modelValue } : null"
|
|
22
22
|
class="flex-1">
|
|
23
23
|
<input class="flex-1" type="text" readonly :value="DMMMYYYY"/>
|
|
@@ -102,9 +102,9 @@ export default{
|
|
|
102
102
|
|
|
103
103
|
setup(props, { emit }){
|
|
104
104
|
|
|
105
|
-
const DD = ref(dayjs(props.modelValue).format('DD'))
|
|
106
|
-
const MM = ref(dayjs(props.modelValue).format('MM'))
|
|
107
|
-
const YYYY = ref(dayjs(props.modelValue).format('YYYY'))
|
|
105
|
+
const DD = ref(dayjs(props.modelValue ?? props.defaultValue).format('DD'))
|
|
106
|
+
const MM = ref(dayjs(props.modelValue ?? props.defaultValue).format('MM'))
|
|
107
|
+
const YYYY = ref(dayjs(props.modelValue ?? props.defaultValue).format('YYYY'))
|
|
108
108
|
|
|
109
109
|
watch([ YYYY, MM, DD ], (to) => {
|
|
110
110
|
emit('update:modelValue', to.join('-'))
|
|
@@ -136,6 +136,8 @@ export default{
|
|
|
136
136
|
|
|
137
137
|
modelValue:String,
|
|
138
138
|
|
|
139
|
+
defaultValue: String,
|
|
140
|
+
|
|
139
141
|
readonly: undefined,
|
|
140
142
|
|
|
141
143
|
},
|
|
@@ -262,9 +264,8 @@ export default{
|
|
|
262
264
|
<style module>
|
|
263
265
|
|
|
264
266
|
.datepicker {
|
|
265
|
-
@apply h-[var(--h-cp)];
|
|
267
|
+
@apply min-h-[var(--h-cp)];
|
|
266
268
|
@apply flex items-center rounded-lg overflow-hidden cursor-pointer relative;
|
|
267
|
-
@apply border-[1px] border-text-200 bg-base-50;
|
|
268
269
|
@apply cursor-pointer;
|
|
269
270
|
}
|
|
270
271
|
.datepicker:not(.readonly){
|
|
@@ -301,16 +302,34 @@ export default{
|
|
|
301
302
|
@apply block fill-text-300;
|
|
302
303
|
}
|
|
303
304
|
|
|
304
|
-
.
|
|
305
|
+
.selected{
|
|
306
|
+
@apply bg-primary;
|
|
307
|
+
}
|
|
308
|
+
|
|
309
|
+
.mode-calendar{
|
|
305
310
|
@apply p-2 h-auto;
|
|
306
311
|
}
|
|
307
312
|
|
|
313
|
+
.mode-{
|
|
314
|
+
@apply flex flex-row gap-2;
|
|
315
|
+
}
|
|
316
|
+
.mode- select{
|
|
317
|
+
@apply bg-base border-[1px] border-text-200 rounded-lg;
|
|
318
|
+
@apply min-h-[var(--h-cp)];
|
|
319
|
+
}
|
|
320
|
+
.mode- select:first-child{
|
|
321
|
+
@apply w-12;
|
|
322
|
+
}
|
|
323
|
+
.mode- select:nth-child(2){
|
|
324
|
+
@apply w-72;
|
|
325
|
+
}
|
|
326
|
+
.mode- select:last-child{
|
|
327
|
+
@apply w-48;
|
|
328
|
+
}
|
|
329
|
+
|
|
308
330
|
.datepicker-date--1, .datepicker-date-1{
|
|
309
331
|
@apply text-gray-500;
|
|
310
332
|
}
|
|
311
333
|
|
|
312
|
-
.selected{
|
|
313
|
-
@apply bg-primary;
|
|
314
|
-
}
|
|
315
334
|
|
|
316
335
|
</style>
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
<slot name="start"></slot>
|
|
4
4
|
<input :type="computedType" :disabled="isDisabled" @focus="isActive = true" @input="onInput" @blur="onBlur"
|
|
5
5
|
:placeholder="placeholder" :maxlength="maxlength" ref="input" autocomplete="new-password"
|
|
6
|
-
:value="displayedValue" :readonly="Boolean(readonly)"
|
|
6
|
+
:value="displayedValue" :readonly="Boolean(readonly)" @paste="onPaste"
|
|
7
7
|
@keydown="onKeyDown"/>
|
|
8
8
|
<button class="mr-2" v-if="Boolean(clearable) && !Boolean(readonly) && state >= 1 && modelValue" type="button" @click="$emit('clear')">
|
|
9
9
|
<svg :class="$style.svg" width="19" height="19" viewBox="0 0 24 24" class="fill-text-200" xmlns="http://www.w3.org/2000/svg">
|
|
@@ -128,12 +128,31 @@ export default{
|
|
|
128
128
|
this.$emit('blur', e)
|
|
129
129
|
},
|
|
130
130
|
|
|
131
|
+
onPaste(e){
|
|
132
|
+
e.preventDefault()
|
|
133
|
+
|
|
134
|
+
let text = (e.clipboardData || window.clipboardData).getData("text");
|
|
135
|
+
|
|
136
|
+
switch(this.type){
|
|
137
|
+
case 'tel':
|
|
138
|
+
text = text.replace(/[^0-9]/g, '')
|
|
139
|
+
break
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
if(parseInt(this.maxlength) > 0){
|
|
143
|
+
text = text.substring(0, parseInt(this.maxlength))
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
this.$emit('update:modelValue', text)
|
|
147
|
+
},
|
|
148
|
+
|
|
131
149
|
onKeyDown(e){
|
|
132
150
|
if([ 'number', 'tel' ].includes(this.type)){
|
|
133
151
|
if(((e.keyCode >= 48 && e.keyCode <= 57) || (e.keyCode >= 96 && e.keyCode <= 105) ||
|
|
134
152
|
[ 8, 9, 13, 27, 37, 38, 39, 40, 46 ].includes(e.keyCode)) && !e.ctrlKey && !e.metaKey && !e.shiftKey && !e.altKey);
|
|
135
153
|
else if(e.keyCode === 65 && (e.ctrlKey || e.metaKey));
|
|
136
154
|
else if(e.keyCode === 82 && (e.ctrlKey || e.metaKey));
|
|
155
|
+
else if(e.keyCode === 86 && (e.ctrlKey || e.metaKey)); // ctrl-v
|
|
137
156
|
else{
|
|
138
157
|
e.preventDefault()
|
|
139
158
|
}
|
package/src/index.js
CHANGED
|
@@ -169,6 +169,14 @@ const util = {
|
|
|
169
169
|
}
|
|
170
170
|
},
|
|
171
171
|
|
|
172
|
+
removeEmpty(array, emptyValues = [ '', '{}', '[]' ]){
|
|
173
|
+
for (let i = array.length - 1; i >= 0; i--) {
|
|
174
|
+
if (!array[i] || emptyValues.includes(JSON.stringify(array[i])) || Object.values(array[i]).join('').length <= 0){
|
|
175
|
+
array.splice(i, 1);
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
},
|
|
179
|
+
|
|
172
180
|
onEvent: (arr, updates, opt = {}) => {
|
|
173
181
|
|
|
174
182
|
const [ model, event, items ] = updates
|
|
@@ -252,6 +260,7 @@ export default{
|
|
|
252
260
|
app.component('Block', defineAsyncComponent(() => import("./components/Block.vue")))
|
|
253
261
|
app.component('Button', defineAsyncComponent(() => import("./components/Button.vue")))
|
|
254
262
|
app.component('Box', defineAsyncComponent(() => import("./components/Box.vue")))
|
|
263
|
+
app.component('CitySelector', defineAsyncComponent(() => import("./components/CitySelector.vue")))
|
|
255
264
|
app.component('ColorPicker', defineAsyncComponent(() => import("./components/ColorPicker.vue")))
|
|
256
265
|
app.component('SearchButton', defineAsyncComponent(() => import("./components/SearchButton.vue")))
|
|
257
266
|
app.component('ChatTyping', defineAsyncComponent(() => import("./components/ChatTyping.vue")))
|
|
@@ -1,28 +1,72 @@
|
|
|
1
1
|
<template>
|
|
2
2
|
<div :class="compClass">
|
|
3
|
-
<div
|
|
3
|
+
<div>
|
|
4
|
+
<h2 v-if="title">{{ title }}</h2>
|
|
5
|
+
<p v-if="description" v-html="description"></p>
|
|
6
|
+
</div>
|
|
4
7
|
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
<
|
|
8
|
-
</div>
|
|
8
|
+
<div class="flex flex-col gap-4">
|
|
9
|
+
<div v-for="field in fields">
|
|
10
|
+
<label class="text-gray-600">{{ field.label ?? field.type }}</label>
|
|
9
11
|
|
|
10
|
-
|
|
11
|
-
<div v-for="field in fields">
|
|
12
|
-
<label class="text-gray-700">{{ field.label ?? field.type }}</label>
|
|
12
|
+
<div class="mt-1">
|
|
13
13
|
<Textbox v-if="field.type === 'name'" v-model="form[field.type]" class="bg-white text-xl" :readonly="completed" />
|
|
14
|
-
|
|
15
|
-
<Textbox v-else-if="field.type === '
|
|
16
|
-
|
|
14
|
+
|
|
15
|
+
<Textbox v-else-if="field.type === 'university'" v-model="form[field.type]"
|
|
16
|
+
class="bg-white text-xl" :readonly="completed" />
|
|
17
|
+
|
|
18
|
+
<Textbox v-else-if="field.type === 'ktpNumber'" maxlength="16" type="tel" v-model="form[field.type]"
|
|
19
|
+
class="bg-white text-xl font-mono" :readonly="completed" />
|
|
20
|
+
|
|
21
|
+
<Textbox v-else-if="field.type === 'email'" v-model="form[field.type]"
|
|
22
|
+
class="bg-white text-xl md:w-[300px] max-w-full" :readonly="completed" />
|
|
23
|
+
|
|
24
|
+
<Textbox v-else-if="field.type === 'mobileNumber'" v-model="form[field.type]"
|
|
25
|
+
class="bg-white text-xl font-mono" maxlength="18" type="tel" :readonly="completed" />
|
|
26
|
+
|
|
27
|
+
<Textbox v-else-if="field.type === 'referralCode'" v-model="form[field.type]"
|
|
28
|
+
class="bg-white text-xl md:w-[200px] max-w-full" :readonly="completed" />
|
|
29
|
+
|
|
30
|
+
<div v-else-if="field.type === 'birthDate'" class="flex flex-col md:flex-row gap-2">
|
|
31
|
+
<Textbox v-model="form['birthPlace']" class="bg-base cursor-pointer" @click="$refs.citySelector.open()" readonly="true"
|
|
32
|
+
placeholder="Kota">
|
|
33
|
+
<template #end>
|
|
34
|
+
<div class="p-3">
|
|
35
|
+
<svg xmlns="http://www.w3.org/2000/svg" width="14" height="14" class="fill-text-200" viewBox="0 0 320 512"><path d="M287.968 160H32.038c-28.425 0-42.767 34.488-22.627 54.627l127.962 128c12.496 12.496 32.758 12.497 45.255 0l127.968-128C330.695 194.528 316.45 160 287.968 160zM160 320L32 192h256L160 320z"/></svg>
|
|
36
|
+
</div>
|
|
37
|
+
</template>
|
|
38
|
+
</Textbox>
|
|
39
|
+
<Datepicker v-model="form['birthDate']" class="w-[200px] text-lg" default-value="2000-01-01" :readonly="completed" />
|
|
40
|
+
</div>
|
|
41
|
+
|
|
42
|
+
<Dropdown v-else-if="field.type === 'position'" v-model="form[field.type]" class="text-xl">
|
|
43
|
+
<option v-for="item in field.items" :value="item.text">{{ item.text }}</option>
|
|
44
|
+
</Dropdown>
|
|
45
|
+
|
|
46
|
+
<Dropdown v-else-if="field.type === 'provinceName'" v-model="form[field.type]" class="text-xl">
|
|
47
|
+
<option v-for="item in field.items" :value="item.text">{{ item.text }}</option>
|
|
48
|
+
</Dropdown>
|
|
49
|
+
|
|
50
|
+
<Dropdown v-else-if="field.type === 'education'" v-model="form[field.type]" class="text-xl">
|
|
51
|
+
<option v-for="item in field.items" :value="item.text">{{ item.text }}</option>
|
|
52
|
+
</Dropdown>
|
|
53
|
+
|
|
54
|
+
<Dropdown v-else-if="field.type === 'major'" v-model="form[field.type]" class="text-xl">
|
|
55
|
+
<option v-for="item in field.items" :value="item.text">{{ item.text }}</option>
|
|
56
|
+
</Dropdown>
|
|
57
|
+
|
|
17
58
|
<Textarea v-else-if="field.type === 'remark'" v-model="form[field.type]" rows="2" :readonly="completed"></Textarea>
|
|
59
|
+
|
|
60
|
+
<pre v-else>{{ field.type }}</pre>
|
|
18
61
|
</div>
|
|
19
62
|
</div>
|
|
63
|
+
</div>
|
|
20
64
|
|
|
21
|
-
|
|
22
|
-
<h5>{{ completed ? 'Form berhasil dikirim' : 'Kirim' }}</h5>
|
|
23
|
-
</Button>
|
|
65
|
+
<CitySelector ref="citySelector" @change="(city) => form['birthPlace'] = city.alias"/>
|
|
24
66
|
|
|
25
|
-
|
|
67
|
+
<Button ref="submitBtn" class="w-full" @click="submitForm" :state="!canSubmit ? -1 : 1">
|
|
68
|
+
<h5>{{ completed ? 'Form berhasil dikirim' : 'Kirim' }}</h5>
|
|
69
|
+
</Button>
|
|
26
70
|
</div>
|
|
27
71
|
</template>
|
|
28
72
|
|
|
@@ -69,8 +113,12 @@ export default{
|
|
|
69
113
|
this.$refs.submitBtn.setState(2)
|
|
70
114
|
axios({
|
|
71
115
|
method: this.submitMethod ?? 'post',
|
|
72
|
-
url: this.submitUrl,
|
|
73
|
-
data:
|
|
116
|
+
url: import.meta.env.VITE_API_HOST + this.submitUrl,
|
|
117
|
+
data: {
|
|
118
|
+
url: this.$route.path,
|
|
119
|
+
componentUid: this.uid,
|
|
120
|
+
...this.form
|
|
121
|
+
},
|
|
74
122
|
params: this.form
|
|
75
123
|
})
|
|
76
124
|
.then(_ => this.completed = true)
|
|
@@ -83,7 +131,9 @@ export default{
|
|
|
83
131
|
computed: {
|
|
84
132
|
|
|
85
133
|
canSubmit(){
|
|
86
|
-
return this.fields.
|
|
134
|
+
return this.fields.length > 0 &&
|
|
135
|
+
this.fields.every(field => !field.required || this.form[field.type]) &&
|
|
136
|
+
Object.values(this.form).join('').length > 0 &&
|
|
87
137
|
!this.completed
|
|
88
138
|
},
|
|
89
139
|
|
|
@@ -119,16 +169,11 @@ export default{
|
|
|
119
169
|
<style module>
|
|
120
170
|
|
|
121
171
|
.comp{
|
|
122
|
-
@apply flex-1;
|
|
172
|
+
@apply flex-1 w-full max-w-[480px] mx-auto rounded-lg overflow-hidden border-text-200 border-[1px] p-6;
|
|
173
|
+
@apply flex flex-col gap-8 bg-base;
|
|
123
174
|
background-image: v-bind(bgImages[0]);
|
|
124
175
|
}
|
|
125
176
|
|
|
126
|
-
.form{
|
|
127
|
-
@apply mx-auto bg-gray-100 border-text-200 border-[1px] p-6 rounded-lg;
|
|
128
|
-
@apply w-full max-w-[420px];
|
|
129
|
-
@apply flex flex-col gap-8;
|
|
130
|
-
}
|
|
131
|
-
|
|
132
177
|
@media screen and (min-width: 768px){
|
|
133
178
|
.comp{
|
|
134
179
|
background-image: v-bind(bgImages[1]);
|
|
@@ -17,16 +17,21 @@
|
|
|
17
17
|
Add Field
|
|
18
18
|
</button>
|
|
19
19
|
</div>
|
|
20
|
-
<ListItem :items="item.props.fields" class="mt-2
|
|
20
|
+
<ListItem :items="item.props.fields" class="mt-2 border-text-200 border-[1px] rounded-lg overflow-hidden"
|
|
21
|
+
bodyClass="flex flex-col gap-1 divide-y divide-text-200"
|
|
21
22
|
@reorder="(from, to) => { item.props.fields.splice(to, 0, item.props.fields.splice(from, 1)[0]); $emit('change') }">
|
|
22
23
|
<template v-slot="{ item:field, index }">
|
|
23
|
-
<div class="flex flex-row items-center gap-2
|
|
24
|
+
<div class="flex flex-row items-center gap-2 px-3 bg-base-500">
|
|
24
25
|
<svg data-reorder width="14" height="14" class="fill-text-300" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512"><path d="M496 288H16c-8.8 0-16 7.2-16 16v32c0 8.8 7.2 16 16 16h480c8.8 0 16-7.2 16-16v-32c0-8.8-7.2-16-16-16zm0-128H16c-8.8 0-16 7.2-16 16v32c0 8.8 7.2 16 16 16h480c8.8 0 16-7.2 16-16v-32c0-8.8-7.2-16-16-16z"/></svg>
|
|
25
|
-
<div
|
|
26
|
+
<div>
|
|
27
|
+
<Checkbox v-model="field.required" @change="$emit('change')"/>
|
|
28
|
+
</div>
|
|
29
|
+
<div class="flex-1 px-2 text-ellipsis overflow-hidden whitespace-nowrap">
|
|
26
30
|
<label>{{ field.label ?? field.type }}</label>
|
|
27
31
|
</div>
|
|
28
|
-
<button
|
|
29
|
-
|
|
32
|
+
<button class="text-sm text-primary" v-if="field._edit" @click="$refs[field._edit].open(field)">Edit</button>
|
|
33
|
+
<button type="button" @click="confirm($t('Remove this field?'), '', () => { item.props.fields.splice(index, 1); $emit('change') })">
|
|
34
|
+
<svg width="14" height="14" class="fill-text-300 hover:fill-red-500" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 320 512"><path d="M207.6 256l107.72-107.72c6.23-6.23 6.23-16.34 0-22.58l-25.03-25.03c-6.23-6.23-16.34-6.23-22.58 0L160 208.4 52.28 100.68c-6.23-6.23-16.34-6.23-22.58 0L4.68 125.7c-6.23 6.23-6.23 16.34 0 22.58L112.4 256 4.68 363.72c-6.23 6.23-6.23 16.34 0 22.58l25.03 25.03c6.23 6.23 16.34 6.23 22.58 0L160 303.6l107.72 107.72c6.23 6.23 16.34 6.23 22.58 0l25.03-25.03c6.23-6.23 6.23-16.34 0-22.58L207.6 256z"/></svg>
|
|
30
35
|
</button>
|
|
31
36
|
</div>
|
|
32
37
|
</template>
|
|
@@ -49,10 +54,10 @@
|
|
|
49
54
|
<div class="flex-1 flex flex-col gap-2">
|
|
50
55
|
<label class="text-text-400 leading-1">Send whatsapp to</label>
|
|
51
56
|
<div class="flex flex-row gap-2">
|
|
52
|
-
<Textbox class="flex-1" v-model="action.number" type="tel"
|
|
57
|
+
<Textbox class="flex-1" v-model="action.number" type="tel"/>
|
|
53
58
|
<Button type="button" class="text-primary px-3"
|
|
54
59
|
:state="!action.number ? -1 : 1"
|
|
55
|
-
@click="delete action._edit">OK</Button>
|
|
60
|
+
@click="delete action._edit;$emit('change')">OK</Button>
|
|
56
61
|
</div>
|
|
57
62
|
</div>
|
|
58
63
|
</div>
|
|
@@ -64,7 +69,7 @@
|
|
|
64
69
|
<button type="button" @click="action._edit = true">
|
|
65
70
|
<svg width="13" height="13" class="fill-text-300 hover:fill-primary-500" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 576 512"><path d="M402.6 83.2l90.2 90.2c3.8 3.8 3.8 10 0 13.8L274.4 405.6l-92.8 10.3c-12.4 1.4-22.9-9.1-21.5-21.5l10.3-92.8L388.8 83.2c3.8-3.8 10-3.8 13.8 0zm162-22.9l-48.8-48.8c-15.2-15.2-39.9-15.2-55.2 0l-35.4 35.4c-3.8 3.8-3.8 10 0 13.8l90.2 90.2c3.8 3.8 10 3.8 13.8 0l35.4-35.4c15.2-15.3 15.2-40 0-55.2zM384 346.2V448H64V128h229.8c3.2 0 6.2-1.3 8.5-3.5l40-40c7.6-7.6 2.2-20.5-8.5-20.5H48C21.5 64 0 85.5 0 112v352c0 26.5 21.5 48 48 48h352c26.5 0 48-21.5 48-48V306.2c0-10.7-12.9-16-20.5-8.5l-40 40c-2.2 2.3-3.5 5.3-3.5 8.5z"/></svg>
|
|
66
71
|
</button>
|
|
67
|
-
<button type="button" @click="confirm($t('Remove this
|
|
72
|
+
<button type="button" @click="confirm($t('Remove this action?'), '', () => { item.props.onSubmit.splice(index, 1); $emit('change') })">
|
|
68
73
|
<svg width="16" height="16" class="fill-text-300 hover:fill-red-500" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 320 512"><path d="M207.6 256l107.72-107.72c6.23-6.23 6.23-16.34 0-22.58l-25.03-25.03c-6.23-6.23-16.34-6.23-22.58 0L160 208.4 52.28 100.68c-6.23-6.23-16.34-6.23-22.58 0L4.68 125.7c-6.23 6.23-6.23 16.34 0 22.58L112.4 256 4.68 363.72c-6.23 6.23-6.23 16.34 0 22.58l25.03 25.03c6.23 6.23 16.34 6.23 22.58 0L160 303.6l107.72 107.72c6.23 6.23 16.34 6.23 22.58 0l25.03-25.03c6.23-6.23 6.23-16.34 0-22.58L207.6 256z"/></svg>
|
|
69
74
|
</button>
|
|
70
75
|
</div>
|
|
@@ -106,11 +111,12 @@
|
|
|
106
111
|
defaultDisplay="flex"
|
|
107
112
|
@change="$emit('change')" />
|
|
108
113
|
|
|
109
|
-
<ContextMenu ref="fieldOpt" position="bottom-right">
|
|
110
|
-
<div class="flex flex-col
|
|
114
|
+
<ContextMenu ref="fieldOpt" position="bottom-right" class="border-text-200">
|
|
115
|
+
<div class="flex flex-col min-w-[120px] divide-y divide-text-100">
|
|
111
116
|
<button v-for="field in fields"
|
|
112
|
-
class="p-3 bg-base-500 text-left pl-8 hover:bg-text-50"
|
|
113
|
-
@click="item.props.fields.push(field);$emit('change')"
|
|
117
|
+
class="p-3 bg-base-500 text-left pl-8 hover:bg-text-50 disabled:bg-base-500 disabled:text-text-300"
|
|
118
|
+
@click="item.props.fields.push(field);$emit('change')"
|
|
119
|
+
:disabled="item.props.fields.findIndex((_) => _.type === field.type) >= 0">
|
|
114
120
|
{{ field.label }}
|
|
115
121
|
</button>
|
|
116
122
|
</div>
|
|
@@ -120,11 +126,62 @@
|
|
|
120
126
|
<div class="flex flex-col gap-1 min-w-[120px]">
|
|
121
127
|
<button class="p-3 bg-base-500 text-left pl-8 hover:bg-text-50"
|
|
122
128
|
@click="item.props.onSubmit.push({ type:'send-whatsapp', _edit:true })">Send Whatsapp</button>
|
|
123
|
-
<button class="p-3 bg-base-500 text-left pl-8 hover:bg-text-50"
|
|
129
|
+
<button class="p-3 bg-base-500 text-left pl-8 hover:bg-text-50" v-if="item.props.fields.includes('referralCode')"
|
|
124
130
|
@click="item.props.onSubmit.push({ type:'send-whatsapp-referral' });$emit('change')">Send Whatsapp to Referral</button>
|
|
125
131
|
</div>
|
|
126
132
|
</ContextMenu>
|
|
127
133
|
|
|
134
|
+
<Modal ref="positionEdit" width="360" height="480">
|
|
135
|
+
<template v-slot:head>
|
|
136
|
+
<div class="relative p-5">
|
|
137
|
+
<h3>Daftar Posisi</h3>
|
|
138
|
+
<div class="absolute top-0 right-0 p-2">
|
|
139
|
+
<button type="button" class="p-2" @click="$refs.positionEdit.close()">
|
|
140
|
+
<svg width="24" height="24" viewBox="0 0 24 24" class="fill-text-300 hover:fill-red-500" xmlns="http://www.w3.org/2000/svg">
|
|
141
|
+
<path d="M6.53034 5.46965C6.23745 5.17676 5.76257 5.17676 5.46968 5.46965C5.17679 5.76255 5.17679 6.23742 5.46968 6.53031L10.9393 12L5.46967 17.4697C5.17678 17.7626 5.17678 18.2374 5.46967 18.5303C5.76256 18.8232 6.23744 18.8232 6.53033 18.5303L12 13.0606L17.4697 18.5303C17.7626 18.8232 18.2375 18.8232 18.5303 18.5303C18.8232 18.2374 18.8232 17.7626 18.5303 17.4697L13.0607 12L18.5303 6.53032C18.8232 6.23743 18.8232 5.76256 18.5303 5.46966C18.2374 5.17677 17.7626 5.17677 17.4697 5.46966L12 10.9393L6.53034 5.46965Z"/>
|
|
142
|
+
</svg>
|
|
143
|
+
</button>
|
|
144
|
+
</div>
|
|
145
|
+
</div>
|
|
146
|
+
</template>
|
|
147
|
+
<template v-slot:foot="{ context }">
|
|
148
|
+
<div class="p-5">
|
|
149
|
+
<Button type="button" class="w-[100px]" @click="$util.removeEmpty(context.items);$refs.positionEdit.close();$emit('change')">OK</Button>
|
|
150
|
+
</div>
|
|
151
|
+
</template>
|
|
152
|
+
<template #default="{ context }">
|
|
153
|
+
<div class="flex-1 p-5">
|
|
154
|
+
<ListItem :items="context.items"
|
|
155
|
+
body-class="flex flex-col gap-2"
|
|
156
|
+
@reorder="(from, to) => { context.items.splice(to, 0, context.items.splice(from, 1)[0]); }">
|
|
157
|
+
<template v-slot="{ item, index }">
|
|
158
|
+
<div class="flex flex-row items-center gap-2">
|
|
159
|
+
<div class="flex-1">
|
|
160
|
+
<Textbox v-model="item.text" @keyup.enter="context.items.push({})">
|
|
161
|
+
<template #start>
|
|
162
|
+
<div v-if="context.items.length > 1" data-reorder class="self-stretch flex items-center justify-center px-2 bg-text-50">
|
|
163
|
+
<svg width="14" height="14" class="fill-text-300" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512"><path d="M496 288H16c-8.8 0-16 7.2-16 16v32c0 8.8 7.2 16 16 16h480c8.8 0 16-7.2 16-16v-32c0-8.8-7.2-16-16-16zm0-128H16c-8.8 0-16 7.2-16 16v32c0 8.8 7.2 16 16 16h480c8.8 0 16-7.2 16-16v-32c0-8.8-7.2-16-16-16z"/></svg>
|
|
164
|
+
</div>
|
|
165
|
+
</template>
|
|
166
|
+
</Textbox>
|
|
167
|
+
</div>
|
|
168
|
+
<div>
|
|
169
|
+
<button type="button" @click="context.items.splice(index, 1)">
|
|
170
|
+
<svg width="16" height="16" class="fill-text-300 hover:fill-red-500" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 320 512"><path d="M207.6 256l107.72-107.72c6.23-6.23 6.23-16.34 0-22.58l-25.03-25.03c-6.23-6.23-16.34-6.23-22.58 0L160 208.4 52.28 100.68c-6.23-6.23-16.34-6.23-22.58 0L4.68 125.7c-6.23 6.23-6.23 16.34 0 22.58L112.4 256 4.68 363.72c-6.23 6.23-6.23 16.34 0 22.58l25.03 25.03c6.23 6.23 16.34 6.23 22.58 0L160 303.6l107.72 107.72c6.23 6.23 16.34 6.23 22.58 0l25.03-25.03c6.23-6.23 6.23-16.34 0-22.58L207.6 256z"/></svg>
|
|
171
|
+
</button>
|
|
172
|
+
</div>
|
|
173
|
+
</div>
|
|
174
|
+
</template>
|
|
175
|
+
</ListItem>
|
|
176
|
+
|
|
177
|
+
<div class="text-center p-3">
|
|
178
|
+
<button type="button" class="text-primary" @click="context.items.push({})">Tambah Posisi</button>
|
|
179
|
+
</div>
|
|
180
|
+
|
|
181
|
+
</div>
|
|
182
|
+
</template>
|
|
183
|
+
</Modal>
|
|
184
|
+
|
|
128
185
|
</div>
|
|
129
186
|
</template>
|
|
130
187
|
|
|
@@ -158,12 +215,12 @@ export default{
|
|
|
158
215
|
{ type:'remark', label:'Pertanyaan' },
|
|
159
216
|
{ type:'referralCode', label:'Kode Referral (optional)' },
|
|
160
217
|
{ type:'ktpNumber', label:'Nomor KTP' },
|
|
161
|
-
{ type:'birthDate', label:'Tanggal Lahir' },
|
|
162
|
-
{ type:'position', label:'Jabatan yang Dilamar' },
|
|
218
|
+
{ type:'birthDate', label:'Tempat/Tanggal Lahir' },
|
|
219
|
+
{ type:'position', label:'Jabatan yang Dilamar', _edit:'positionEdit', items:[] },
|
|
163
220
|
{ type:'provinceName', label:'Propinsi Domisili' },
|
|
164
|
-
{ type:'education', label:'Pendidikan Terakhir' },
|
|
165
|
-
{ type:'major', label:'Jurusan' },
|
|
166
|
-
{ type:'university', label:'Nama Sekolah/Institusi/Universitas' },
|
|
221
|
+
{ type:'education', label:'Pendidikan Terakhir', _edit:'positionEdit', items:[] },
|
|
222
|
+
{ type:'major', label:'Jurusan', _edit:'positionEdit', items:[] },
|
|
223
|
+
{ type:'university', label:'Nama Sekolah/Institusi/Universitas', _edit:'positionEdit', items:[] },
|
|
167
224
|
]
|
|
168
225
|
}
|
|
169
226
|
},
|
|
@@ -830,9 +830,14 @@ export default{
|
|
|
830
830
|
|
|
831
831
|
{ type:'ContactForm', name:'Contact Form', group:'Widgets', props:{
|
|
832
832
|
fields:[
|
|
833
|
-
{ type:'name', label:'Nama' },
|
|
834
|
-
{ type:'mobileNumber', label:'Nomor HP' }
|
|
833
|
+
{ type:'name', label:'Nama', required:true },
|
|
834
|
+
{ type:'mobileNumber', label:'Nomor HP', required:true },
|
|
835
|
+
{ type:'remark', label:'Pertanyaan' },
|
|
835
836
|
],
|
|
837
|
+
title: 'Contact Us',
|
|
838
|
+
description: 'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Praesent gravida erat eget nisi',
|
|
839
|
+
submitMethod: 'post',
|
|
840
|
+
submitUrl: '/inquiry',
|
|
836
841
|
onSubmit:[],
|
|
837
842
|
}},
|
|
838
843
|
|