Skip to content

Commit

Permalink
chore: add Card, FileInput and RadioGroup
Browse files Browse the repository at this point in the history
  • Loading branch information
gravitano committed Jun 11, 2024
1 parent b1bd9df commit a22607f
Show file tree
Hide file tree
Showing 4 changed files with 209 additions and 0 deletions.
39 changes: 39 additions & 0 deletions components/app/RadioGroup.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
<script setup lang="ts">
import {
RadioGroup as HRadioGroup,
RadioGroupOption as HRadioGroupOption,
} from '@headlessui/vue'
export interface RadioGroupItem {
label: string
value: string
}
const { items } = defineProps<{
items: RadioGroupItem[]
}>()
const modelValue = defineModel<string>()
</script>

<template>
<HRadioGroup v-model="modelValue" class="divide-y">
<HRadioGroupOption
v-for="(item, index) in items"
v-slot="{ checked }"
:key="index"
:value="item.value"
class="flex items-center gap-2 justify-between py-3"
>
<span class="text-sm font-medium select-none">
{{ item.label }}
</span>
<div
class="size-5 flex items-center justify-center rounded-full"
:class="checked ? 'bg-pertamina-blue-700' : 'border border-gray-300'"
>
<div class="size-2 rounded-full bg-white" />
</div>
</HRadioGroupOption>
</HRadioGroup>
</template>
11 changes: 11 additions & 0 deletions components/app/card/Card.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
<script setup lang="ts">
//
</script>

<template>
<div
class="mb-4 border p-4 rounded-[12px] shadow-[0px_20px_40px_0px_#33287B0D]"
>
<slot />
</div>
</template>
116 changes: 116 additions & 0 deletions components/app/file-input/FileInput.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,116 @@
<script setup lang="ts">
import { useFileDialog } from '@vueuse/core'
import {
UploadCloud02Icon,
} from '@morphemeicons/vue/untitled'
const {
placeholder = '',
accept,
directory = false,
buttonLabel = 'Klik untuk unggah',
hideFiles = false,
label = '',
multiple = false,
error = false,
errorMessage = '',
labelClass = '',
removeable = false,
disabled = false,
} = defineProps<{
placeholder?: string
accept?: string
directory?: boolean
buttonLabel?: string
label?: string
hideFiles?: boolean
multiple?: boolean
error?: boolean
errorMessage?: string
labelClass?: string
removeable?: boolean
disabled?: boolean
}>()
const modelValue = defineModel<File[]>({
default: [],
})
const { files, open, reset, onChange } = useFileDialog({
accept,
directory,
})
onChange((files) => {
if (files)
modelValue.value = Array.from(files)
})
function removeFile(index: number) {
modelValue.value = modelValue.value.filter((_, i) => i !== index)
}
defineExpose({
files,
open,
reset,
})
</script>

<template>
<div>
<div v-if="label" class="v-input-label" :class="labelClass">
{{ label }}
</div>

<div
v-if="multiple || !modelValue.length"
class="border border-gray-200 rounded-[12px] p-[14px] flex flex-col items-center justify-center gap-2"
:class="{
'border-red-500': error,
}"
>
<div class="size-10 rounded-full flex items-center justify-center bg-gray-100 border-[6px] border-gray-50">
<UploadCloud02Icon class="size-5 shrink-0 text-gray-600" />
</div>
<VButton
:disabled="disabled"
color="primary"
text
flush
@click="open"
>
{{ buttonLabel }}
</VButton>
<p class="text-xs text-gray-600">
{{ placeholder }}
</p>
</div>

<div v-if="!hideFiles && modelValue.length" class="flex flex-col gap-1 mt-2">
<FileInputItem
v-for="(file, index) in modelValue"
:key="index"
:image="getObjectURL(file)"
:label="label"
:filename="file.name"
:removeable="removeable"
@remove="removeFile(index)"
/>
</div>

<div v-if="error" class="v-input-error">
{{ errorMessage }}
</div>

<slot
v-bind="{
files: modelValue,
open,
reset,
multiple,
removeFile,
}"
/>
</div>
</template>
43 changes: 43 additions & 0 deletions components/app/file-input/FileInputItem.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
<script setup lang="ts">
const {
imageAlt = '',
} = defineProps<{
image: string
imageAlt?: string
label: string
filename: string
removeable?: boolean
}>()
const emit = defineEmits<{
(e: 'remove'): void
}>()
</script>

<template>
<div class="border rounded-[12px] p-4 flex gap-4 items-center bg-white shadow-xs">
<NuxtImg
:src="image"
:alt="imageAlt"
width="40"
height="40"
class="border border-gray-200 rounded-[8px] shrink-0"
/>
<div class="flex-grow space-y-0.5">
<h3 class="text-sm font-medium text-gray-700">
{{ label }}
</h3>
<p class="text-xs text-gray-600">
{{ filename }}
</p>
</div>
<VButton
v-if="removeable"
prefix-icon="ph:trash"
size="sm"
fab
text
@click="emit('remove')"
/>
</div>
</template>

1 comment on commit a22607f

@github-actions
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Deploy preview for morpheme-nuxt-starter-rato ready!

✅ Preview
https://morpheme-nuxt-starter-rato-7u6wtuz5q-warsonos-projects.vercel.app

Built with commit a22607f.
This pull request is being automatically deployed with vercel-action

Please sign in to comment.