Skip to content

Commit 70b4d4b

Browse files
author
samarbadriddin0v
committed
Create deals
1 parent 0b4c0be commit 70b4d4b

File tree

5 files changed

+177
-34
lines changed

5 files changed

+177
-34
lines changed

components/shared/create-deal.vue

Lines changed: 114 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1,114 @@
1-
<template>create deal</template>
1+
<script setup lang="ts">
2+
import type { FormError, FormSubmitEvent } from '#ui/types'
3+
import { useMutation } from '@tanstack/vue-query'
4+
import { COLLECTION_DEALS, DB_ID } from '~/constants'
5+
import { DATABASE, UNIQUE_ID } from '~/libs/appwrite'
6+
import { useAuthStore } from '~/store/auth.store'
7+
import type { ICreateDeals } from '~/types'
8+
9+
const props = defineProps({
10+
status: {
11+
type: String,
12+
default: '',
13+
required: true,
14+
},
15+
refetch: {
16+
type: Function,
17+
required: true,
18+
},
19+
})
20+
21+
const toast = useToast()
22+
const { currentUser } = useAuthStore()
23+
24+
const state = reactive({
25+
name: undefined,
26+
description: undefined,
27+
})
28+
29+
const validate = (state: any): FormError[] => {
30+
const errors = []
31+
if (!state.name) errors.push({ path: 'name', message: 'Name is requierd' })
32+
if (!state.description)
33+
errors.push({ path: 'description', message: 'Description is required' })
34+
return errors
35+
}
36+
37+
const { isPending, mutate } = useMutation({
38+
mutationKey: ['create-deal'],
39+
mutationFn: (data: ICreateDeals) =>
40+
DATABASE.createDocument(DB_ID, COLLECTION_DEALS, UNIQUE_ID, data),
41+
onSuccess: () => {
42+
props.refetch()
43+
state.name = undefined
44+
state.description = undefined
45+
toast.add({
46+
title: 'Success',
47+
description: 'Deal created successfully',
48+
})
49+
},
50+
onError: () => {
51+
toast.add({
52+
title: 'Error',
53+
description: 'Something went wrong',
54+
color: 'red',
55+
})
56+
},
57+
})
58+
59+
async function onSubmit(event: FormSubmitEvent<any>) {
60+
const { name, description } = event.data
61+
62+
mutate({
63+
name,
64+
description,
65+
status: props.status,
66+
userId: currentUser.id,
67+
})
68+
}
69+
</script>
70+
71+
<template>
72+
<UPopover :popper="{ placement: 'right' }">
73+
<UButton
74+
variant="ghost"
75+
class="opacity-75 hover:opacity-100 mx-auto mt-3"
76+
color="blue"
77+
>
78+
<Icon name="radix-icons:plus-circled" size="35" />
79+
</UButton>
80+
81+
<template #panel>
82+
<div class="p-4 w-80 dark:bg-gray-900 bg-gray-100">
83+
<UForm
84+
:validate="validate"
85+
:state="state"
86+
class="space-y-4"
87+
@submit="onSubmit"
88+
>
89+
<UFormGroup label="Name" name="name">
90+
<UInput v-model="state.name" color="blue" size="lg" />
91+
</UFormGroup>
92+
93+
<UFormGroup label="Description" name="description">
94+
<UTextarea v-model="state.description" color="blue" size="lg" />
95+
</UFormGroup>
96+
97+
<UButton
98+
type="submit"
99+
color="blue"
100+
class="w-full"
101+
block
102+
size="lg"
103+
:disabled="isPending"
104+
>
105+
<template v-if="isPending">
106+
<Icon name="svg-spinners:3-dots-fade" class="w-5 h-5" />
107+
</template>
108+
<template v-else>Submit</template>
109+
</UButton>
110+
</UForm>
111+
</div>
112+
</template>
113+
</UPopover>
114+
</template>

components/ui/deals-loader.vue

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
<div class="text-center">
44
<Icon name="svg-spinners:3-dots-fade" class="w-5 h-5" />
55
</div>
6-
<div class="my-3 bg-gray-900 rounded-md p-2 animation">
6+
<div class="my-3 dark:bg-gray-900 bg-gray-300 rounded-md p-2 animation">
77
<USkeleton class="w-10/12 h-4" />
88
<USkeleton class="w-full h-1 my-3" />
99
<USkeleton class="w-full h-8" />

layouts/documents.vue

