Skip to content

Commit 87821c3

Browse files
authored
feat: update partner action (#73)
* feat: update partner action * chore: button updated
1 parent 524af09 commit 87821c3

12 files changed

Lines changed: 261 additions & 38 deletions

File tree

apps/web-app/app/components/PartnerAgreementCard.vue

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,11 @@
11
<template>
22
<UCard
3-
class="h-full"
3+
class="h-full group/list"
44
:class="[
55
!agreement.isActive && 'opacity-75 grayscale-100',
66
]"
77
>
8-
<div class="flex flex-col gap-3 group/list">
8+
<div class="flex flex-col gap-3">
99
<div class="flex flex-row justify-between">
1010
<div class="flex flex-row items-start gap-2.5">
1111
<UIcon name="i-lucide-scroll-text" class="shrink-0 size-14 text-primary" />

apps/web-app/app/components/PartnerLegalEntityCard.vue

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
<template>
2-
<UCard class="h-full">
3-
<div class="flex flex-col gap-3 group/list">
2+
<UCard class="h-full group/list">
3+
<div class="flex flex-col gap-3">
44
<div class="flex flex-row justify-between">
55
<div class="flex flex-row items-start gap-2.5">
66
<UIcon name="i-lucide-scale" class="size-14 text-primary" />
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
<template>
2+
<UCard class="h-full group/list">
3+
<div class="shrink-0 w-full flex flex-col gap-2">
4+
<div class="flex flex-row justify-between">
5+
<div class="flex flex-row items-start gap-2.5">
6+
<UIcon name="i-lucide-handshake" class="size-14 text-primary" />
7+
</div>
8+
9+
<UTooltip text="Редактировать">
10+
<UButton
11+
variant="outline"
12+
color="neutral"
13+
size="md"
14+
icon="i-lucide-pencil"
15+
class="size-10 justify-center opacity-0 group-hover/list:opacity-100"
16+
@click="modalUpdatePartner.open({ partnerId: partner.id })"
17+
/>
18+
</UTooltip>
19+
</div>
20+
21+
<h3 class="text-xl md:text-xl/6 font-semibold">
22+
{{ partner?.priceLevel }} уровень цен
23+
</h3>
24+
25+
<p class="text-base/5">
26+
{{ partner?.city }}
27+
</p>
28+
</div>
29+
</UCard>
30+
</template>
31+
32+
<script setup lang="ts">
33+
import type { Partner } from '@roll-stack/database'
34+
import { ModalUpdatePartner } from '#components'
35+
36+
defineProps<{ partner: Partner }>()
37+
38+
const overlay = useOverlay()
39+
const modalUpdatePartner = overlay.create(ModalUpdatePartner)
40+
</script>
Lines changed: 114 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,114 @@
1+
<template>
2+
<UForm
3+
:validate="createValidator(updatePartnerSchema)"
4+
:state="state"
5+
class="flex flex-col gap-3"
6+
@submit="onSubmit"
7+
>
8+
<UFormField
9+
:label="$t('app.partner-legal-entity.title')"
10+
name="legalEntityId"
11+
required
12+
>
13+
<USelectMenu
14+
v-model="selectedLegalEntity"
15+
:items="legalEntities"
16+
:placeholder="$t('common.select')"
17+
size="xl"
18+
class="w-full"
19+
/>
20+
</UFormField>
21+
22+
<UFormField
23+
:label="$t('common.city')"
24+
name="city"
25+
required
26+
>
27+
<UInput
28+
v-model="state.city"
29+
size="xl"
30+
class="w-full items-center justify-center"
31+
/>
32+
</UFormField>
33+
34+
<UFormField
35+
:label="$t('app.price-level')"
36+
name="priceLevel"
37+
required
38+
>
39+
<UInputNumber
40+
v-model="state.priceLevel"
41+
orientation="vertical"
42+
size="xl"
43+
class="w-full items-center justify-center"
44+
/>
45+
</UFormField>
46+
47+
<UButton
48+
type="submit"
49+
variant="solid"
50+
color="secondary"
51+
size="xl"
52+
block
53+
class="mt-3"
54+
:label="$t('common.update')"
55+
/>
56+
</UForm>
57+
</template>
58+
59+
<script setup lang="ts">
60+
import type { UpdatePartner } from '#shared/services/partner'
61+
import type { FormSubmitEvent } from '@nuxt/ui'
62+
import { updatePartnerSchema } from '#shared/services/partner'
63+
64+
const { partnerId } = defineProps<{
65+
partnerId: string
66+
}>()
67+
68+
const emit = defineEmits(['success', 'submitted'])
69+
70+
const { t } = useI18n()
71+
const actionToast = useActionToast()
72+
73+
const partnerStore = usePartnerStore()
74+
const partner = computed(() => partnerStore.partners.find((partner) => partner.id === partnerId))
75+
76+
const state = ref<Partial<UpdatePartner>>({
77+
city: partner.value?.city ?? undefined,
78+
priceLevel: partner.value?.priceLevel ?? undefined,
79+
legalEntityId: partner.value?.legalEntityId ?? undefined,
80+
})
81+
82+
const legalEntities = computed(() => partnerStore.legalEntities.map((legalEntity) => {
83+
return {
84+
label: legalEntity.name,
85+
value: legalEntity.id,
86+
}
87+
}))
88+
89+
const selectedLegalEntity = ref(legalEntities.value.find((legalEntity) => legalEntity.value === partner.value?.legalEntityId))
90+
91+
watch(selectedLegalEntity, (newValue) => {
92+
state.value.legalEntityId = newValue?.value
93+
})
94+
95+
async function onSubmit(event: FormSubmitEvent<UpdatePartner>) {
96+
const toastId = actionToast.start()
97+
emit('submitted')
98+
99+
try {
100+
await $fetch(`/api/partner/id/${partnerId}`, {
101+
method: 'PATCH',
102+
body: event.data,
103+
})
104+
105+
await partnerStore.update()
106+
107+
actionToast.success(toastId, t('toast.partner-updated'))
108+
emit('success')
109+
} catch (error) {
110+
console.error(error)
111+
actionToast.error(toastId)
112+
}
113+
}
114+
</script>
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
<template>
2+
<UModal :title="$t('app.update.partner.title')">
3+
<template #body>
4+
<FormUpdatePartner
5+
:partner-id="partnerId"
6+
@submitted="overlay.closeAll"
7+
@success="overlay.closeAll"
8+
/>
9+
</template>
10+
</UModal>
11+
</template>
12+
13+
<script setup lang="ts">
14+
defineProps<{
15+
partnerId: string
16+
}>()
17+
18+
const overlay = useOverlay()
19+
</script>

