Skip to content

Commit

Permalink
feat(vue): Complete actor page
Browse files Browse the repository at this point in the history
  • Loading branch information
0live committed Oct 3, 2024
1 parent fc0e318 commit d088534
Show file tree
Hide file tree
Showing 11 changed files with 181 additions and 44 deletions.
1 change: 1 addition & 0 deletions symfony/src/Entity/Actor.php
Original file line number Diff line number Diff line change
Expand Up @@ -152,6 +152,7 @@ class Actor
* @var Collection<int, Project>
*/
#[ORM\OneToMany(targetEntity: Project::class, mappedBy: 'actor')]
#[Groups([self::ACTOR_READ_ITEM, self::ACTOR_WRITE])]
private Collection $projects;

#[ORM\Column(length: 255, nullable: true)]
Expand Down
14 changes: 8 additions & 6 deletions symfony/src/Entity/Project.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,16 +2,17 @@

namespace App\Entity;

use ApiPlatform\Metadata\ApiResource;
use App\Entity\Trait\TimestampableEntity;
use App\Enum\AdministrativeScopes;
use App\Enum\Status;
use App\Repository\ProjectRepository;
use Doctrine\Common\Collections\ArrayCollection;
use Doctrine\Common\Collections\Collection;
use Doctrine\DBAL\Types\Types;
use Doctrine\ORM\Mapping as ORM;
use App\Enum\AdministrativeScopes;
use ApiPlatform\Metadata\ApiResource;
use App\Repository\ProjectRepository;
use App\Entity\Trait\TimestampableEntity;
use Doctrine\Common\Collections\Collection;
use Jsor\Doctrine\PostGIS\Types\PostGISType;
use Doctrine\Common\Collections\ArrayCollection;
use Symfony\Component\Serializer\Attribute\Groups;

#[ORM\Entity(repositoryClass: ProjectRepository::class)]
#[ApiResource]
Expand All @@ -25,6 +26,7 @@ class Project
private ?int $id = null;

#[ORM\Column(length: 255)]
#[Groups([Actor::ACTOR_READ_ITEM])]
private ?string $title = null;

#[ORM\Column(length: 255)]
Expand Down
2 changes: 1 addition & 1 deletion symfony/src/Entity/User.php
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ class User implements UserInterface, PasswordAuthenticatedUserInterface
#[ORM\Id]
#[ORM\GeneratedValue]
#[ORM\Column]
#[Groups([self::GROUP_READ, self::GROUP_GETME])]
#[Groups([self::GROUP_READ, self::GROUP_GETME, Actor::ACTOR_READ_ITEM])]
private ?int $id = null;

#[ORM\Column(length: 255)]
Expand Down
10 changes: 10 additions & 0 deletions vue/src/assets/translations/fr/actors.json
Original file line number Diff line number Diff line change
Expand Up @@ -22,5 +22,15 @@
"admin": {
"sort": "Trier par"
}
},
"actorPage": {
"description": "Activité",
"projects": "Projets",
"data": "Données",
"resources": "Ressources",
"services": "Services",
"images": "En images",
"adminScope": "Zone d'intervention",
"contact": "Point de contact"
}
}
3 changes: 2 additions & 1 deletion vue/src/assets/translations/fr/common.json
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,7 @@
},
"content": {
"website": "Visiter le site internet",
"mail": "Contacter par mail"
"mail": "Contacter par mail",
"edit": "Modifier"
}
}
41 changes: 41 additions & 0 deletions vue/src/components/generic-components/banners/SectionBanner.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
<template>
<div class="SectionBanner">
<div class="SectionBanner__HalfCircle"></div>
<div class="SectionBanner__Title">{{ text }}</div>
</div>
</template>
<script setup lang="ts">
defineProps({
text: String
})
</script>
<style scoped lang="scss">
.SectionBanner {
display: flex;
align-items: center;
flex-wrap: wrap;
width: 100%;
min-height: 42px;
position: relative;
&__HalfCircle {
width: 21px;
height: 42px;
background-color: rgb(var(--v-theme-main-yellow));
border-radius: 0 21px 21px 0;
position: absolute;
left: 0;
top: 50%;
transform: translateY(-50%);
}
&__Title {
margin-left: 50px;
font-size: 30px;
font-weight: 700;
color: rgb(var(--v-theme-main-blue));
line-height: 45px;
}
}
</style>
36 changes: 31 additions & 5 deletions vue/src/components/generic-components/content/ContentBanner.vue
Original file line number Diff line number Diff line change
@@ -1,10 +1,18 @@
<template>
<PageBanner :text="content.name" :subtitle="content.acronym" class="mt-10" />
<div class="ActorPage__shareBar mt-3">
<ShareButton />
<div class="ContentPage__shareBar mt-3">
<v-btn
prepend-icon="mdi-pencil"
color="main-red"
v-if="isEditable && editFunction"
@click="editFunction(content.id)"
>
{{ $t("content.edit") }}
</v-btn>
<ShareButton class="ml-2"/>
<LikeButton />
</div>
<div class="ActorPage__contact mt-4">
<div class="ContentPage__contact mt-4">
<BasicCard icon="mdi-open-in-new">
<a :href="content.website" target="_blank" class="ml-2">{{ $t('content.website') }}</a>
</BasicCard>
Expand All @@ -25,6 +33,24 @@ import BasicCard from '@/components/generic-components/global/BasicCard.vue';
import type { Actor } from '@/models/interfaces/Actor';
defineProps<{
content: Actor
content: Actor,
isEditable: boolean,
editFunction?: (id: string) => void,
}>()
</script>
</script>

