1
0
forked from test/crm

fix: updated task list design in task tab

This commit is contained in:
Shariq Ansari 2023-09-28 20:53:55 +05:30
parent c20d296b35
commit dc20b4c36e
5 changed files with 133 additions and 43 deletions

View File

@ -27,7 +27,7 @@
</Button>
</div>
<div v-if="activities?.length" class="flex-1 overflow-y-auto">
<div v-if="title == 'Notes'" class="grid grid-cols-3 gap-4 px-10 py-5 pt-0">
<div v-if="title == 'Notes'" class="grid grid-cols-3 gap-4 px-10 pb-5">
<div
v-for="note in activities"
class="group flex h-48 cursor-pointer flex-col justify-between gap-2 rounded-md bg-gray-50 px-4 py-3 hover:bg-gray-100"
@ -77,26 +77,64 @@
</div>
</div>
</div>
<div v-else-if="title == 'Tasks'">
<div v-else-if="title == 'Tasks'" class="px-10 pb-5">
<div v-for="(task, i) in activities">
<div class="grid grid-cols-[30px_minmax(auto,_1fr)] gap-4 px-10">
<div
class="relative flex justify-center after:absolute after:left-[50%] after:top-0 after:-z-10 after:border-l after:border-gray-200"
:class="i != activities.length - 1 ? 'after:h-full' : 'after:h-4'"
>
<div
class="z-10 mt-[15px] flex h-7 w-7 items-center justify-center rounded-full bg-gray-100"
>
<TaskIcon class="text-gray-800" />
<div
class="flex cursor-pointer gap-6 rounded p-2.5 duration-300 ease-in-out hover:bg-gray-50"
@click="showTask(task)"
>
<div class="flex flex-1 flex-col gap-1.5 text-base">
<div class="font-medium text-gray-900">
{{ task.title }}
</div>
<div class="flex gap-1.5 text-gray-800">
<div class="flex items-center gap-1.5">
<UserAvatar :user="task.assigned_to" size="xs" />
{{ getUser(task.assigned_to).full_name }}
</div>
<div class="flex items-center justify-center">
<DotIcon class="h-2.5 w-2.5 text-gray-600" :radius="2" />
</div>
<div class="flex gap-2">
<CalendarIcon />
<Tooltip :text="dateFormat(task.due_date, 'ddd, MMM D, YYYY')">
{{ dateFormat(task.due_date, 'D MMM') }}
</Tooltip>
</div>
<div class="flex items-center justify-center">
<DotIcon class="h-2.5 w-2.5 text-gray-600" :radius="2" />
</div>
<div>
<Badge
variant="solid"
:class="
task.priority == 'High'
? '!bg-red-200 text-red-800'
: task.priority == 'Medium'
? '!bg-yellow-200 text-yellow-700'
: '!bg-gray-200 !text-gray-600'
"
size="sm"
:label="task.priority"
/>
</div>
</div>
</div>
<div
class="mb-3 flex max-w-[70%] flex-col gap-3 rounded-md bg-gray-50 p-4"
@click="showTask(task)"
>
{{ task.title }}
<div class="flex items-center">
<Dropdown
:options="taskStatusOptions(updateTaskStatus, task)"
@click.stop
>
<Button variant="ghosted" class="hover:bg-gray-300">
<TaskStatusIcon :status="task.status" />
</Button>
</Dropdown>
</div>
</div>
<div
v-if="i < activities.length - 1"
class="mx-2 h-px border-t border-gray-200"
/>
</div>
</div>
<div v-else-if="title == 'Calls'">
@ -543,6 +581,8 @@ import PhoneIcon from '@/components/Icons/PhoneIcon.vue'
import NoteIcon from '@/components/Icons/NoteIcon.vue'
import TaskIcon from '@/components/Icons/TaskIcon.vue'
import DurationIcon from '@/components/Icons/DurationIcon.vue'
import CalendarIcon from '@/components/Icons/CalendarIcon.vue'
import TaskStatusIcon from '@/components/Icons/TaskStatusIcon.vue'
import PlayIcon from '@/components/Icons/PlayIcon.vue'
import LeadsIcon from '@/components/Icons/LeadsIcon.vue'
import DealsIcon from '@/components/Icons/DealsIcon.vue'
@ -559,6 +599,7 @@ import {
dateTooltipFormat,
secondsToDuration,
startCase,
taskStatusOptions,
} from '@/utils'
import { usersStore } from '@/stores/users'
import { contactsStore } from '@/stores/contacts'
@ -572,6 +613,7 @@ import {
createResource,
createListResource,
call,
Badge,
} from 'frappe-ui'
import { ref, computed, h, defineModel, markRaw, watch } from 'vue'
@ -837,6 +879,17 @@ function showTask(t) {
showTaskModal.value = true
}
function updateTaskStatus(status, task) {
call('frappe.client.set_value', {
doctype: 'CRM Task',
name: task.name,
fieldname: 'status',
value: status,
}).then(() => {
tasks.reload()
})
}
watch([reload, reload_email], ([reload_value, reload_email_value]) => {
if (reload_value || reload_email_value) {
versions.reload()

View File

@ -0,0 +1,16 @@
<template>
<svg
width="16"
height="16"
viewBox="0 0 16 16"
fill="none"
xmlns="http://www.w3.org/2000/svg"
>
<path
fill-rule="evenodd"
clip-rule="evenodd"
d="M4.5 1C4.77614 1 5 1.22386 5 1.5V2.5L5 2.50056C5.15613 2.5 5.32244 2.5 5.5 2.5H10.5C10.6776 2.5 10.8439 2.5 11 2.50056C11 2.50037 11 2.50019 11 2.5V1.5C11 1.22386 11.2239 1 11.5 1C11.7761 1 12 1.22386 12 1.5V2.5C12 2.50803 11.9998 2.51602 11.9994 2.52395C12.49 2.55387 12.838 2.62116 13.135 2.77248C13.6054 3.01217 13.9878 3.39462 14.2275 3.86502C14.5 4.3998 14.5 5.09987 14.5 6.5V10.5C14.5 11.9001 14.5 12.6002 14.2275 13.135C13.9878 13.6054 13.6054 13.9878 13.135 14.2275C12.6002 14.5 11.9001 14.5 10.5 14.5H5.5C4.09987 14.5 3.3998 14.5 2.86502 14.2275C2.39462 13.9878 2.01217 13.6054 1.77248 13.135C1.5 12.6002 1.5 11.9001 1.5 10.5V6.5C1.5 5.09987 1.5 4.3998 1.77248 3.86502C2.01217 3.39462 2.39462 3.01217 2.86502 2.77248C3.16202 2.62116 3.51 2.55387 4.00056 2.52395C4.00019 2.51602 4 2.50803 4 2.5V1.5C4 1.22386 4.22386 1 4.5 1ZM5.5 3.5H10.5C11.2166 3.5 11.6938 3.50078 12.0606 3.53074C12.4156 3.55975 12.5781 3.61105 12.681 3.66349C12.9632 3.8073 13.1927 4.03677 13.3365 4.31901C13.389 4.42194 13.4403 4.5844 13.4693 4.93944C13.4916 5.21337 13.4977 5.54901 13.4994 6H2.50061C2.50226 5.54901 2.50836 5.21337 2.53074 4.93944C2.55975 4.5844 2.61105 4.42194 2.66349 4.31901C2.8073 4.03677 3.03677 3.8073 3.31901 3.66349C3.42194 3.61105 3.5844 3.55975 3.93944 3.53074C4.30615 3.50078 4.78343 3.5 5.5 3.5ZM2.5 7V10.5C2.5 11.2166 2.50078 11.6939 2.53074 12.0606C2.55975 12.4156 2.61105 12.5781 2.66349 12.681C2.8073 12.9632 3.03677 13.1927 3.31901 13.3365C3.42194 13.389 3.5844 13.4403 3.93944 13.4693C4.30615 13.4992 4.78343 13.5 5.5 13.5H10.5C11.2166 13.5 11.6938 13.4992 12.0606 13.4693C12.4156 13.4403 12.5781 13.389 12.681 13.3365C12.9632 13.1927 13.1927 12.9632 13.3365 12.681C13.389 12.5781 13.4403 12.4156 13.4693 12.0606C13.4992 11.6939 13.5 11.2166 13.5 10.5V7H2.5Z"
fill="currentColor"
/>
</svg>
</template>

View File

@ -6,6 +6,14 @@
fill="none"
xmlns="http://www.w3.org/2000/svg"
>
<circle cx="8" cy="8" r="3.5" fill="currentColor" />
<circle cx="8" cy="8" :r="radius" fill="currentColor" />
</svg>
</template>
<script setup>
const props = defineProps({
radius: {
type: Number,
default: 3.5,
},
})
</script>

View File

@ -37,7 +37,7 @@
/>
</div>
<div class="flex items-center gap-2">
<Dropdown :options="statusOptions()">
<Dropdown :options="taskStatusOptions(updateTaskStatus)">
<Button :label="_task.status" class="w-full justify-between">
<template #prefix>
<TaskStatusIcon :status="_task.status" />
@ -64,7 +64,7 @@
input-class="border-none"
:formatValue="(val) => val.split('-').reverse().join('-')"
/>
<Dropdown :options="priorityOptions()">
<Dropdown :options="taskPriorityOptions(updateTaskPriority)">
<Button :label="_task.priority" class="w-full justify-between">
<template #prefix>
<TaskPriorityIcon :priority="_task.priority" />
@ -81,7 +81,7 @@
import TaskStatusIcon from '@/components/Icons/TaskStatusIcon.vue'
import TaskPriorityIcon from '@/components/Icons/TaskPriorityIcon.vue'
import UserAvatar from '@/components/UserAvatar.vue'
import { activeAgents } from '@/utils'
import { activeAgents, taskStatusOptions, taskPriorityOptions } from '@/utils'
import { usersStore } from '@/stores/users'
import {
TextInput,
@ -112,34 +112,23 @@ const emit = defineEmits(['updateTask'])
const title = ref(null)
const editMode = ref(false)
const _task = ref({})
const _task = ref({
title: '',
description: '',
assigned_to: '',
due_date: '',
status: 'Backlog',
priority: 'Low',
})
const { getUser } = usersStore()
function statusOptions() {
return ['Backlog', 'Todo', 'In Progress', 'Done', 'Canceled'].map(
(status) => {
return {
icon: () => h(TaskStatusIcon, { status }),
label: status,
onClick: () => {
_task.value.status = status
},
}
}
)
function updateTaskStatus(status) {
_task.value.status = status
}
function priorityOptions() {
return ['Low', 'Medium', 'High'].map((priority) => {
return {
label: priority,
icon: () => h(TaskPriorityIcon, { priority }),
onClick: () => {
_task.value.priority = priority
},
}
})
function updateTaskPriority(priority) {
_task.value.priority = priority
}
async function updateTask(close) {

View File

@ -1,4 +1,6 @@
import IndicatorIcon from '@/components/Icons/IndicatorIcon.vue'
import TaskStatusIcon from '@/components/Icons/TaskStatusIcon.vue'
import TaskPriorityIcon from '@/components/Icons/TaskPriorityIcon.vue'
import { usersStore } from '@/stores/users'
import { useDateFormat, useTimeAgo } from '@vueuse/core'
import { toast } from 'frappe-ui'
@ -92,6 +94,28 @@ export function statusDropdownOptions(data, doctype, action) {
return options
}
export function taskStatusOptions(action, data) {
return ['Backlog', 'Todo', 'In Progress', 'Done', 'Canceled'].map(
(status) => {
return {
icon: () => h(TaskStatusIcon, { status }),
label: status,
onClick: () => action && action(status, data),
}
}
)
}
export function taskPriorityOptions(action, data) {
return ['Low', 'Medium', 'High'].map((priority) => {
return {
label: priority,
icon: () => h(TaskPriorityIcon, { priority }),
onClick: () => action && action(priority, data),
}
})
}
export function openWebsite(url) {
window.open(url, '_blank')
}