Skip to content

Commit

Permalink
Merge pull request #51 from LucasWerey/feat/19
Browse files Browse the repository at this point in the history
feat(front): add demand card
  • Loading branch information
LucasWerey authored Jan 29, 2024
2 parents d3cb941 + 366390e commit ade3241
Show file tree
Hide file tree
Showing 10 changed files with 330 additions and 3 deletions.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ You will find the last version of the library here : https://github.com/LucasWer
In your main project import the library :

```bash
yarn add @lucaswerey/[email protected].57
yarn add @lucaswerey/[email protected].70
```

## Use docker
Expand Down
2 changes: 1 addition & 1 deletion badges/coverage.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@lucaswerey/dslib-pfe",
"version": "0.0.70",
"version": "0.0.71",
"private": false,
"main": "./lib/index.umd.js",
"module": "./lib/index.mjs",
Expand Down
2 changes: 2 additions & 0 deletions src/components.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,8 @@ declare module 'vue' {
ControlDescription: typeof import('./../histoire/components/internals/ControlDescription.vue')['default']
DeleteModal: typeof import('./components/Indicators/DeleteModal/DeleteModal.vue')['default']
'DeleteModal.story': typeof import('./components/Indicators/DeleteModal/DeleteModal.story.vue')['default']
DemandCard: typeof import('./components/Containment/DemandCard/DemandCard.vue')['default']
'DemandCard.story': typeof import('./components/Containment/DemandCard/DemandCard.story.vue')['default']
IconsBase: typeof import('./components/Media/IconsBase/IconsBase.vue')['default']
'IconsBase.story': typeof import('./components/Media/IconsBase/IconsBase.story.vue')['default']
InputField: typeof import('./components/CTA/InputField/InputField.vue')['default']
Expand Down
25 changes: 25 additions & 0 deletions src/components/Containment/DemandCard/DemandCard.model.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
/*
Avaible colors:
basic:
black: '#1B1B1E',
darkgrey: '#787878',
grey: '#CDCDCD',
lightgrey: '#ECECEC',
verylightgrey: '#F6F6F6',
white: '#FAFAFA'
primary:
DEFAULT: '#000000',
light: '#00F2A5',
charcoal: '#373F51',
moonstone: '#58A4B0',
powder: '#A9BCD0',
platinum: '#D8DBE2'
transparent: 'transparent',
current: 'currentColor',
inherit: 'inherit',
error: '#FF5656',
warning: '#FFC85C',
success: '#7BC079',
info: '#333333'
*/
95 changes: 95 additions & 0 deletions src/components/Containment/DemandCard/DemandCard.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
import { mount } from '@vue/test-utils'
import { it, describe, expect } from 'vitest'
import DemandCard from './DemandCard.vue'

describe('DemandCard.vue', () => {
it('renders correctly when type is empty', () => {
const wrapper = mount(DemandCard, {
props: {
type: 'empty',
title: '',
location: '',
nCandidates: 0,
contractType: '',
contractDuration: '',
id: '',
studentNames: [],
desktopColor: 'transparent',
notification: 0,
nMatchs: 0
}
})
expect(wrapper.find('[data-test="create-demand"]').exists()).toBe(true)
expect(wrapper.find('h5').text()).toBe('ajouter une demande')
})

it('renders correctly when type is fill', () => {
const wrapper = mount(DemandCard, {
props: {
type: 'fill',
title: 'Test Title',
location: 'Test Location',
nCandidates: 5,
contractType: 'Test Contract Type',
contractDuration: 'Test Contract Duration',
id: '1',
studentNames: ['John', 'Doe'],
desktopColor: 'error',
notification: 3,
nMatchs: 2
}
})
expect(wrapper.find('h4').text()).toBe('Test Title')
expect(wrapper.find('p').text()).toBe('Test Location')
expect(wrapper.find('.flex.w-full.items-center.gap-3.text-basic-black').exists()).toBe(true)
expect(wrapper.find('.flex.w-full.flex-col.gap-2').exists()).toBe(true)
expect(
wrapper
.find(
'.absolute.right-0.flex.h-4.w-16.items-center.justify-end.rounded-l-md.bg-error.px-2.drop-shadow-md'
)
.exists()
).toBe(true)
})

it('emits seeDemand event', async () => {
const wrapper = mount(DemandCard, {
props: {
type: 'fill',
title: 'Test Title',
location: 'Test Location',
nCandidates: 5,
contractType: 'Test Contract Type',
contractDuration: 'Test Contract Duration',
id: '1',
studentNames: ['John', 'Doe'],
desktopColor: 'error',
notification: 3,
nMatchs: 2
}
})
await wrapper.find('button').trigger('click')
expect(wrapper.emitted()).toHaveProperty('seeDemand')
expect(wrapper.emitted().seeDemand[0]).toEqual(['1']) // Check if the correct id is emitted
})

it('emits createDemand event', async () => {
const wrapper = mount(DemandCard, {
props: {
type: 'empty',
title: '',
location: '',
nCandidates: 0,
contractType: '',
contractDuration: '',
id: '',
studentNames: [],
desktopColor: 'transparent',
notification: 0,
nMatchs: 0
}
})
await wrapper.find('[data-test="create-demand"]').trigger('click')
expect(wrapper.emitted()).toHaveProperty('createDemand')
})
})
91 changes: 91 additions & 0 deletions src/components/Containment/DemandCard/DemandCard.story.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
<template>
<Story
title="Demand Card"
group="containment"
:layout="{
type: 'grid',
width: '50%'
}"
>
<template #controls>
<ControlDescription>
<HstSelect v-model="controls.type" :options="Object.values(OFFER_CARD_TYPE)" title="Type" />
</ControlDescription>
<ControlDescription>
<HstText v-model="controls.title" title="Title" />
</ControlDescription>
<ControlDescription>
<HstText v-model="controls.location" title="Location" />
</ControlDescription>
<ControlDescription>
<HstText v-model="controls.contractType" title="Contract type" />
</ControlDescription>
<ControlDescription>
<HstText v-model="controls.contractDuration" title="Contract duration" />
</ControlDescription>
<ControlDescription>
<HstText v-model="controls.id" title="Id" />
</ControlDescription>
<ControlDescription>
<HstNumber v-model="controls.nMatchs" title="Number of matchs" />
</ControlDescription>
<ControlDescription>
<HstNumber v-model="controls.notification" title="Number of notif" />
</ControlDescription>
<ControlDescription>
<HstSelect
v-model="controls.desktopColor"
:options="Object.keys(colorsPalette)"
title="Desktop color"
/>
</ControlDescription>
</template>

