Env swap #21
|
@ -77,6 +77,30 @@ export interface Profile {
|
||||||
skills : Skill[]
|
skills : Skill[]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** The data required to update a profile */
|
||||||
|
export interface ProfileForm {
|
||||||
|
/** Whether the citizen to whom this profile belongs is actively seeking employment */
|
||||||
|
isSeekingEmployment : boolean
|
||||||
|
/** Whether this profile should appear in the public search */
|
||||||
|
isPublic : boolean
|
||||||
|
/** The user's real name */
|
||||||
|
realName : string
|
||||||
|
/** The ID of the continent on which the citizen is located */
|
||||||
|
continentId : string
|
||||||
|
/** The area within that continent where the citizen is located */
|
||||||
|
region : string
|
||||||
|
/** If the citizen is available for remote work */
|
||||||
|
remoteWork : boolean
|
||||||
|
/** If the citizen is seeking full-time employment */
|
||||||
|
fullTime : boolean
|
||||||
|
/** The user's professional biography */
|
||||||
|
biography : string
|
||||||
|
/** The user's past experience */
|
||||||
|
experience : string | undefined
|
||||||
|
/** The skills for the user */
|
||||||
|
skills : Skill[]
|
||||||
|
}
|
||||||
|
|
||||||
/** The data required to show a viewable profile */
|
/** The data required to show a viewable profile */
|
||||||
export interface ProfileForView {
|
export interface ProfileForView {
|
||||||
/** The profile itself */
|
/** The profile itself */
|
||||||
|
|
45
src/JobsJobsJobs/App/src/components/profile/SkillEdit.vue
Normal file
45
src/JobsJobsJobs/App/src/components/profile/SkillEdit.vue
Normal file
|
@ -0,0 +1,45 @@
|
||||||
|
<template>
|
||||||
|
<v-row>
|
||||||
|
<v-col cols="2" md="1">
|
||||||
|
<br>
|
||||||
|
<v-btn color="danger" variant="outlined" title="Delete" @click="$emit('remove')">−</v-btn>
|
||||||
|
</v-col>
|
||||||
|
<v-col cols="10" md="6">
|
||||||
|
<label :for="`skillDesc${skill.id}`" class="jjj-label">Skill</label>
|
||||||
|
<input type="text" :id="`skillDesc${skill.id}`" maxlength="100"
|
||||||
|
placeholder="A skill (language, design technique, process, etc.)"
|
||||||
|
:value="skill.description" @input="updateValue('description', $event.target.value)">
|
||||||
|
</v-col>
|
||||||
|
<v-col cols="12" md="5">
|
||||||
|
<label :for="`skillNotes${skill.id}`" class="jjj-label">Notes</label>
|
||||||
|
<input type="text" :id="`skillNotes${skill.id}`" maxlength="100"
|
||||||
|
placeholder="A further description of the skill (100 characters max)"
|
||||||
|
:value="skill.notes" @input="updateValue('notes', $event.target.value)">
|
||||||
|
</v-col>
|
||||||
|
</v-row>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script lang="ts">
|
||||||
|
import { defineComponent } from 'vue'
|
||||||
|
import { Skill } from '@/api'
|
||||||
|
|
||||||
|
export default defineComponent({
|
||||||
|
name: 'ProfileSkillEdit',
|
||||||
|
props: {
|
||||||
|
modelValue: {
|
||||||
|
type: Object,
|
||||||
|
required: true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
emits: ['remove', 'update:modelValue'],
|
||||||
|
setup (props, { emit }) {
|
||||||
|
/** The skill being edited */
|
||||||
|
const skill : Skill = { ...props.modelValue as Skill }
|
||||||
|
|
||||||
|
return {
|
||||||
|
skill,
|
||||||
|
updateValue: (key : string, value : string) => emit('update:modelValue', { ...skill, [key]: value })
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
</script>
|
|
@ -8,7 +8,7 @@
|
||||||
<v-row>
|
<v-row>
|
||||||
<v-col cols="12" sm="10" md="8" lg="6">
|
<v-col cols="12" sm="10" md="8" lg="6">
|
||||||
<label for="realName">Real Name</label>
|
<label for="realName">Real Name</label>
|
||||||
<input type="text" id="realName" v-model="realName" maxlength="255"
|
<input type="text" id="realName" v-model="profile.realName" maxlength="255"
|
||||||
placeholder="Leave blank to use your NAS display name">
|
placeholder="Leave blank to use your NAS display name">
|
||||||
</v-col>
|
</v-col>
|
||||||
</v-row>
|
</v-row>
|
||||||
|
@ -60,12 +60,10 @@
|
||||||
<hr>
|
<hr>
|
||||||
<h4>
|
<h4>
|
||||||
Skills
|
Skills
|
||||||
<button type="button" class="btn btn-outline-primary" @onclick="AddNewSkill">Add a Skill</button>
|
<v-btn color="primary" variant="outlined" @click="addSkill">Add a Skill</v-btn>
|
||||||
</h4>
|
</h4>
|
||||||
@foreach (var skill in ProfileForm.Skills)
|
<profile-skill-edit v-for="(skill, idx) in profile.skills" :key="skill.id" v-model="profile.skills[idx]"
|
||||||
{
|
@remove="removeSkill(skill.id)" />
|
||||||
[SkillEdit Skill=@skill OnRemove=@RemoveSkill /]
|
|
||||||
}
|
|
||||||
<hr>
|
<hr>
|
||||||
<h4>Experience</h4>
|
<h4>Experience</h4>
|
||||||
<p>
|
<p>
|
||||||
|
@ -111,16 +109,19 @@
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import { computed, defineComponent, Ref, ref } from 'vue'
|
import { computed, defineComponent, Ref, ref } from 'vue'
|
||||||
import { useRouter } from 'vue-router'
|
import { useRouter } from 'vue-router'
|
||||||
import api, { LogOnSuccess, Profile } from '@/api'
|
import api, { Citizen, LogOnSuccess, Profile, ProfileForm } from '@/api'
|
||||||
|
import { useStore } from '@/store'
|
||||||
|
|
||||||
import MarkdownEditor from '@/components/MarkdownEditor.vue'
|
import MarkdownEditor from '@/components/MarkdownEditor.vue'
|
||||||
import LoadData from '@/components/LoadData.vue'
|
import LoadData from '@/components/LoadData.vue'
|
||||||
import { useStore } from '@/store'
|
import ProfileSkillEdit from '@/components/profile/SkillEdit.vue'
|
||||||
|
|
||||||
export default defineComponent({
|
export default defineComponent({
|
||||||
name: 'EditProfile',
|
name: 'EditProfile',
|
||||||
components: {
|
components: {
|
||||||
LoadData,
|
LoadData,
|
||||||
MarkdownEditor
|
MarkdownEditor,
|
||||||
|
ProfileSkillEdit
|
||||||
},
|
},
|
||||||
setup () {
|
setup () {
|
||||||
const store = useStore()
|
const store = useStore()
|
||||||
|
@ -132,11 +133,23 @@ export default defineComponent({
|
||||||
/** Whether this is a new profile */
|
/** Whether this is a new profile */
|
||||||
const isNew = ref(false)
|
const isNew = ref(false)
|
||||||
|
|
||||||
/** The user's current profile */
|
/** The starting values for a new employment profile */
|
||||||
const profile : Ref<Profile | undefined> = ref(undefined)
|
const newProfile : Profile = {
|
||||||
|
id: user.citizenId,
|
||||||
|
seekingEmployment: false,
|
||||||
|
isPublic: false,
|
||||||
|
continentId: '',
|
||||||
|
region: '',
|
||||||
|
remoteWork: false,
|
||||||
|
fullTime: false,
|
||||||
|
biography: '',
|
||||||
|
lastUpdatedOn: '',
|
||||||
|
experience: undefined,
|
||||||
|
skills: []
|
||||||
|
}
|
||||||
|
|
||||||
/** The user's real name */
|
/** The user's current profile (plus a few items, adapted for editing) */
|
||||||
const realName : Ref<string | undefined> = ref(undefined)
|
const profile : Ref<ProfileForm | undefined> = ref(undefined)
|
||||||
|
|
||||||
/** Retrieve the user's profile and their real name */
|
/** Retrieve the user's profile and their real name */
|
||||||
const retrieveData = async (errors : string[]) => {
|
const retrieveData = async (errors : string[]) => {
|
||||||
|
@ -146,16 +159,43 @@ export default defineComponent({
|
||||||
errors.push(profileResult)
|
errors.push(profileResult)
|
||||||
} else if (typeof profileResult === 'undefined') {
|
} else if (typeof profileResult === 'undefined') {
|
||||||
isNew.value = true
|
isNew.value = true
|
||||||
} else {
|
|
||||||
profile.value = profileResult
|
|
||||||
// console.info(JSON.stringify(profile))
|
|
||||||
}
|
}
|
||||||
const nameResult = await api.citizen.retrieve(user.citizenId, user)
|
const nameResult = await api.citizen.retrieve(user.citizenId, user)
|
||||||
if (typeof nameResult === 'string') {
|
if (typeof nameResult === 'string') {
|
||||||
errors.push(nameResult)
|
errors.push(nameResult)
|
||||||
} else if (typeof nameResult !== 'undefined') {
|
|
||||||
realName.value = nameResult.realName || ''
|
|
||||||
}
|
}
|
||||||
|
if (errors.length > 0) return
|
||||||
|
const p = isNew.value ? newProfile : profileResult as Profile
|
||||||
|
profile.value = {
|
||||||
|
isSeekingEmployment: p.seekingEmployment,
|
||||||
|
isPublic: p.isPublic,
|
||||||
|
continentId: p.continentId,
|
||||||
|
region: p.region,
|
||||||
|
remoteWork: p.remoteWork,
|
||||||
|
fullTime: p.fullTime,
|
||||||
|
biography: p.biography,
|
||||||
|
experience: p.experience,
|
||||||
|
skills: p.skills,
|
||||||
|
realName: typeof nameResult !== 'undefined' ? (nameResult as Citizen).realName || '' : ''
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/** The ID for new skills */
|
||||||
|
let newSkillId = 0
|
||||||
|
|
||||||
|
/** Add a skill to the profile */
|
||||||
|
const addSkill = () => {
|
||||||
|
const form = profile.value as ProfileForm
|
||||||
|
form.skills.push({ id: `new${newSkillId}`, description: '', notes: undefined })
|
||||||
|
newSkillId++
|
||||||
|
profile.value = form
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Remove the given skill from the profile */
|
||||||
|
const removeSkill = (skillId : string) => {
|
||||||
|
const form = profile.value as ProfileForm
|
||||||
|
form.skills = form.skills.filter(s => s.id !== skillId)
|
||||||
|
profile.value = form
|
||||||
}
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
|
@ -163,8 +203,9 @@ export default defineComponent({
|
||||||
user,
|
user,
|
||||||
isNew,
|
isNew,
|
||||||
profile,
|
profile,
|
||||||
realName,
|
|
||||||
continents: computed(() => store.state.continents),
|
continents: computed(() => store.state.continents),
|
||||||
|
addSkill,
|
||||||
|
removeSkill,
|
||||||
viewProfile: () => router.push(`/profile/view/${user.citizenId}`)
|
viewProfile: () => router.push(`/profile/view/${user.citizenId}`)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue
Block a user