<style scoped lang="scss">
.ContentPage {
&__shareBar {
display: flex;
align-items: center;
margin-left: 50px;
}
&__contact {
width: 100%;
display: grid;
grid-template-columns: repeat(auto-fill, minmax(200px, 1fr));
gap: 10px;
}
}
</style>
14 changes: 14 additions & 0 deletions vue/src/components/generic-components/content/ContentDivider.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
<template>
<div class="ContentDivider"></div>
</template>

<script setup lang="ts">
</script>

<style scoped>
.ContentDivider{
width: 100%;
height: 0.3em;
background-color: rgb(var(--v-theme-light-yellow));
}
</style>
23 changes: 23 additions & 0 deletions vue/src/components/generic-components/content/ThematicChip.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
<template>
<div class="ThematicChip">{{ text }}</div>
</template>

<script setup lang="ts">
defineProps({
text: String
})</script>

<style scoped lang="scss">
.ThematicChip {
background-color: rgb(var(--v-theme-light-yellow));
color: rgb(var(--v-theme-main-blue));
font-size: 14px;
font-weight: 400;
display: inline-block;
padding: 8px 16px;
border-radius: 16px;
text-align: center;
white-space: nowrap;
border: 1px solid white;
}
</style>
75 changes: 46 additions & 29 deletions vue/src/components/views-components/actors/ActorProfile.vue
Original file line number Diff line number Diff line change
@@ -1,28 +1,39 @@
<template>
<!-- Edit right to setup -->
<v-btn @click="editActor(actorsStore.selectedActor?.id as string)" color="main-red">{{ $t("actors.form.editTitle")}}</v-btn>
<!-- Edit right to setup -->
<template v-if="actor">
<div class="ActorPage">
<div class="ActorPage__leftBlock">
<PageBanner :text="actor.name" :subtitle="actor.acronym" class="mt-10" />
<div class="ActorPage__shareBar mt-3">
<ShareButton />
<LikeButton />
<ContentBanner :content="actor" :isEditable="isEditable" :editFunction="editActor"/>
<SectionTitle :text="$t('actorPage.description')" class="mt-12"/>
<ContentDivider class="mt-4"/>
<p class="mt-6 mr-8">{{actor.description}}</p>
<SectionBanner :text="$t('actorPage.projects')" class="mt-12"/>
{{ actor.projects }}
<SectionBanner :text="$t('actorPage.data')" class="mt-12"/>
<SectionBanner :text="$t('actorPage.resources')" class="mt-12"/>
<SectionBanner :text="$t('actorPage.services')" class="mt-12"/>
<SectionBanner :text="$t('actorPage.images')" class="mt-12"/>
</div>
<div class="ActorPage__rightBlock">
<img :src="actor.logo" alt="" v-if="!appStore.mobile" class="mt-4">
<div class="mt-6">
<ThematicChip v-for="thematic in actor.thematics" :text="thematic" class="mt-1"/>
</div>
<SectionTitle :text="$t('actorPage.adminScope')" class="mt-12"/>
<ContentDivider class="mt-4"/>
{{ actor.administrativeScopes }}
<div class="ActorPage__contentCard">
<v-icon icon="mdi-map-marker-outline" color="main-black" />
<div class="ml-1">
<p class="font-weight-bold">{{ actor.officeName }}</p>
<p>{{ actor.officeAdress}}</p>
</div>
</div>
<div class="ActorPage__contact mt-4">
<BasicCard icon="mdi-open-in-new">
<a :href="actor.website" target="_blank" class="ml-2">{{ $t('content.website') }}</a>
</BasicCard>
<BasicCard icon="mdi-email-plus-outline">
<a :href="`mailto:${actor.email}`" class="ml-2">{{ $t('content.mail') }}</a>
</BasicCard>
<BasicCard icon="mdi-phone">
<span class="ml-2">{{actor.phone }}</span>
</BasicCard>
<div class="ActorPage__contentCard flex-column mt-8">
<SectionTitle :text="$t('actorPage.contact')"/>
<span class="font-weight-bold mt-3">{{ actor.contactName }}</span>
<span>{{ actor.contactPosition }}</span>
</div>
</div>
<div class="ActorPage__rightBlock">Coucou</div>
</div>
</template>