<Variant title="playground" auto-props-disabled>
<DemandCard
:type="controls.type"
:title="controls.title"
:location="controls.location"
:contract-type="controls.contractType"
:contract-duration="controls.contractDuration"
:id="controls.id"
:desktop-color="controls.desktopColor"
:notification="controls.notification"
:nMatchs="controls.nMatchs"
@seeOffer="() => {}"
@createOffer="() => {}"
/>
</Variant>
</Story>
</template>

<script setup lang="ts">
import { OFFER_CARD_TYPE_DEFAULT, OFFER_CARD_TYPE } from '../OfferCard/OfferCard.model'
import { colorsPalette } from '../../../tailwind/presetConfig'
import type { OfferCardType } from '../OfferCard/OfferCard.model'
import type { IconsColor } from '../../Media/IconsBase/IconsBase.model'
interface Controls {
type: OfferCardType
title: string
location: string
contractType: string
contractDuration: string
id: string
desktopColor: IconsColor
notification: number
nMatchs: number
}
const controls = reactive<Controls>({
type: OFFER_CARD_TYPE_DEFAULT,
title: 'default',
location: 'default',
contractType: 'default',
contractDuration: 'default',
id: '2323232',
desktopColor: 'warning',
notification: 0,
nMatchs: 0
})
</script>
112 changes: 112 additions & 0 deletions src/components/Containment/DemandCard/DemandCard.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,112 @@
<template>
<div class="h-60 max-h-60 w-80 max-w-80 overflow-hidden">
<div
v-if="isEmpty"
class="flex h-full w-full cursor-pointer flex-col items-center justify-center gap-2 rounded-xl border-2 border-primary-moonstone bg-primary-lightmoonstone text-primary-moonstone"
data-test="create-demand"
@click="emit('createDemand')"
>
<IconsBase name="plus" color="moonstone" size="large" />
<h5 class="text-center uppercase">ajouter une demande</h5>
</div>
<div
v-if="!isEmpty"
class="relative flex h-full w-full flex-col items-center justify-between rounded-xl bg-basic-white p-4"
>
<div class="flex w-full flex-col gap-4">
<div class="flex gap-4">
<IconsBase name="desktop" :color="desktopColor" class="h-14 w-14" />
<div class="flex flex-col">
<h4 class="font-eina1 text-5 font-bold text-basic-black">{{ title }}</h4>
<div class="flex items-start gap-1">
<IconsBase name="mapPin" color="basic" size="small" />
<p class="font-eina1 text-3">{{ location }}</p>
</div>
</div>
</div>
<div class="flex w-full items-center gap-3 text-basic-black">
<div class="flex gap-2">
<ChipContainer :label="contractType" />
<ChipContainer :label="contractDuration" />
</div>
</div>
</div>
<div class="flex w-full flex-col gap-2">
<div class="flex w-full items-center justify-between">
<p class="font-eina1 text-3 text-basic-darkgrey">Matchs en cours : {{ nMatchs }}</p>
<IconsBase name="calendar" class="cursor-pointer" size="small" color="darkgrey" />
</div>
<Button
:type="'default'"
:state="'active'"
class="w-full uppercase"
:styled="'fill'"
@click="emit('seeDemand', id)"
>
Voir ma demande
</Button>
</div>
<div
class="absolute right-0 flex h-4 w-16 items-center justify-end rounded-l-md bg-error px-2 drop-shadow-md"
v-if="hasNewNotifications"
>
<p class="text-nowrap font-eina1 text-1 text-basic-white">+ {{ notification }} match</p>
</div>
</div>
</div>
</template>