Lines changed: 24 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,28 @@
1+
<script setup lang="ts">
2+
import { ACCOUNT } from '~/libs/appwrite'
3+
import { useAuthStore } from '~/store/auth.store'
4+
import { useLoadingStore } from '~/store/loading.store'
5+
6+
const authStore = useAuthStore()
7+
const loadingStore = useLoadingStore()
8+
9+
onMounted(() => {
10+
ACCOUNT.get()
11+
.then(response =>
12+
authStore.set({
13+
email: response.email,
14+
id: response.$id,
15+
name: response.name,
16+
status: response.status,
17+
})
18+
)
19+
.finally(() => loadingStore.set(false))
20+
})
21+
</script>
22+
123
<template>
2-
<main>
24+
<UiLoader v-if="loadingStore.isLoading" />
25+
<main v-else>
326
<LayoutsNavbar />
427
<LayoutsSidebar />
528
<section class="min-h-screen bg-white dark:bg-black pl-72 pt-[10vh]">

pages/documents.vue

Lines changed: 31 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -1,39 +1,18 @@
11
<script setup lang="ts">
2-
import { ACCOUNT } from '~/libs/appwrite'
32
import { useStatusQuery } from '~/query/use-status-query'
4-
import { useAuthStore } from '~/store/auth.store'
5-
import { useLoadingStore } from '~/store/loading.store'
63
74
definePageMeta({ layout: 'documents' })
85
useHead({ title: 'Documents | Jira software' })
96
10-
const router = useRouter()
11-
const loadingStore = useLoadingStore()
12-
const authStore = useAuthStore()
13-
14-
onMounted(() => {
15-
ACCOUNT.get()
16-
.then(response => {
17-
loadingStore.set(false)
18-
authStore.set({
19-
email: response.email,
20-
id: response.$id,
21-
name: response.name,
22-
status: response.status,
23-
})
24-
})
25-
.catch(() => router.push('/auth'))
26-
})
27-
28-
const { data, isLoading } = useStatusQuery()
7+
const { data, isLoading, refetch } = useStatusQuery()
298
</script>
309

3110
<template>
3211
<div class="grid grid-cols-4 gap-2 mt-12" v-if="isLoading">
33-
<USkeleton class="h-12 bg-gray-900" />
34-
<USkeleton class="h-12 bg-gray-900" />
35-
<USkeleton class="h-12 bg-gray-900" />
36-
<USkeleton class="h-12 bg-gray-900" />
12+
<USkeleton class="h-12 dark:bg-gray-900 bg-gray-100" />
13+
<USkeleton class="h-12 dark:bg-gray-900 bg-gray-100" />
14+
<USkeleton class="h-12 dark:bg-gray-900 bg-gray-100" />
15+
<USkeleton class="h-12 dark:bg-gray-900 bg-gray-100" />
3716

3817
<UiDealsLoader />
3918
<UiDealsLoader />
@@ -42,17 +21,21 @@ const { data, isLoading } = useStatusQuery()
4221
</div>
4322

4423
<div class="grid grid-cols-4 gap-2 mt-12" v-else>
45-
<div v-for="item in data" :key="item.id">
24+
<div v-for="column in data" :key="column.id">
4625
<UButton class="w-full h-12" color="blue" variant="outline">
4726
<div class="flex items-center space-x-2">
48-
<span class="font-bold">{{ item.name }}</span>
49-
<span class="text-sm text-neutral-500">{{ item.items.length }}</span>
27+
<span class="font-bold">{{ column.name }}</span>
28+
<span class="text-sm text-neutral-500">{{
29+
column.items.length
30+
}}</span>
5031
</div>
5132
</UButton>
5233

34+
<SharedCreateDeal :status="column.id" :refetch="refetch" />
35+
5336
<div
54-
class="my-3 bg-gray-900 rounded-md p-2"
55-
v-for="card in item.items"
37+
class="my-3 dark:bg-gray-900 bg-gray-100 rounded-md p-2 animation"
38+
v-for="card in column.items"
5639
:key="card.$id"
5740
role="button"
5841
draggable="true"
@@ -78,3 +61,20 @@ const { data, isLoading } = useStatusQuery()
7861
</div>
7962
</div>
8063
</template>
64+
65+
<style scoped>
66+
@keyframes show {
67+
from {
68+
transform: scale(0.5) translateY(-30px);
69+
opacity: 0.4;
70+
}
71+
to {
72+
transform: scale(1) translateY(0);
73+
opacity: 1;
74+
}
75+
}
76+
77+
.animation {
78+
animation: show 0.3s ease-in-out;
79+
}
80+
</style>

types/index.ts

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,3 +26,10 @@ export interface IColumn {
2626
name: string
2727
items: IDeal[]
2828
}
29+
30+
export interface ICreateDeals {
31+
name: string
32+
description: string
33+
status: string
34+
userId: string
35+
}

0 commit comments

Comments
 (0)