Skip to content

Commit ccfd1f5

Browse files
committed
feat: mentorship response form
1 parent 1a7daf9 commit ccfd1f5

File tree

4 files changed

+193
-0
lines changed

4 files changed

+193
-0
lines changed

src/locales/en.json

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1148,6 +1148,20 @@
11481148
"link": "https://en.unesco.org/sustainabledevelopmentgoals"
11491149
}
11501150
},
1151+
"mentorship": {
1152+
"respond": {
1153+
"options": {
1154+
"accept": "Accept",
1155+
"decline": "Decline",
1156+
"need-infos": "Request more information"
1157+
},
1158+
"your-response": "Your response",
1159+
"add-comment": "Add a comment",
1160+
"comment-notice": "This comment will be sent by email to the mentee.",
1161+
"comment-placeholder": "Write here.",
1162+
"title": "Become a mentor"
1163+
}
1164+
},
11511165
"onboarding": {
11521166
"step": "step",
11531167
"title": "What is Projects?"

src/locales/fr.json

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1144,6 +1144,20 @@
11441144
"link": "https://fr.unesco.org/sdgs"
11451145
}
11461146
},
1147+
"mentorship": {
1148+
"respond": {
1149+
"options": {
1150+
"accept": "Accepter",
1151+
"decline": "Refuser",
1152+
"need-infos": "Demander des précisions"
1153+
},
1154+
"your-response": "Votre réponse",
1155+
"add-comment": "Ajouter un commentaire",
1156+
"comment-notice": "Ce commentaire sera envoyé par mail au mentoré.",
1157+
"comment-placeholder": "Écrire ici.",
1158+
"title": "Devenir mentor"
1159+
}
1160+
},
11471161
"onboarding": {
11481162
"step": "étape",
11491163
"title": "Qu'est-ce que Projects ?"
Lines changed: 159 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,159 @@
1+
<template>
2+
<div class="mentroship-respond-page page-section-narrow page-top" v-if="!isLoading">
3+
<h1 class="page-title">{{ $t('mentorship.respond.title') }}</h1>
4+
5+
<div class="form-field">
6+
<h3 class="label">{{ $t('mentorship.respond.your-response') }} *</h3>
7+
8+
<div class="answer-options">
9+
<RadioButton
10+
v-for="answerOption in answerOptions"
11+
:key="answerOption.value"
12+
v-model="form.answer"
13+
:label="answerOption.label"
14+
:value="answerOption.value"
15+
radio-group="answer"
16+
as-button
17+
/>
18+
</div>
19+
</div>
20+
21+
<div class="form-field">
22+
<h3 class="label">{{ $t('mentorship.respond.add-comment') }}</h3>
23+
<p class="notice">{{ $t('mentorship.respond.comment-notice') }}</p>
24+
<TextInput
25+
v-model="form.comment"
26+
label=""
27+
:placeholder="$t('mentorship.respond.comment-placeholder')"
28+
input-type="textarea"
29+
rows="10"
30+
/>
31+
</div>
32+
33+
<div class="form-field submit-field">
34+
<LpiButton
35+
:disabled="!form.answer || isSaving"
36+
:label="$t('common.send')"
37+
:btn-icon="isSaving ? 'LoaderSimple' : null"
38+
class="submit-btn"
39+
@click="submit"
40+
data-test="membership-respond-button"
41+
/>
42+
</div>
43+
</div>
44+
</template>
45+
<script>
46+
import TextInput from '@/components/base/form/TextInput.vue'
47+
import RadioButton from '@/components/base/form/RadioButton.vue'
48+
import LpiButton from '@/components/base/button/LpiButton.vue'
49+
import useUsersStore from '@/stores/useUsers.ts'
50+
export default {
51+
name: 'MentorshipRespondPage',
52+
53+
components: { TextInput, RadioButton, LpiButton },
54+
55+
setup() {
56+
const usersStore = useUsersStore()
57+
return { usersStore }
58+
},
59+
60+
props: {
61+
token: {
62+
type: String,
63+
required: true,
64+
},
65+
},
66+
67+
data() {
68+
return {
69+
form: {
70+
answer: null,
71+
comment: '',
72+
},
73+
isSaving: false,
74+
isLoading: false,
75+
}
76+
},
77+
78+
computed: {
79+
answerOptions() {
80+
return [
81+
{ label: this.$t('mentorship.respond.options.accept'), value: 'accept' },
82+
{ label: this.$t('mentorship.respond.options.decline'), value: 'decline' },
83+
{ label: this.$t('mentorship.respond.options.need-infos'), value: 'need-infos' },
84+
]
85+
},
86+
isConnected() {
87+
return this.usersStore.isConnected
88+
},
89+
},
90+
91+
async mounted() {
92+
this.isLoading = true
93+
if (!this.isConnected || !this.token) {
94+
this.display404()
95+
}
96+
97+
try {
98+
// TODO: Call API to get the mentorship request
99+
await new Promise((resolve) => setTimeout(resolve, 1000))
100+
if (this.token === '404') {
101+
throw new Error('Not found')
102+
}
103+
this.isLoading = false
104+
} catch (error) {
105+
console.error(error)
106+
this.display404()
107+
}
108+
},
109+
110+
methods: {
111+
async submit() {
112+
this.isSaving = true
113+
try {
114+
// TODO: Call API to save the response
115+
await new Promise((resolve) => setTimeout(resolve, 1000))
116+
} catch (error) {
117+
console.error(error)
118+
} finally {
119+
this.isSaving = false
120+
}
121+
},
122+
123+
display404() {
124+
this.$router.replace({
125+
name: 'page404',
126+
params: { pathMatch: this.$route.path.substring(1).split('/') },
127+
})
128+
},
129+
},
130+
}
131+
</script>
132+
<style lang="scss" scoped>
133+
.page-title {
134+
margin-bottom: $space-3xl;
135+
}
136+
137+
.answer-options {
138+
display: flex;
139+
gap: $space-unit;
140+
}
141+
142+
.form-field {
143+
margin-top: $space-unit;
144+
145+
.label {
146+
margin-bottom: $space-m;
147+
}
148+
}
149+
150+
.notice {
151+
margin-bottom: $space-m;
152+
}
153+
154+
.submit-field {
155+
display: flex;
156+
justify-content: center;
157+
margin-bottom: $space-2xl;
158+
}
159+
</style>

src/router/routes.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -146,6 +146,12 @@ const routes: Array<RouteRecordRaw> = [
146146
},
147147
],
148148
},
149+
{
150+
path: '/mentorship/respond/:token',
151+
name: 'MentorhipRespondPage',
152+
props: true,
153+
component: () => import('../pages/MentorshipRespondPage/MentorshipRespondPage.vue'),
154+
},
149155
{
150156
path: '/profile/edit',
151157
name: 'ProfileEdit',

0 commit comments

Comments
 (0)