<script setup lang="ts">
import { OFFER_CARD_TYPE_DEFAULT, OFFER_CARD_TYPE } from '../OfferCard/OfferCard.model'
import type { OfferCardType } from '../OfferCard/OfferCard.model'
import type { IconsColor } from '../../Media/IconsBase/IconsBase.model'
const props = defineProps({
type: {
type: String as PropType<OfferCardType>,
required: true,
default: OFFER_CARD_TYPE_DEFAULT,
validator: (value: OfferCardType) => {
return Object.values(OFFER_CARD_TYPE).includes(value)
}
},
title: {
type: String as PropType<string>
},
location: {
type: String as PropType<string>
},
contractType: {
type: String as PropType<string>
},
contractDuration: {
type: String as PropType<string>
},
id: {
type: String as PropType<string>
},
desktopColor: {
type: String as PropType<IconsColor>
},
notification: {
type: Number as PropType<number>,
default: 0
},
nMatchs: {
type: Number as PropType<number>,
default: 0
}
})
const isEmpty = computed(() => props.type === OFFER_CARD_TYPE.empty)
const title = computed(() => props.title)
const location = computed(() => props.location)
const contractType = computed(() => props.contractType)
const contractDuration = computed(() => props.contractDuration)
const id = computed(() => props.id)
const desktopColor = computed(() => props.desktopColor)
const notification = computed(() => props.notification)
const hasNewNotifications = computed(() => notification.value > 0)
const nMatchs = computed(() => props.nMatchs)
const emit = defineEmits(['seeDemand', 'createDemand'])
</script>
1 change: 1 addition & 0 deletions src/components/Containment/DemandCard/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export { default } from './DemandCard.vue';
1 change: 1 addition & 0 deletions src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,3 +18,4 @@ export { default as DeleteModal } from './components/Indicators/DeleteModal'
export { default as RankingContainer } from './components/Containment/RankingContainer'
export { default as SelectField } from './components/CTA/SelectField'
export { default as OfferCard } from './components/Containment/OfferCard';
export { default as DemandCard } from './components/Containment/DemandCard';

0 comments on commit ade3241

Please sign in to comment.