Skip to content

Commit 9766024

Browse files
authored
feat: agreement, legal entity (#14)
1 parent c3c9f08 commit 9766024

20 files changed

Lines changed: 532 additions & 274 deletions

File tree

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

Lines changed: 43 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,25 @@
11
<template>
22
<ActiveCard padding="none" class="flex flex-col gap-2.5 group">
3-
<img
4-
:src="partner.avatarUrl ?? undefined"
5-
alt=""
6-
class="aspect-square w-full rounded-lg duration-200"
7-
:class="{ 'opacity-75 grayscale group-hover:grayscale-0 group-hover:opacity-100': imagesMode === 'grayscale' }"
8-
>
3+
<div class="relative">
4+
<img
5+
:src="partner.avatarUrl ?? undefined"
6+
alt=""
7+
class="aspect-square w-full rounded-lg duration-200"
8+
:class="{ 'opacity-75 grayscale group-hover:grayscale-0 group-hover:opacity-100': imagesMode === 'grayscale' }"
9+
>
10+
11+
<div class="absolute top-2 left-0 right-0 w-full">
12+
<div class="mx-2 px-2 py-1 bg-default/97 rounded-lg flex flex-row items-center gap-1.5">
13+
<UIcon name="i-lucide-scroll-text" class="shrink-0 size-5 text-secondary" />
14+
15+
<UProgress
16+
v-model="agreementProgress"
17+
size="md"
18+
color="secondary"
19+
/>
20+
</div>
21+
</div>
22+
</div>
923

1024
<div class="min-h-20 h-full px-2.5 pb-2 flex flex-col gap-2.5">
1125
<div class="flex flex-row items-center gap-2">
@@ -23,7 +37,11 @@
2337
</div>
2438

2539
<p class="text-sm/4 text-muted line-clamp-3">
26-
{{ partner.legal }}
40+
{{ partner.legalEntity?.name }}
41+
</p>
42+
43+
<p class="text-sm/4 text-error line-clamp-3">
44+
{{ partner?.legal }}
2745
</p>
2846

2947
<p class="text-sm/4 text-muted line-clamp-3">
@@ -34,11 +52,26 @@
3452
</template>
3553

3654
<script setup lang="ts">
37-
import type { Partner } from '@roll-stack/database'
55+
import type { Partner, PartnerAgreement, PartnerLegalEntity } from '@roll-stack/database'
3856
39-
defineProps<{
40-
partner: Partner
57+
const { partner } = defineProps<{
58+
partner: Partner & {
59+
legalEntity: PartnerLegalEntity | null
60+
activeAgreement: PartnerAgreement | null
61+
}
4162
}>()
4263
4364
const { imagesMode } = useApp()
65+
66+
const agreementProgress = computed(() => {
67+
if (!partner?.activeAgreement?.willEndAt || !partner?.activeAgreement?.concludedAt) {
68+
return 0
69+
}
70+
71+
const now = new Date()
72+
const concludedAt = new Date(partner.activeAgreement.concludedAt)
73+
const willEndAt = new Date(partner.activeAgreement.willEndAt)
74+
75+
return Math.floor(100 - ((now.getTime() - concludedAt.getTime()) / (willEndAt.getTime() - concludedAt.getTime())) * 100)
76+
})
4477
</script>

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

Lines changed: 115 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -1,58 +1,137 @@
11
<template>
22
<Content>
3-
<div class="grid grid-cols-1 gap-4 md:gap-6 md:grid-cols-2 lg:grid-cols-3 xl:grid-cols-4">
4-
<div class="flex flex-col gap-2.5">
5-
<img
6-
:src="partner?.avatarUrl ?? undefined"
7-
alt=""
8-
class="w-full rounded-lg"
9-
>
10-
</div>
11-
12-
<div class="flex flex-col gap-2.5">
13-
<div class="flex flex-row items-center gap-1.5">
14-
<PartnerPrestigeBadge
15-
:prestige="partner?.prestige ?? 0"
16-
size="lg"
17-
class="group-hover:scale-125 duration-200"
18-
/>
19-
<h3 class="text-xl md:text-2xl font-semibold">
20-
Престиж
3+
<div class="grid grid-cols-1 gap-4 md:gap-6 md:grid-cols-2 lg:grid-cols-3 xl:grid-cols-4 2xl:grid-cols-5">
4+
<UCard variant="subtle" class="col-span-1">
5+
<div class="flex flex-col gap-2.5">
6+
<div class="flex flex-col items-start gap-2">
7+
<div class="flex flex-row items-center gap-3.5">
8+
<img
9+
:src="partner?.avatarUrl ?? undefined"
10+
alt=""
11+
class="aspect-square size-20 rounded-lg"
12+
>
13+
<h2 class="text-xl md:text-2xl/7 font-semibold">
14+
{{ partner?.name }} {{ partner?.surname }}
15+
</h2>
16+
</div>
17+
18+
<p class="text-base">
19+
{{ partner?.priceLevel }} уровень цен
20+
</p>
21+
22+
<p class="text-base">
23+
{{ partner?.city }}
24+
</p>
25+
</div>
26+
</div>
27+
</UCard>
28+
29+
<UCard class="col-span-1">
30+
<div class="flex flex-col gap-2.5">
31+
<div class="flex flex-row items-center gap-1.5">
32+
<PartnerPrestigeBadge
33+
:prestige="partner?.prestige ?? 0"
34+
size="lg"
35+
class="group-hover:scale-125 duration-200"
36+
/>
37+
<h3 class="text-xl md:text-2xl font-semibold">
38+
Престиж
39+
</h3>
40+
</div>
41+
<p class="text-muted leading-5">
42+
Престиж не является статичным - он может как укрепляться, так и утрачиваться в зависимости от действий Партнера, его достижений и общественного восприятия.
43+
</p>
44+
</div>
45+
</UCard>
46+
47+
<UCard v-if="partner?.legalEntity" class="col-span-2">
48+
<div class="flex flex-col gap-2.5">
49+
<UIcon name="i-lucide-scale" class="size-16 text-muted/25" />
50+
51+
<h3 class="text-xl md:text-xl/6 font-semibold">
52+
{{ partner.legalEntity.name }}
2153
</h3>
54+
55+
<div>
56+
<p>ИНН {{ partner.legalEntity.inn }}</p>
57+
<p>ОГРНИП {{ partner.legalEntity.ogrnip }}</p>
58+
</div>
59+
60+
<p class="text-muted">
61+
{{ partner.legalEntity.comment }}
62+
</p>
2263
</div>
23-
<p class="text-muted leading-5">
24-
Престиж не является статичным - он может как укрепляться, так и утрачиваться в зависимости от действий Партнера, его достижений и общественного восприятия.
25-
</p>
26-
</div>
27-
</div>
64+
</UCard>
2865

29-
<div class="flex flex-col items-start gap-2">
30-
<h2 class="text-xl md:text-3xl font-bold">
31-
{{ partner?.name }} {{ partner?.surname }}
32-
</h2>
66+
<UCard
67+
v-if="partner?.activeAgreement"
68+
variant="subtle"
69+
class="col-span-2"
70+
>
71+
<div class="flex flex-col gap-3">
72+
<div class="flex flex-row items-start gap-3.5">
73+
<UIcon name="i-lucide-scroll-text" class="shrink-0 size-16 text-secondary" />
3374

34-
<p class="text-lg">
35-
{{ partner?.legal }}
36-
</p>
75+
<UProgress
76+
v-model="agreementProgress"
77+
size="lg"
78+
color="secondary"
79+
status
80+
/>
81+
</div>
3782

38-
<p class="text-base">
39-
{{ partner?.priceLevel }} уровень цен
40-
</p>
83+
<h3 class="text-xl md:text-xl/6 font-semibold">
84+
Договор №{{ partner.activeAgreement.internalId }}
85+
</h3>
86+
87+
<div>
88+
<p v-if="partner.activeAgreement.willEndAt">
89+
Заключен до {{ format(new Date(partner.activeAgreement.willEndAt), 'd MMMM yyyy', { locale: ru }) }}
90+
</p>
91+
<p>Роялти: {{ partner.activeAgreement.royalty }}%</p>
92+
<p>Мин. роялти: {{ partner.activeAgreement.minRoyaltyPerMonth }} ₽ / месяц</p>
93+
94+
<p v-if="partner.activeAgreement.marketingFee">
95+
Маркетинговый сбор: {{ partner.activeAgreement.marketingFee }}%
96+
</p>
97+
<p v-if="partner.activeAgreement.minMarketingFeePerMonth">
98+
Мин. маркетинговый сбор: {{ partner.activeAgreement.minMarketingFeePerMonth }} ₽ / месяц
99+
</p>
41100

42-
<p class="text-base">
43-
{{ partner?.city }}
44-
</p>
101+
<p>Паушальный взнос: {{ partner.activeAgreement.lumpSumPayment }} ₽</p>
102+
</div>
103+
104+
<p class="text-muted">
105+
{{ partner.activeAgreement.comment }}
106+
</p>
107+
</div>
108+
</UCard>
45109
</div>
46110
</Content>
47111
</template>
48112

49113
<script setup lang="ts">
114+
import { format } from 'date-fns'
115+
import { ru } from 'date-fns/locale/ru'
116+
50117
const { t } = useI18n()
51118
const { params } = useRoute('partner-id')
52119
53120
const partnerStore = usePartnerStore()
54121
const partner = computed(() => partnerStore.partners.find((partner) => partner.id === params.id))
55122
123+
const agreementProgress = computed(() => {
124+
if (!partner.value?.activeAgreement?.willEndAt || !partner.value?.activeAgreement?.concludedAt) {
125+
return 0
126+
}
127+
128+
const now = new Date()
129+
const concludedAt = new Date(partner.value.activeAgreement.concludedAt)
130+
const willEndAt = new Date(partner.value.activeAgreement.willEndAt)
131+
132+
return Math.floor(100 - ((now.getTime() - concludedAt.getTime()) / (willEndAt.getTime() - concludedAt.getTime())) * 100)
133+
})
134+
56135
useHead({
57136
title: t('common.partner'),
58137
})
Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,9 @@
1-
import type { Kitchen, Partner } from '@roll-stack/database'
1+
import type { Kitchen, Partner, PartnerAgreement, PartnerLegalEntity } from '@roll-stack/database'
22

33
type PartnerWithData = Partner & {
44
kitchens: Kitchen[]
5+
legalEntity: PartnerLegalEntity | null
6+
activeAgreement: PartnerAgreement | null
57
}
68

79
export const usePartnerStore = defineStore('partner', () => {

0 commit comments

Comments
 (0)