Expand All @@ -32,11 +43,16 @@ import type { Actor } from '@/models/interfaces/Actor';
import { useActorsStore } from '@/stores/actorsStore';
import { computed, onMounted, watchEffect } from 'vue';
import { useRoute } from 'vue-router';
import PageBanner from '@/components/generic-components/banners/PageBanner.vue';
import LikeButton from '@/components/generic-components/global/LikeButton.vue';
import ShareButton from '@/components/generic-components/global/ShareButton.vue';
import BasicCard from '@/components/generic-components/global/BasicCard.vue';
import ContentBanner from '@/components/generic-components/content/ContentBanner.vue';
import SectionTitle from '@/components/generic-components/text-elements/SectionTitle.vue';
import ContentDivider from '@/components/generic-components/content/ContentDivider.vue';
import SectionBanner from '@/components/generic-components/banners/SectionBanner.vue';
import ThematicChip from '@/components/generic-components/content/ThematicChip.vue';
import { useApplicationStore } from '@/stores/applicationStore';
import { useUserStore } from '@/stores/userStore';
const appStore = useApplicationStore();
const userStore = useUserStore();
const actorsStore = useActorsStore();
const actor = computed(() => actorsStore.selectedActor)
// Handle page openened directly by url
Expand All @@ -46,12 +62,17 @@ onMounted(() => {
if (actorsStore.dataLoaded) {
if (actorsStore.selectedActor === null) {
const actor: Actor | undefined = actorsStore.actors.find(actor => actor.name === route.params.name);
console.log(actor)
actorsStore.setSelectedActor(actor?.id as string);
}
}
});
})
const isEditable = computed(() => {
return userStore.userIsAdmin() || actor.value?.createdBy.id === userStore.currentUser?.id
})
function editActor(id: string) {
actorsStore.activateActorEdition(id)
}
Expand All @@ -77,15 +98,11 @@ function editActor(id: string) {
flex-wrap: wrap;
}
.ActorPage {
&__shareBar {
&__contentCard {
display: flex;
margin-left: 50px;
}
&__contact {
padding: 1.5em;
width: 100%;
display: grid;
grid-template-columns: repeat(auto-fill, minmax(200px, 1fr));
gap: 10px;
background-color: rgb(var(--v-theme-light-yellow));
}
}
</style>
6 changes: 4 additions & 2 deletions vue/src/models/interfaces/Actor.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,9 @@ import type { ContentImageFromUserFile, ContentImageFromUrl } from "./ContentIma

export interface Actor {
id: string;
createdBy: User["id"];
createdBy: {
id: User["id"]
};
isValidated: boolean;
name: string;
acronym: string;
Expand All @@ -19,7 +21,7 @@ export interface Actor {
description: string;
administrativeScopes: AdministrativesScopes[];
officeName: string;
officeAddress: string;
officeAdress: string;
officeLocation: [number, number]; //To add later in SF Entity
contactName: string;
contactPosition: string;
Expand Down

0 comments on commit d088534

Please sign in to comment.