refactor: organize frontend project structure

- feat: add toggle for conversation sidebar
- save sidebar state in localstorage.
This commit is contained in:
Abhinav Raut
2025-02-06 03:33:13 +05:30
parent c5cf62573e
commit ceb076bbba
162 changed files with 608 additions and 1040 deletions

View File

@@ -0,0 +1,189 @@
<template>
<div class="space-y-5 rounded-lg" :class="{ 'box border p-5': actions.length > 0 }">
<div class="space-y-5">
<div v-for="(action, index) in actions" :key="index" class="space-y-5">
<div v-if="index > 0">
<hr class="border-t-2 border-dotted border-gray-300" />
</div>
<div class="space-y-3">
<div class="flex items-center justify-between">
<div class="flex gap-5">
<div class="w-48">
<!-- Type -->
<Select
v-model="action.type"
@update:modelValue="(value) => handleFieldChange(value, index)"
>
<SelectTrigger class="m-auto">
<SelectValue placeholder="Select action" />
</SelectTrigger>
<SelectContent>
<SelectGroup>
<SelectItem
v-for="(actionConfig, key) in conversationActions"
:key="key"
:value="key"
>
{{ actionConfig.label }}
</SelectItem>
</SelectGroup>
</SelectContent>
</Select>
</div>
<!-- Value -->
<div
v-if="action.type && conversationActions[action.type]?.type === 'tag'"
class="w-full"
>
<SelectTag
v-model="action.value"
:items="tagsStore.tagNames"
placeholder="Select tag"
/>
</div>
<div
class="w-48"
v-if="action.type && conversationActions[action.type]?.type === 'select'"
>
<ComboBox
v-model="action.value[0]"
:items="conversationActions[action.type]?.options"
placeholder="Select"
@select="handleValueChange($event, index)"
>
<template #item="{ item }">
<div class="flex items-center gap-2 ml-2">
<Avatar v-if="action.type === 'assign_user'" class="w-7 h-7">
<AvatarImage :src="item.avatar_url ?? ''" :alt="item.label.slice(0, 2)" />
<AvatarFallback>
{{ item.label.slice(0, 2).toUpperCase() }}
</AvatarFallback>
</Avatar>
<span v-if="action.type === 'assign_team'">
{{ item.emoji }}
</span>
<span>{{ item.label }}</span>
</div>
</template>
<template #selected="{ selected }">
<div v-if="action.type === 'assign_team'">
<div v-if="selected" class="flex items-center gap-2">
{{ selected.emoji }}
<span>{{ selected.label }}</span>
</div>
<span v-else>Select team</span>
</div>
<div v-else-if="action.type === 'assign_user'" class="flex items-center gap-2">
<div v-if="selected" class="flex items-center gap-2">
<Avatar class="w-7 h-7">
<AvatarImage
:src="selected.avatar_url ?? ''"
:alt="selected.label.slice(0, 2)"
/>
<AvatarFallback>
{{ selected.label.slice(0, 2).toUpperCase() }}
</AvatarFallback>
</Avatar>
<span>{{ selected.label }}</span>
</div>
<span v-else>Select user</span>
</div>
<span v-else>
<span v-if="!selected"> Select</span>
<span v-else>{{ selected.label }} </span>
</span>
</template>
</ComboBox>
</div>
</div>
<div class="cursor-pointer" @click.prevent="removeAction(index)">
<X size="16" />
</div>
</div>
<div
v-if="action.type && conversationActions[action.type]?.type === 'richtext'"
class="pl-0 shadow"
>
<QuillEditor
theme="snow"
v-model:content="action.value[0]"
contentType="html"
@update:content="(value) => handleValueChange(value, index)"
class="h-32 mb-12"
/>
</div>
</div>
</div>
</div>
<div>
<Button variant="outline" @click.prevent="addAction">Add action</Button>
</div>
</div>
</template>
<script setup>
import { toRefs } from 'vue'
import { Button } from '@/components/ui/button'
import { X } from 'lucide-vue-next'
import { useTagStore } from '@/stores/tag'
import {
Select,
SelectContent,
SelectGroup,
SelectItem,
SelectTrigger,
SelectValue
} from '@/components/ui/select'
import { QuillEditor } from '@vueup/vue-quill'
import '@vueup/vue-quill/dist/vue-quill.snow.css'
import ComboBox from '@/components/ui/combobox/ComboBox.vue'
import { Avatar, AvatarFallback, AvatarImage } from '@/components/ui/avatar'
import { SelectTag } from '@/components/ui/select'
import { useConversationFilters } from '@/composables/useConversationFilters'
const props = defineProps({
actions: {
type: Array,
required: true
}
})
const { actions } = toRefs(props)
const emit = defineEmits(['update-actions', 'add-action', 'remove-action'])
const tagsStore = useTagStore()
const { conversationActions } = useConversationFilters()
const handleFieldChange = (value, index) => {
actions.value[index].value = []
actions.value[index].type = value
emitUpdate(index)
}
const handleValueChange = (value, index) => {
if (typeof value === 'object') {
value = value.value
}
actions.value[index].value = [value]
emitUpdate(index)
}
const removeAction = (index) => {
emit('remove-action', index)
}
const addAction = () => {
emit('add-action')
}
const emitUpdate = (index) => {
emit('update-actions', actions, index)
}
</script>