apps/web-app/app/pages/agreement/index.vue

Lines changed: 26 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -38,25 +38,17 @@
3838
/>
3939
</UDropdownMenu>
4040

41-
<UButton
42-
size="md"
43-
variant="solid"
44-
color="secondary"
45-
class="w-full md:w-fit"
46-
icon="i-lucide-circle-plus"
47-
:label="t('app.create.partner-legal-entity.button')"
48-
@click="modalCreatePartnerLegalEntity.open()"
49-
/>
50-
51-
<UButton
52-
size="md"
53-
variant="solid"
54-
color="secondary"
55-
class="w-full md:w-fit"
56-
icon="i-lucide-circle-plus"
57-
:label="t('app.create.agreement.button')"
58-
@click="modalCreatePartnerAgreement.open()"
59-
/>
41+
<UDropdownMenu
42+
:items="itemsForCreateButton"
43+
:content="{ align: 'end' }"
44+
class="ml-auto"
45+
>
46+
<UButton
47+
icon="i-lucide-plus"
48+
color="secondary"
49+
variant="solid"
50+
/>
51+
</UDropdownMenu>
6052
</div>
6153
</div>
6254

@@ -309,6 +301,21 @@ function getDropdownActions(agreement: PartnerAgreement): DropdownMenuItem[][] {
309301
]
310302
}
311303
304+
const itemsForCreateButton = computed<DropdownMenuItem[]>(() => [
305+
{
306+
label: t('app.create.partner-legal-entity.button'),
307+
type: 'link',
308+
onSelect: () => modalCreatePartnerLegalEntity.open(),
309+
icon: 'i-lucide-scale',
310+
},
311+
{
312+
label: t('app.create.agreement.button'),
313+
type: 'link',
314+
onSelect: () => modalCreatePartnerAgreement.open(),
315+
icon: 'i-lucide-scroll-text',
316+
},
317+
])
318+
312319
const table = useTemplateRef('table')
313320
314321
useHead({

apps/web-app/app/pages/partner/[id]/index.vue

Lines changed: 1 addition & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,7 @@
11
<template>
22
<Content>
33
<div class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 xl:grid-cols-6 2xl:grid-cols-7 gap-4 md:gap-6">
4-
<UCard>
5-
<div class="shrink-0 w-full flex flex-col gap-2">
6-
<UIcon name="i-lucide-handshake" class="size-14 text-primary" />
7-
8-
<h3 class="text-xl md:text-xl/6 font-semibold">
9-
{{ partner?.priceLevel }} уровень цен
10-
</h3>
11-
12-
<p class="text-base/5">
13-
{{ partner?.city }}
14-
</p>
15-
</div>
16-
</UCard>
4+
<PartnerPageCard v-if="partner" :partner="partner" />
175

186
<UCard>
197
<div class="flex flex-col gap-2.5">

apps/web-app/i18n/locales/ru-RU.json

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,7 @@
7070
"preview": "Предпросмотр",
7171
"price": "Цена",
7272
"sku": "Артикул",
73+
"city": "Город",
7374
"weight-or-volume": "Вес / Объем",
7475
"measurement-unit": "Ед. измерения",
7576
"abbreviation": {
@@ -163,6 +164,7 @@
163164
"partner-legal-entity": {
164165
"title": "Юридическое лицо"
165166
},
167+
"price-level": "Уровень цен",
166168
"create": {
167169
"idea": {
168170
"button": "Предложить свою идею",
@@ -267,6 +269,10 @@
267269
"activity-schedule-item": {
268270
"button": "Обновить активность",
269271
"title": "Обновление активности"
272+
},
273+
"partner": {
274+
"button": "Обновить партнера",
275+
"title": "Обновление партнера"
270276
}
271277
},
272278
"delete": {
@@ -390,6 +396,9 @@
390396
"print-created": "Материал создан",
391397
"print-updated": "Материал обновлен",
392398
"print-deleted": "Материал удален",
399+
"partner-created": "Партнер создан",
400+
"partner-updated": "Партнер обновлен",
401+
"partner-deleted": "Партнер удален",
393402
"partner-legal-entity-created": "Юридическое лицо создано",
394403
"partner-legal-entity-updated": "Юридическое лицо обновлено",
395404
"partner-legal-entity-deleted": "Юридическое лицо удалено",

apps/web-app/server/api/partner/agreement/id/[agreementId]/index.patch.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ export default defineEventHandler(async (event) => {
2323
const agreement = await repository.partner.findAgreement(agreementId)
2424
if (!agreement) {
2525
throw createError({
26-
statusCode: 400,
26+
statusCode: 404,
2727
message: 'Agreement not found',
2828
})
2929
}
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
import { repository } from '@roll-stack/database'
2+
import { type } from 'arktype'
3+
import { updatePartnerSchema } from '~~/shared/services/partner'
4+
5+
export default defineEventHandler(async (event) => {
6+
try {
7+
// await hasPermission(event, 'product:edit')
8+
9+
const partnerId = getRouterParam(event, 'partnerId')
10+
if (!partnerId) {
11+
throw createError({
12+
statusCode: 400,
13+
message: 'Id is required',
14+
})
15+
}
16+
17+
const body = await readBody(event)
18+
const data = updatePartnerSchema(body)
19+
if (data instanceof type.errors) {
20+
throw data
21+
}
22+
23+
const partner = await repository.partner.find(partnerId)
24+
if (!partner) {
25+
throw createError({
26+
statusCode: 404,
27+
message: 'Partner not found',
28+
})
29+
}
30+
31+
await repository.partner.update(partnerId, data)
32+
33+
return {
34+
ok: true,
35+
}
36+
} catch (error) {
37+
throw errorResolver(error)
38+
}
39+
})

0 commit comments

Comments
 (0)