chore: add SoftSkill, fix panel by adding two InfoPanel views
This commit is contained in:
parent
b8578c3eb6
commit
8d2d0d4310
@ -1,3 +1,5 @@
|
|||||||
|
en: English
|
||||||
|
es: Spanish
|
||||||
edit: Edit
|
edit: Edit
|
||||||
onedit: Edit On
|
onedit: Edit On
|
||||||
changeview: View
|
changeview: View
|
||||||
@ -85,6 +87,7 @@ cv:
|
|||||||
languages: Languages
|
languages: Languages
|
||||||
infrastructures: Infrastructures
|
infrastructures: Infrastructures
|
||||||
skills_tools: Skills & Tools
|
skills_tools: Skills & Tools
|
||||||
|
soft_skills: Soft Skills
|
||||||
skills: Skills
|
skills: Skills
|
||||||
onweb: On the Web
|
onweb: On the Web
|
||||||
mission: Mission
|
mission: Mission
|
||||||
|
@ -1,3 +1,5 @@
|
|||||||
|
en: Inglés
|
||||||
|
es: Español
|
||||||
edit: Editar
|
edit: Editar
|
||||||
onedit: Activar Edición
|
onedit: Activar Edición
|
||||||
changeview: Vista
|
changeview: Vista
|
||||||
@ -83,6 +85,7 @@ cv:
|
|||||||
languages: Idiomas
|
languages: Idiomas
|
||||||
infrastructures: Infrastructuras
|
infrastructures: Infrastructuras
|
||||||
skills_tools: Habilidades y Herramientas
|
skills_tools: Habilidades y Herramientas
|
||||||
|
soft_skills: Aptitudes
|
||||||
skills: Habilidades
|
skills: Habilidades
|
||||||
onweb: En la Web
|
onweb: En la Web
|
||||||
mission: Misión
|
mission: Misión
|
||||||
|
@ -282,7 +282,9 @@ const onNavMenu = (item: string) => {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
const onHome = () => {
|
const onHome = () => {
|
||||||
router.push(useState().APPHOME.value)
|
goTopPage()
|
||||||
|
// router.push(router.currentRoute.value.fullPath)
|
||||||
|
// router.push(useState().APPHOME.value)
|
||||||
}
|
}
|
||||||
const goTopPage = () => {
|
const goTopPage = () => {
|
||||||
const dom_body = document.getElementsByTagName('body')[0]
|
const dom_body = document.getElementsByTagName('body')[0]
|
||||||
|
@ -132,6 +132,7 @@ export interface DataCoreType {
|
|||||||
profile: ProfileType[]
|
profile: ProfileType[]
|
||||||
certifications: CertificationType[]
|
certifications: CertificationType[]
|
||||||
skills: SkillsType[]
|
skills: SkillsType[]
|
||||||
|
soft_skills: SkillsType[]
|
||||||
infra: SkillsType[]
|
infra: SkillsType[]
|
||||||
sites: SitesType[]
|
sites: SitesType[]
|
||||||
langs: LangsType[]
|
langs: LangsType[]
|
||||||
@ -241,6 +242,8 @@ export interface ShowInfoType {
|
|||||||
sites: boolean
|
sites: boolean
|
||||||
skills: boolean
|
skills: boolean
|
||||||
skills_itms: boolean
|
skills_itms: boolean
|
||||||
|
soft_skills: boolean
|
||||||
|
soft_skills_itms: boolean
|
||||||
infra: boolean
|
infra: boolean
|
||||||
certs: boolean
|
certs: boolean
|
||||||
langs: boolean
|
langs: boolean
|
||||||
|
@ -40,7 +40,14 @@
|
|||||||
id="sidebar"
|
id="sidebar"
|
||||||
class="rounded-r w-full lg:w-80 sm:max-w-sm p-8 border-l-1 border-indigo-200 bg-gradient-to-b from-indigo-300 via-indigo-200 to-indigo-100 dark:bg-gray-600 dark:from-indigo-500 dark:via-indigo-400 dark:to-indigo-800"
|
class="rounded-r w-full lg:w-80 sm:max-w-sm p-8 border-l-1 border-indigo-200 bg-gradient-to-b from-indigo-300 via-indigo-200 to-indigo-100 dark:bg-gray-600 dark:from-indigo-500 dark:via-indigo-400 dark:to-indigo-800"
|
||||||
>
|
>
|
||||||
<info-panel
|
<info-panel-main
|
||||||
|
:data="data_info.core"
|
||||||
|
:localedata="localedata"
|
||||||
|
:showinfo="show_info"
|
||||||
|
:authinfo="auth_info"
|
||||||
|
@onItem="onItem"
|
||||||
|
@onEditor="onEditor" />
|
||||||
|
<info-panel-skills
|
||||||
:data="data_info.core"
|
:data="data_info.core"
|
||||||
:localedata="localedata"
|
:localedata="localedata"
|
||||||
:showinfo="show_info"
|
:showinfo="show_info"
|
||||||
@ -49,6 +56,19 @@
|
|||||||
@onEditor="onEditor" />
|
@onEditor="onEditor" />
|
||||||
</div>
|
</div>
|
||||||
<div class="content w-full p-5">
|
<div class="content w-full p-5">
|
||||||
|
<div
|
||||||
|
v-if="!show_infopanel && data_info.core && data_info.core.title1"
|
||||||
|
id="main-info"
|
||||||
|
class="rounded-r w-full lg:w-150 sm:max-w-sm p-8 mb-5 bg-gradient-to-b from-indigo-300 via-indigo-200 to-indigo-100 dark:bg-gray-600 dark:from-indigo-500 dark:via-indigo-400 dark:to-indigo-800"
|
||||||
|
>
|
||||||
|
<info-panel-main
|
||||||
|
:data="data_info.core"
|
||||||
|
:localedata="localedata"
|
||||||
|
:showinfo="show_info"
|
||||||
|
:authinfo="auth_info"
|
||||||
|
@onItem="onItem"
|
||||||
|
@onEditor="onEditor" />
|
||||||
|
</div>
|
||||||
<div class="prose">
|
<div class="prose">
|
||||||
<h2
|
<h2
|
||||||
:class="show_info.profile ? 'section-headline' : `noprint ${auth_info.viewchange ? 'pb-11' : ''}`"
|
:class="show_info.profile ? 'section-headline' : `noprint ${auth_info.viewchange ? 'pb-11' : ''}`"
|
||||||
@ -160,42 +180,28 @@
|
|||||||
<div
|
<div
|
||||||
v-if="!show_infopanel"
|
v-if="!show_infopanel"
|
||||||
id="cv-skills"
|
id="cv-skills"
|
||||||
class="prose"
|
class="prose rounded-r w-full lg:w-150 sm:max-w-sm p-8 border-l-1 border-indigo-200 bg-gradient-to-b from-indigo-300 via-indigo-200 to-indigo-100 dark:bg-gray-600 dark:from-indigo-500 dark:via-indigo-400 dark:to-indigo-800"
|
||||||
>
|
>
|
||||||
<h2 class="section-headline">
|
|
||||||
<span v-if="show_info.skills">{{ t('cv.skills_tools', 'Skill & Tools') }}</span>
|
|
||||||
<button
|
<button
|
||||||
v-if="auth_info.viewchange"
|
class="no-print text-sm float-right icon-btn mt-2 mr-2 !outline-none text-gray-500 dark:text-gray-400"
|
||||||
class="no-print text-sm float-right icon-btn !outline-none text-gray-500 dark:text-gray-400"
|
|
||||||
@click.prevent="onSkills()"
|
|
||||||
>
|
|
||||||
<div v-if="show_info.skills" i-carbon-view-off />
|
|
||||||
<div v-else class="noprint flex-grow-0 flex -mb-5">
|
|
||||||
<div class="-mt-0.5 mr-2 line-through text-xs">{{ t('cv.skills_tools', 'Skill & Tools') }}</div>
|
|
||||||
<div i-carbon-view />
|
|
||||||
</div>
|
|
||||||
</button>
|
|
||||||
<button
|
|
||||||
v-if="show_info.skills"
|
|
||||||
class="no-print text-sm icon-btn mr-2 float-right !outline-none text-gray-500 dark:text-gray-400"
|
|
||||||
@click.prevent="onHome()"
|
@click.prevent="onHome()"
|
||||||
>
|
>
|
||||||
<div i-carbon-home />
|
<div i-carbon-home />
|
||||||
</button>
|
</button>
|
||||||
</h2>
|
<info-panel-skills
|
||||||
<div v-if="show_info.skills" class="list-none w-3/5">
|
:data="data_info.core"
|
||||||
<skills-view
|
|
||||||
:data="data_info.core.skills"
|
|
||||||
:localedata="localedata"
|
:localedata="localedata"
|
||||||
:showinfo="show_info.skills"
|
:showinfo="show_info"
|
||||||
:authinfo="show_info.auth" />
|
:authinfo="auth_info"
|
||||||
</div>
|
@onItem="onItem"
|
||||||
|
@onEditor="onEditor" />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</main>
|
</main>
|
||||||
<div
|
<div
|
||||||
v-if="show_content && cvdata.core && cvdata.core.name"
|
v-if="show_content && cvdata.core && cvdata.core.name"
|
||||||
class="mr-auto w-full lg:w-1/2 text-center text-sm py-2 pr-5 text-gray-600 border-gray-300 border-1 border-b-0 rounded-t-lg"
|
class="mr-auto w-full lg:w-1/2 text-center text-sm py-2 pr-5 text-gray-600 border-gray-300 border-1 border-b-0 rounded-t-lg"
|
||||||
|
|
||||||
>
|
>
|
||||||
<nav-menu
|
<nav-menu
|
||||||
:position="NavPosition.footer"
|
:position="NavPosition.footer"
|
||||||
@ -230,18 +236,16 @@
|
|||||||
</template>
|
</template>
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { useI18n } from 'vue-i18n'
|
import { useI18n } from 'vue-i18n'
|
||||||
const i18n = useI18n()
|
// import InfoPanel from '~/views/cv/InfoPanel.vue'
|
||||||
const { t } = useI18n()
|
import InfoPanelMain from '~/views/cv/InfoPanelMain.vue'
|
||||||
const router = useRouter()
|
import InfoPanelSkills from '~/views/cv/InfoPanelSkills.vue'
|
||||||
|
|
||||||
import InfoPanel from '~/views/cv/InfoPanel.vue'
|
|
||||||
import Profile from '~/views/cv/Profile.vue'
|
import Profile from '~/views/cv/Profile.vue'
|
||||||
import WorkExperienceView from '~/views/cv/WorkExperience.vue'
|
import WorkExperienceView from '~/views/cv/WorkExperience.vue'
|
||||||
import ProjectsView from '~/views/cv/Projects.vue'
|
import ProjectsView from '~/views/cv/Projects.vue'
|
||||||
import TeachingView from '~/views/cv/Teaching.vue'
|
import TeachingView from '~/views/cv/Teaching.vue'
|
||||||
import TalksView from '~/views/cv/Talks.vue'
|
import TalksView from '~/views/cv/Talks.vue'
|
||||||
import EducationView from '~/views/cv/Education.vue'
|
import EducationView from '~/views/cv/Education.vue'
|
||||||
import SkillsView from '~/views/cv/Skills.vue'
|
// import SkillsView from '~/views/cv/Skills.vue'
|
||||||
import OthersView from '~/views/cv/Others.vue'
|
import OthersView from '~/views/cv/Others.vue'
|
||||||
import MessageBoxView from '@/MessageBoxView.vue'
|
import MessageBoxView from '@/MessageBoxView.vue'
|
||||||
import NavMenu from '@/NavMenu.vue'
|
import NavMenu from '@/NavMenu.vue'
|
||||||
@ -255,6 +259,10 @@ import { track_action } from '~/hooks/tracking'
|
|||||||
import { MessageType} from '~/typs'
|
import { MessageType} from '~/typs'
|
||||||
import { MessageBoxType, NavPosition, InputBtnsType, ModelType, ShowInfoType } from '~/typs/cv'
|
import { MessageBoxType, NavPosition, InputBtnsType, ModelType, ShowInfoType } from '~/typs/cv'
|
||||||
|
|
||||||
|
const i18n = useI18n()
|
||||||
|
const { t } = useI18n()
|
||||||
|
const router = useRouter()
|
||||||
|
|
||||||
const prefix = 'cv'
|
const prefix = 'cv'
|
||||||
const assetsPath = useState().ASSETS_PATH
|
const assetsPath = useState().ASSETS_PATH
|
||||||
const routeKy = router.currentRoute.value.params.ky || router.currentRoute.value.query.k || ''
|
const routeKy = router.currentRoute.value.params.ky || router.currentRoute.value.query.k || ''
|
||||||
@ -474,6 +482,11 @@ const onSkills = () => {
|
|||||||
useState().showinfo.value.skills_itms = show_info.value.skills
|
useState().showinfo.value.skills_itms = show_info.value.skills
|
||||||
// !useState().showinfo.value.skills_itms
|
// !useState().showinfo.value.skills_itms
|
||||||
}
|
}
|
||||||
|
const onSoftSkills = () => {
|
||||||
|
show_info.value.soft_skills = !show_info.value.soft_skills
|
||||||
|
useState().showinfo.value.soft_skills_itms = show_info.value.soft_skills
|
||||||
|
// !useState().showinfo.value.soft_skills_itms
|
||||||
|
}
|
||||||
const onLoadModel = (model: { id: string}) => {
|
const onLoadModel = (model: { id: string}) => {
|
||||||
const url = useState().CONFURLS.value.data || ''
|
const url = useState().CONFURLS.value.data || ''
|
||||||
if (useState().models.value[model.id] && url.length > 0 ) {
|
if (useState().models.value[model.id] && url.length > 0 ) {
|
||||||
|
@ -284,6 +284,7 @@
|
|||||||
</h2>
|
</h2>
|
||||||
<skills-view
|
<skills-view
|
||||||
v-if="showinfo.skills"
|
v-if="showinfo.skills"
|
||||||
|
src="soft_skills"
|
||||||
:data="data.skills"
|
:data="data.skills"
|
||||||
:localedata="localedata"
|
:localedata="localedata"
|
||||||
:showinfo="showinfo"
|
:showinfo="showinfo"
|
||||||
@ -291,17 +292,53 @@
|
|||||||
@onItem="onSkills"
|
@onItem="onSkills"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<div v-if="showinfo.infra" class="panel-group">
|
<div
|
||||||
<h2 class="h2-title">
|
id="info-soft_skills"
|
||||||
<span>{{ t('cv.infrastructures', 'Infrastructures') }}</span>
|
:class="{ 'hidden': !showinfo.soft_skills && !authinfo.viewchange }"
|
||||||
|
class="panel-group -mt-2"
|
||||||
|
>
|
||||||
|
<h2 class="h2-title flex">
|
||||||
|
<span v-if="showinfo.soft_skills">{{ t('cv.soft_skills', 'Soft Skills') }}</span>
|
||||||
|
<div v-if="authinfo.viewchange" class="flex-grow-0 flex noprint ml-2">
|
||||||
|
<span v-if="!showinfo.soft_skills" class="w-4/5 flex-grow" />
|
||||||
<button
|
<button
|
||||||
class="no-print text-sm float-right icon-btn mt-2 !outline-none text-gray-500 dark:text-gray-400"
|
class="no-print text-base flex-grow-0 icon-btn !outline-none text-gray-500 dark:text-gray-400"
|
||||||
|
@click.prevent="onView('soft_skills')"
|
||||||
|
>
|
||||||
|
<div v-if="showinfo.soft_skills" class="flex" i-carbon-view-off />
|
||||||
|
<div v-else class="noprint flex">
|
||||||
|
<div class="mr-2 text-sm line-through">{{ t('cv.soft_skills', 'Soft Skills').replaceAll(' ','') }}</div>
|
||||||
|
<div class="flex-grow-0" i-carbon-view />
|
||||||
|
</div>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</h2>
|
||||||
|
<skills-view
|
||||||
|
v-if="showinfo.soft_skills"
|
||||||
|
src="soft_skills"
|
||||||
|
:data="data.soft_skills"
|
||||||
|
:localedata="localedata"
|
||||||
|
:showinfo="showinfo"
|
||||||
|
:authinfo="authinfo"
|
||||||
|
@onItem="onSoftSkills"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div :class="{ 'hidden': !showinfo.infra && !authinfo.viewchange }" class="panel-group">
|
||||||
|
<h2 class="h2-title flex">
|
||||||
|
<span v-if="showinfo.infra">{{ t('cv.infrastructures', 'Infrastructures') }}</span>
|
||||||
|
<button
|
||||||
|
v-if="authinfo.viewchange"
|
||||||
|
class="no-print text-sm float-right icon-btn ml-2 mt-1 !outline-none text-gray-500 dark:text-gray-400"
|
||||||
@click.prevent="onView('infra')"
|
@click.prevent="onView('infra')"
|
||||||
>
|
>
|
||||||
<div i-carbon-view-off />
|
<div v-if="showinfo.infra" i-carbon-view-off />
|
||||||
|
<div v-else class="noprint flex flex-grow-0">
|
||||||
|
<div class="-mt-0.5 mr-2 line-through">{{ t('cv.infrastructures', 'Infrastructures') }}</div>
|
||||||
|
<div class="flex-grow-0" i-carbon-view />
|
||||||
|
</div>
|
||||||
</button>
|
</button>
|
||||||
</h2>
|
</h2>
|
||||||
<div class="-ml-5 mt-2 leading-8 text-sm grid grid-flow-col grid-cols-2 grid-rows-2 gap-2">
|
<div v-if="showinfo.infra" class="-ml-5 mt-2 leading-8 text-sm grid grid-flow-col grid-cols-2 grid-rows-2 gap-2">
|
||||||
<div
|
<div
|
||||||
v-for="infra in data.infra"
|
v-for="infra in data.infra"
|
||||||
:key="infra.id"
|
:key="infra.id"
|
||||||
@ -397,7 +434,7 @@ import useState from '~/hooks/useState'
|
|||||||
import { track_action } from '~/hooks/tracking'
|
import { track_action } from '~/hooks/tracking'
|
||||||
const emit = defineEmits(['onEditor', 'onItem'])
|
const emit = defineEmits(['onEditor', 'onItem'])
|
||||||
const { t } = useI18n()
|
const { t } = useI18n()
|
||||||
const router = useRouter()
|
// const router = useRouter()
|
||||||
const props = defineProps({
|
const props = defineProps({
|
||||||
data: {
|
data: {
|
||||||
type: Object as PropType<DataCoreType>,
|
type: Object as PropType<DataCoreType>,
|
||||||
@ -433,6 +470,8 @@ const onView = (itm: string) => {
|
|||||||
showinfo.value[itm] = !showinfo.value[itm]
|
showinfo.value[itm] = !showinfo.value[itm]
|
||||||
if (itm === 'skills')
|
if (itm === 'skills')
|
||||||
useState().showinfo.value.skills = showinfo.value[itm]
|
useState().showinfo.value.skills = showinfo.value[itm]
|
||||||
|
else if (itm === 'soft_skills')
|
||||||
|
useState().showinfo.value.soft_skills = showinfo.value[itm]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
const onEditor = (info: { src: string, field: string, idx: number, data: string, ev: Event }) => {
|
const onEditor = (info: { src: string, field: string, idx: number, data: string, ev: Event }) => {
|
||||||
@ -470,6 +509,9 @@ const onItem = (src: string, idx: number) => {
|
|||||||
const onSkills = (data: { src: string, idx: number }) => {
|
const onSkills = (data: { src: string, idx: number }) => {
|
||||||
emit('onItem', { root: 'info', src: data.src, itm: props.data[data.src][data.idx], idx: data.idx })
|
emit('onItem', { root: 'info', src: data.src, itm: props.data[data.src][data.idx], idx: data.idx })
|
||||||
}
|
}
|
||||||
|
const onSoftSkills = (data: { src: string, idx: number }) => {
|
||||||
|
emit('onItem', { root: 'info', src: data.src, itm: props.data[data.src][data.idx], idx: data.idx })
|
||||||
|
}
|
||||||
const onLink = (e: any) => {
|
const onLink = (e: any) => {
|
||||||
track_action(e)
|
track_action(e)
|
||||||
}
|
}
|
||||||
|
348
src/views/cv/InfoPanelMain.vue
Normal file
348
src/views/cv/InfoPanelMain.vue
Normal file
@ -0,0 +1,348 @@
|
|||||||
|
<template>
|
||||||
|
<div class="px-1 mb-8">
|
||||||
|
<div :class="{ 'flex': showinfo.image }">
|
||||||
|
<img
|
||||||
|
v-if="showinfo.image"
|
||||||
|
:src="`${assets_path}${get_data('imgsrc')}`"
|
||||||
|
:alt="get_data('imgalt')"
|
||||||
|
class="flex-grow-0 rounded-full w-48 max-w-xs mx-auto mb-2 border-indigo-200 border-2"
|
||||||
|
/>
|
||||||
|
<button
|
||||||
|
v-if="authinfo.viewchange"
|
||||||
|
:class="showinfo.image ? 'flex-grow-0 mt-2' : 'float-right -mt-4'"
|
||||||
|
class="no-print text-sm h-6 icon-btn !outline-none text-gray-500 dark:text-gray-400"
|
||||||
|
@click.prevent="onView('image')"
|
||||||
|
>
|
||||||
|
<div i-carbon-view-off />
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
<h1
|
||||||
|
:class="showinfo.fullname ? 'text-lg' : 'text-2xl'"
|
||||||
|
class="text-center text-indigo-700 dark:text-indigo-200 font-semibold mb-2"
|
||||||
|
>{{ `${showinfo.fullname ? get_data('fullname') : get_data('name')}` }}</h1>
|
||||||
|
<h2
|
||||||
|
v-if="showinfo.title && data.title1 !== ''"
|
||||||
|
class="text-center text-sm font-light text-indigo-500 dark:text-indigo-100"
|
||||||
|
>
|
||||||
|
<tiptap-editor
|
||||||
|
v-if="authinfo.editable"
|
||||||
|
:data="data.title1"
|
||||||
|
:editable="authinfo.editable"
|
||||||
|
src="info"
|
||||||
|
field="title1"
|
||||||
|
:idx="-1"
|
||||||
|
@onEditorBlur="onEditor"
|
||||||
|
/>
|
||||||
|
<span v-else v-html="data.title1" />
|
||||||
|
</h2>
|
||||||
|
<h2
|
||||||
|
v-if="showinfo.title && data.title2 !== ''"
|
||||||
|
class="text-center text-sm font-light text-indigo-500 dark:text-indigo-100"
|
||||||
|
>
|
||||||
|
<tiptap-editor
|
||||||
|
v-if="authinfo.editable"
|
||||||
|
:data="data.title2"
|
||||||
|
:editable="authinfo.editable"
|
||||||
|
src="info"
|
||||||
|
field="title2"
|
||||||
|
:idx="-1"
|
||||||
|
@onEditorBlur="onEditor"
|
||||||
|
/>
|
||||||
|
<span v-else v-html="data.title2" />
|
||||||
|
</h2>
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
v-if="data.mission !== ''"
|
||||||
|
class="font-light text-lg px-1"
|
||||||
|
:class="{ 'mb-8': showinfo.mission && authinfo.viewchange }"
|
||||||
|
>
|
||||||
|
<h2 class="text-center h2-title dark:text-indigo-900">
|
||||||
|
<span v-if="showinfo.mission">{{ t('cv.mission', 'Mission') }}</span>
|
||||||
|
<button
|
||||||
|
v-if="authinfo.viewchange"
|
||||||
|
class="no-print text-sm float-right icon-btn mt-2 !outline-none text-gray-500 dark:text-gray-400"
|
||||||
|
@click.prevent="onView('mission')"
|
||||||
|
>
|
||||||
|
<div v-if="showinfo.mission" i-carbon-view-off />
|
||||||
|
<div v-else class="noprint flex -mt-7">
|
||||||
|
<div class="-mt-0.5 mr-2 line-through">{{ t('cv.mission', 'Mission') }}</div>
|
||||||
|
<div i-carbon-view />
|
||||||
|
</div>
|
||||||
|
</button>
|
||||||
|
</h2>
|
||||||
|
<p
|
||||||
|
v-if="showinfo.mission"
|
||||||
|
class="-ml-3 mb-2 text-xs font-semibold text-indigo-900 dark:text-indigo-200 tracking-normal"
|
||||||
|
>
|
||||||
|
<tiptap-editor
|
||||||
|
v-if="authinfo.editable"
|
||||||
|
:data="get_data('mission')"
|
||||||
|
:editable="authinfo.editable"
|
||||||
|
src="info"
|
||||||
|
field="title1"
|
||||||
|
:idx="-1"
|
||||||
|
@onEditorBlur="onEditor"
|
||||||
|
/>
|
||||||
|
<span v-else v-html="get_data('mission')" />
|
||||||
|
</p>
|
||||||
|
<ul
|
||||||
|
v-if="showinfo.mission && showinfo.mission_how && get_data('mission_how').length > 0"
|
||||||
|
class="ml-2 list-disc"
|
||||||
|
>
|
||||||
|
<li
|
||||||
|
v-for="(mitem,index) in get_data('mission_how')"
|
||||||
|
:key="index"
|
||||||
|
class="text-xs tracking-normal font-light text-indigo-800 dark:text-gray-100"
|
||||||
|
:class="{ 'noprint list-none': !mitem.auth.show }"
|
||||||
|
>
|
||||||
|
<div class="flex">
|
||||||
|
<button
|
||||||
|
v-if="authinfo.viewchange"
|
||||||
|
class="noprint flex-grow-0 icon-btn !outline-none text-gray-500 dark:text-gray-400"
|
||||||
|
@click.prevent="onItem('mission_how', index)"
|
||||||
|
>
|
||||||
|
<div v-if="mitem.auth.show" class="mr-1" i-carbon-view-off />
|
||||||
|
<div v-else class="noprint flex flex-row">
|
||||||
|
<div class="mt-0.2 mr-2 line-through text-xs">{{ index }}</div>
|
||||||
|
<div i-carbon-view />
|
||||||
|
</div>
|
||||||
|
</button>
|
||||||
|
<div v-if=" mitem.auth.show">
|
||||||
|
<tiptap-editor
|
||||||
|
v-if="authinfo.editable && mitem.auth.editable"
|
||||||
|
:data="mitem.desc"
|
||||||
|
:editable="authinfo.editable"
|
||||||
|
src="info.mission_how"
|
||||||
|
field="desc"
|
||||||
|
:idx="index"
|
||||||
|
@onEditorBlur="onEditor"
|
||||||
|
/>
|
||||||
|
<span v-else>{{ mitem.desc }}</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
<button
|
||||||
|
v-if="authinfo.viewchange"
|
||||||
|
class="no-print text-sm float-right icon-btn mt-2 !outline-none text-gray-500 dark:text-gray-400"
|
||||||
|
@click.prevent="onView('mission_how')"
|
||||||
|
>
|
||||||
|
<div v-if="showinfo.mission_how" i-carbon-view-off />
|
||||||
|
<div v-else class="noprint flex -mt-7">
|
||||||
|
<div class="-mt-0.5 mr-2 line-through">{{ t('cv.mission_how', 'Mission How') }}</div>
|
||||||
|
<div i-carbon-view />
|
||||||
|
</div>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
<div class="font-light text-lg px-1 mt-4 mb-8 panel-group">
|
||||||
|
<h2 class="h2-title">{{ t('cv.contact', 'Contact') }}</h2>
|
||||||
|
<div class="flex items-center my-3">
|
||||||
|
<img :src="`${assets_path}/images/assets/mail-outline.svg`" class="inline w-6 mr-4" alt="Mail icon" />
|
||||||
|
<a @click="onLink" :href="`mailto:${data.email}`">{{ data.email }}</a>
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
:class="{ 'hidden': !showinfo.phone && !authinfo.viewchange }"
|
||||||
|
class="flex items-center my-3"
|
||||||
|
>
|
||||||
|
<img
|
||||||
|
v-if="showinfo.phone"
|
||||||
|
:src="`${assets_path}/images/assets/call-outline.svg`"
|
||||||
|
class="inline w-6 mr-4"
|
||||||
|
alt="Phone icon"
|
||||||
|
/>
|
||||||
|
<a v-if="showinfo.phone" class="text-sm" @click="onLink" :href="`tel:${data.phone}`">
|
||||||
|
<tiptap-editor
|
||||||
|
v-if="authinfo.editable"
|
||||||
|
:data="data.phone"
|
||||||
|
:editable="authinfo.editable"
|
||||||
|
src="info"
|
||||||
|
field="phone"
|
||||||
|
:idx="-1"
|
||||||
|
@onEditorBlur="onEditor"
|
||||||
|
/>
|
||||||
|
<span v-else>{{ data.phone }}</span>
|
||||||
|
</a>
|
||||||
|
<span v-if="!showinfo.phone" class="w-4/5 flex-grow" />
|
||||||
|
<button
|
||||||
|
v-if="authinfo.viewchange"
|
||||||
|
class="no-print text-sm flex icon-btn ml-4 mt-0 !outline-none text-gray-500 dark:text-gray-400"
|
||||||
|
@click.prevent="onView('phone')"
|
||||||
|
>
|
||||||
|
<div v-if="showinfo.phone" i-carbon-view-off />
|
||||||
|
<div v-else class="noprint flex-grow-0 flex -mb-5">
|
||||||
|
<div class="-mt-0.5 mr-2 line-through">{{ t('phone', 'Phone') }}</div>
|
||||||
|
<div i-carbon-view />
|
||||||
|
</div>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
:class="{ 'hidden': !showinfo.address && !authinfo.viewchange }"
|
||||||
|
class="flex flex-row my-5"
|
||||||
|
>
|
||||||
|
<div>
|
||||||
|
<img
|
||||||
|
v-if="showinfo.address"
|
||||||
|
:src="`${assets_path}/images/assets/home-outline.svg`"
|
||||||
|
class="flex-grow-0 w-6 pb-1 mr-4"
|
||||||
|
alt="House icon"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div v-if="showinfo.address" class="text-xs">
|
||||||
|
<p>{{ data.address }}</p>
|
||||||
|
<p class="text-xs font-semibold">{{ get_data('city') }}</p>
|
||||||
|
<p>{{ data.postalcode }} {{ get_data('state') }}</p>
|
||||||
|
<p class="text-sm">{{ get_data('country')}}</p>
|
||||||
|
</div>
|
||||||
|
<span v-if="!showinfo.address" class="w-4/5 flex-grow" />
|
||||||
|
<button
|
||||||
|
v-if="authinfo.viewchange"
|
||||||
|
class="no-print text-sm flex icon-btn ml-4 mt-0 !outline-none text-gray-500 dark:text-gray-400"
|
||||||
|
@click.prevent="onView('address')"
|
||||||
|
>
|
||||||
|
<div v-if="showinfo.address" i-carbon-view-off />
|
||||||
|
<div v-else class="noprint flex-grow-0 flex -mb-5">
|
||||||
|
<div class="-mt-0.5 mr-2 line-through">{{ t('address', 'Adress') }}</div>
|
||||||
|
<div i-carbon-view />
|
||||||
|
</div>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div v-if="showinfo.birthdate || showinfo.status" class="panel-group">
|
||||||
|
<h2 class="h2-title">{{ t('cv.personal', 'Personal') }}</h2>
|
||||||
|
<div v-if="showinfo.birthdate" class="flex items-center my-3">
|
||||||
|
<img :src="`${assets_path}/images/assets/egg-outline.svg`" class="inline w-6 mr-4" alt="Egg Icon" />
|
||||||
|
<span class="text-sm">{{ data.birthdate }}</span>
|
||||||
|
</div>
|
||||||
|
<div v-if="data.status && showinfo.status" class="flex items-center my-3">
|
||||||
|
<img :src="`${assets_path}/images/assets/people-outline.svg`" class="inline w-6 mr-4" alt="Two Persons Icon" />
|
||||||
|
<span>{{ t(`cv.${data.status.toLowerCase()}`, data.status) }}</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div :class="{ 'hidden': !showinfo.sites && !authinfo.viewchange }" class="panel-group -mt-4">
|
||||||
|
<h2 class="h2-title flex">
|
||||||
|
<span v-if="showinfo.sites">{{ t('cv.onweb', 'On the Web') }}</span>
|
||||||
|
<span v-else class="w-5 flex-grow" />
|
||||||
|
<button
|
||||||
|
v-if="authinfo.viewchange"
|
||||||
|
class="no-print text-sm flex icon-btn ml-2 mt-1.5 !outline-none text-gray-500 dark:text-gray-400"
|
||||||
|
@click.prevent="onView('sites')"
|
||||||
|
>
|
||||||
|
<div v-if="showinfo.sites" i-carbon-view-off />
|
||||||
|
<div v-else class="noprint flex-grow-0 flex -mb-5">
|
||||||
|
<div class="-mt-0.5 mr-2 line-through text-xs">{{ t('cv.onweb', 'On the Web') }}</div>
|
||||||
|
<div i-carbon-view />
|
||||||
|
</div>
|
||||||
|
</button>
|
||||||
|
</h2>
|
||||||
|
<div
|
||||||
|
v-if="showinfo.sites"
|
||||||
|
v-for="(site,index) in data.sites"
|
||||||
|
:key="site.id"
|
||||||
|
class="flex items-center y-3"
|
||||||
|
:class="{ 'noprint': !site.auth.show }"
|
||||||
|
>
|
||||||
|
<div v-if="authinfo.viewchange" class="flex-grow-0 flex noprint">
|
||||||
|
<span v-if="!showinfo.sites" class="w-4/5 flex-grow" />
|
||||||
|
<button
|
||||||
|
class="noprint text-xs mr-1 flex-grow-0 icon-btn !outline-none text-gray-500 dark:text-gray-400"
|
||||||
|
@click.prevent="onItem('sites', index)"
|
||||||
|
>
|
||||||
|
<div v-if="site.auth.show" i-carbon-view-off />
|
||||||
|
<div v-else class="noprint flex">
|
||||||
|
<div class="-mt-0.5 mr-2 line-through">{{ index }}</div>
|
||||||
|
<div i-carbon-view />
|
||||||
|
</div>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
<div v-if="site.auth.show" class="flex-grow flex mb-2 text-sm">
|
||||||
|
<img :src="`${assets_path}${site.img}`" class="flex-grow-0 inline w-6 mr-4" :alt="site.alt" />
|
||||||
|
<span class="mt-0.5 mr-2 flex-grow-0 text-gray-500 dark:text-gray-700" style="font-size: 80%">{{ site.title }}</span>
|
||||||
|
<a @click="onLink" :href="site.link" target="_blank" rel="noopener noreferrer" class="flex-grow">
|
||||||
|
<span class="flex-grow" style="font-size: 80%">{{ site.sub }}</span>
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
<script setup lang="ts">
|
||||||
|
import { PropType } from 'vue'
|
||||||
|
import { AuthInfoType, DataCoreType, ShowInfoType,DataLangsType } from '~/typs/cv'
|
||||||
|
import TiptapEditor from '~/components/TiptapEditor.vue'
|
||||||
|
import useState from '~/hooks/useState'
|
||||||
|
import { track_action } from '~/hooks/tracking'
|
||||||
|
const emit = defineEmits(['onEditor', 'onItem'])
|
||||||
|
const { t } = useI18n()
|
||||||
|
// const router = useRouter()
|
||||||
|
const props = defineProps({
|
||||||
|
data: {
|
||||||
|
type: Object as PropType<DataCoreType>,
|
||||||
|
default: {},
|
||||||
|
required: true,
|
||||||
|
},
|
||||||
|
localedata: {
|
||||||
|
type: Object as PropType<DataLangsType>,
|
||||||
|
default: {},
|
||||||
|
required: true,
|
||||||
|
},
|
||||||
|
showinfo: {
|
||||||
|
type: Object as PropType<ShowInfoType>,
|
||||||
|
default: {},
|
||||||
|
required: true,
|
||||||
|
},
|
||||||
|
authinfo: {
|
||||||
|
type: Object as PropType<AuthInfoType>,
|
||||||
|
default: { editable: false, viewchange: false },
|
||||||
|
required: true,
|
||||||
|
},
|
||||||
|
})
|
||||||
|
const assets_path = useState().ASSETS_PATH.value
|
||||||
|
const showinfo = ref(props.showinfo as ShowInfoType)
|
||||||
|
const authinfo = computed(() => {
|
||||||
|
return showinfo.value.auth ? showinfo.value.auth : props.authinfo
|
||||||
|
})
|
||||||
|
const get_data = (itm: string) => {
|
||||||
|
return props.localedata.value && props.localedata.value.corelang && props.localedata.value.corelang[itm] ? props.localedata.value.corelang[itm] : props.data[itm]
|
||||||
|
}
|
||||||
|
const onView = (itm: string) => {
|
||||||
|
if (typeof showinfo.value[itm] !== 'undefined') {
|
||||||
|
showinfo.value[itm] = !showinfo.value[itm]
|
||||||
|
// if (itm === 'skills')
|
||||||
|
// useState().showinfo.value.skills = showinfo.value[itm]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
const onEditor = (info: { src: string, field: string, idx: number, data: string, ev: Event }) => {
|
||||||
|
let has_changed = false
|
||||||
|
let arr_data: string[] = []
|
||||||
|
let data = ''
|
||||||
|
const arr_src = info.field.split('.')
|
||||||
|
switch (arr_src[0]) {
|
||||||
|
case 'mission_how':
|
||||||
|
const field = arr_src.length > 0 ? arr_src[1] : info.field
|
||||||
|
arr_data = info.data.replace('<ul>', '').replace('</ul>', '').replace(/<li.+?>/g, '').split('</li>')
|
||||||
|
data = get_data(arr_src[0])[info.idx][field]
|
||||||
|
break
|
||||||
|
default:
|
||||||
|
has_changed = info.data.replace('<p>', '').replace('</p>', '') !== get_data(info.field)
|
||||||
|
}
|
||||||
|
if (arr_data.length > 0) {
|
||||||
|
arr_data = arr_data.filter(it => it !== '')
|
||||||
|
arr_data.forEach((it, idx) => {
|
||||||
|
if (!has_changed && it.replace('<p>', '').replace('</p>', '') !== data ) {
|
||||||
|
has_changed = true
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
if (has_changed) {
|
||||||
|
emit('onEditor', { ...info, arr_data })
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// const onEditor = (info: { src: string, idx: number, data: string, ev: Event }) => {
|
||||||
|
// emit('onEditor', { ...info })
|
||||||
|
// }
|
||||||
|
const onItem = (src: string, idx: number) => {
|
||||||
|
emit('onItem', { root: 'info', src, itm: props.data[src][idx], idx })
|
||||||
|
}
|
||||||
|
const onLink = (e: any) => {
|
||||||
|
track_action(e)
|
||||||
|
}
|
||||||
|
</script>
|
227
src/views/cv/InfoPanelSkills.vue
Normal file
227
src/views/cv/InfoPanelSkills.vue
Normal file
@ -0,0 +1,227 @@
|
|||||||
|
<template>
|
||||||
|
<div
|
||||||
|
id="info-skills"
|
||||||
|
:class="{ 'hidden': !showinfo.skills && !authinfo.viewchange }"
|
||||||
|
class="panel-group -mt-2"
|
||||||
|
>
|
||||||
|
<h2 class="h2-title flex">
|
||||||
|
<span v-if="showinfo.skills">{{ t('cv.skills_tools', 'Skill & Tools') }}</span>
|
||||||
|
<div v-if="authinfo.viewchange" class="flex-grow-0 flex noprint ml-2">
|
||||||
|
<span v-if="!showinfo.skills" class="w-4/5 flex-grow" />
|
||||||
|
<button
|
||||||
|
class="no-print text-base flex-grow-0 icon-btn !outline-none text-gray-500 dark:text-gray-400"
|
||||||
|
@click.prevent="onView('skills')"
|
||||||
|
>
|
||||||
|
<div v-if="showinfo.skills" class="flex" i-carbon-view-off />
|
||||||
|
<div v-else class="noprint flex">
|
||||||
|
<div class="mr-2 text-sm line-through">{{ t('cv.skills_tools', 'Skill & Tools').replaceAll(' ','') }}</div>
|
||||||
|
<div class="flex-grow-0" i-carbon-view />
|
||||||
|
</div>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</h2>
|
||||||
|
<skills-view
|
||||||
|
v-if="showinfo.skills"
|
||||||
|
src="soft_skills"
|
||||||
|
:data="data.skills"
|
||||||
|
:localedata="localedata"
|
||||||
|
:showinfo="showinfo"
|
||||||
|
:authinfo="authinfo"
|
||||||
|
@onItem="onSkills"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
id="info-soft_skills"
|
||||||
|
:class="{ 'hidden': !showinfo.soft_skills && !authinfo.viewchange }"
|
||||||
|
class="panel-group -mt-2"
|
||||||
|
>
|
||||||
|
<h2 class="h2-title flex">
|
||||||
|
<span v-if="showinfo.soft_skills">{{ t('cv.soft_skills', 'Soft Skills') }}</span>
|
||||||
|
<div v-if="authinfo.viewchange" class="flex-grow-0 flex noprint ml-2">
|
||||||
|
<span v-if="!showinfo.soft_skills" class="w-4/5 flex-grow" />
|
||||||
|
<button
|
||||||
|
class="no-print text-base flex-grow-0 icon-btn !outline-none text-gray-500 dark:text-gray-400"
|
||||||
|
@click.prevent="onView('soft_skills')"
|
||||||
|
>
|
||||||
|
<div v-if="showinfo.soft_skills" class="flex" i-carbon-view-off />
|
||||||
|
<div v-else class="noprint flex">
|
||||||
|
<div class="mr-2 text-sm line-through">{{ t('cv.soft_skills', 'Soft Skills').replaceAll(' ','') }}</div>
|
||||||
|
<div class="flex-grow-0" i-carbon-view />
|
||||||
|
</div>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</h2>
|
||||||
|
<skills-view
|
||||||
|
v-if="showinfo.soft_skills"
|
||||||
|
src="soft_skills"
|
||||||
|
:data="data.soft_skills"
|
||||||
|
:localedata="localedata"
|
||||||
|
:showinfo="showinfo"
|
||||||
|
:authinfo="authinfo"
|
||||||
|
@onItem="onSoftSkills"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div :class="{ 'hidden': !showinfo.infra && !authinfo.viewchange }" class="panel-group">
|
||||||
|
<h2 class="h2-title flex">
|
||||||
|
<span v-if="showinfo.infra">{{ t('cv.infrastructures', 'Infrastructures') }}</span>
|
||||||
|
<button
|
||||||
|
v-if="authinfo.viewchange"
|
||||||
|
class="no-print text-sm float-right icon-btn ml-2 mt-1 !outline-none text-gray-500 dark:text-gray-400"
|
||||||
|
@click.prevent="onView('infra')"
|
||||||
|
>
|
||||||
|
<div v-if="showinfo.infra" i-carbon-view-off />
|
||||||
|
<div v-else class="noprint flex flex-grow-0">
|
||||||
|
<div class="-mt-0.5 mr-2 line-through">{{ t('cv.infrastructures', 'Infrastructures') }}</div>
|
||||||
|
<div class="flex-grow-0" i-carbon-view />
|
||||||
|
</div>
|
||||||
|
</button>
|
||||||
|
</h2>
|
||||||
|
<div v-if="showinfo.infra" class="-ml-5 mt-2 leading-8 text-sm grid grid-flow-col grid-cols-2 grid-rows-2 gap-2">
|
||||||
|
<div
|
||||||
|
v-for="infra in data.infra"
|
||||||
|
:key="infra.id"
|
||||||
|
class="border-1 border-indigo-400 rounded-xl bg-gray-300 w-25 px-3 ml-2"
|
||||||
|
>{{ infra.title }}</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div :class="{ 'hidden': !showinfo.certs && !authinfo.viewchange }" class="panel-group -mt-4">
|
||||||
|
<h2 class="h2-title flex">
|
||||||
|
<span v-if="showinfo.certs">{{ t('cv.certifications', 'Certifications') }}</span>
|
||||||
|
<button
|
||||||
|
v-if="authinfo.viewchange"
|
||||||
|
class="no-print text-sm float-right icon-btn ml-2 mt-1 !outline-none text-gray-500 dark:text-gray-400"
|
||||||
|
@click.prevent="onView('certs')"
|
||||||
|
>
|
||||||
|
<div v-if="showinfo.certs" i-carbon-view-off />
|
||||||
|
<div v-else class="noprint flex flex-grow-0">
|
||||||
|
<div class="-mt-0.5 mr-2 line-through">{{ t('cv.certifications', 'Certifications') }}</div>
|
||||||
|
<div class="flex-grow-0" i-carbon-view />
|
||||||
|
</div>
|
||||||
|
</button>
|
||||||
|
</h2>
|
||||||
|
<div
|
||||||
|
v-if="showinfo.certs"
|
||||||
|
v-for="(cert,index) in get_data('certifications')"
|
||||||
|
:key="cert.id"
|
||||||
|
class="border-b-1 border-gray-400 mb-3 pb-2 flex"
|
||||||
|
>
|
||||||
|
<div v-if="cert.auth.show" class="flex-grow">
|
||||||
|
<h3 class="font-semibold text-sm">{{ cert.title }}</h3>
|
||||||
|
<div class="font-light text-xs">{{ cert.date }}</div>
|
||||||
|
<div class="font-light text-xs flex flex-col">
|
||||||
|
<div v-if="cert.href && cert.href !== ''" class="flex-grow">
|
||||||
|
<small class="hidden">{{ t('link', 'Link') }}: </small>
|
||||||
|
<a @click="onLink" :href="cert.href">{{ cert.link }}</a>
|
||||||
|
</div>
|
||||||
|
<div v-if="cert.certid && cert.certid !== ''" class="flex-grow-0">
|
||||||
|
<small>{{ t('id', 'Id') }}: {{ cert.certid }}</small>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<p v-if="cert.author && cert.author !== ''" class="font-light text-xs mb-2">
|
||||||
|
<small class="hidden">{{ t('from', 'From') }}: </small>
|
||||||
|
<span class="font-semibold">
|
||||||
|
<i>{{ cert.author }}</i>
|
||||||
|
</span>
|
||||||
|
</p>
|
||||||
|
<p v-else class="mb-2" />
|
||||||
|
</div>
|
||||||
|
<div class="flex flex-grow-0">
|
||||||
|
<button
|
||||||
|
v-if="authinfo.viewchange"
|
||||||
|
class="noprint flex-grow-0 icon-btn !outline-none text-gray-500 dark:text-gray-400"
|
||||||
|
@click.prevent="onItem('certifications', index)"
|
||||||
|
>
|
||||||
|
<div v-if="cert.auth.show" class="mr-1" i-carbon-view-off />
|
||||||
|
<div v-else class="noprint flex flex-row">
|
||||||
|
<div class="mt-0.2 mr-2 line-through text-xs">{{ index }}</div>
|
||||||
|
<div i-carbon-view />
|
||||||
|
</div>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div :class="{ 'hidden': !showinfo.langs && !authinfo.viewchange }" class="panel-group -mt-4">
|
||||||
|
<h2 class="h2-title">
|
||||||
|
<span v-if="showinfo.langs">{{ t('cv.languages', 'Languages') }}</span>
|
||||||
|
<span v-else class="w-5 flex-grow" />
|
||||||
|
<button
|
||||||
|
v-if="authinfo.viewchange"
|
||||||
|
class="no-print text-sm float-right icon-btn mt-2 !outline-none text-gray-500 dark:text-gray-400"
|
||||||
|
@click.prevent="onView('langs')"
|
||||||
|
>
|
||||||
|
<div v-if="showinfo.langs" i-carbon-view-off />
|
||||||
|
<div v-else class="noprint flex-grow-0 flex -mb-5">
|
||||||
|
<div class="-mt-0.5 mr-2 line-through text-xs">{{ t('cv.languages', 'Languages') }}</div>
|
||||||
|
<div i-carbon-view />
|
||||||
|
</div>
|
||||||
|
</button>
|
||||||
|
</h2>
|
||||||
|
<div v-if='showinfo.langs'
|
||||||
|
v-for="lang in data.langs" :key="lang.id" class="flex flex-row">
|
||||||
|
<div class="font-semibold flex-grow">{{ t(`lang.${lang.title.toLowerCase()}`, lang.title) }}</div>
|
||||||
|
<div class="flex-grow-0 text-sm mt-1">{{ t(`lang.${lang.mode.toLowerCase()}`, lang.mode) }}</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
<script setup lang="ts">
|
||||||
|
import { PropType } from 'vue'
|
||||||
|
import { AuthInfoType, DataCoreType, ShowInfoType,DataLangsType } from '~/typs/cv'
|
||||||
|
import SkillsView from '~/views/cv/Skills.vue'
|
||||||
|
import useState from '~/hooks/useState'
|
||||||
|
import { track_action } from '~/hooks/tracking'
|
||||||
|
const emit = defineEmits(['onEditor', 'onItem'])
|
||||||
|
const { t } = useI18n()
|
||||||
|
// const router = useRouter()
|
||||||
|
const props = defineProps({
|
||||||
|
data: {
|
||||||
|
type: Object as PropType<DataCoreType>,
|
||||||
|
default: {},
|
||||||
|
required: true,
|
||||||
|
},
|
||||||
|
localedata: {
|
||||||
|
type: Object as PropType<DataLangsType>,
|
||||||
|
default: {},
|
||||||
|
required: true,
|
||||||
|
},
|
||||||
|
showinfo: {
|
||||||
|
type: Object as PropType<ShowInfoType>,
|
||||||
|
default: {},
|
||||||
|
required: true,
|
||||||
|
},
|
||||||
|
authinfo: {
|
||||||
|
type: Object as PropType<AuthInfoType>,
|
||||||
|
default: { editable: false, viewchange: false },
|
||||||
|
required: true,
|
||||||
|
},
|
||||||
|
})
|
||||||
|
// const assets_path = useState().ASSETS_PATH.value
|
||||||
|
const showinfo = ref(props.showinfo as ShowInfoType)
|
||||||
|
const authinfo = computed(() => {
|
||||||
|
return showinfo.value.auth ? showinfo.value.auth : props.authinfo
|
||||||
|
})
|
||||||
|
const get_data = (itm: string) => {
|
||||||
|
return props.localedata.value && props.localedata.value.corelang && props.localedata.value.corelang[itm] ? props.localedata.value.corelang[itm] : props.data[itm]
|
||||||
|
}
|
||||||
|
const onView = (itm: string) => {
|
||||||
|
if (typeof showinfo.value[itm] !== 'undefined') {
|
||||||
|
showinfo.value[itm] = !showinfo.value[itm]
|
||||||
|
if (itm === 'skills')
|
||||||
|
useState().showinfo.value.skills = showinfo.value[itm]
|
||||||
|
else if (itm === 'soft_skills')
|
||||||
|
useState().showinfo.value.soft_skills = showinfo.value[itm]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const onItem = (src: string, idx: number) => {
|
||||||
|
emit('onItem', { root: 'info', src, itm: props.data[src][idx], idx })
|
||||||
|
}
|
||||||
|
const onSkills = (data: { src: string, idx: number }) => {
|
||||||
|
emit('onItem', { root: 'info', src: data.src, itm: props.data[data.src][data.idx], idx: data.idx })
|
||||||
|
}
|
||||||
|
const onSoftSkills = (data: { src: string, idx: number }) => {
|
||||||
|
emit('onItem', { root: 'info', src: data.src, itm: props.data[data.src][data.idx], idx: data.idx })
|
||||||
|
}
|
||||||
|
const onLink = (e: any) => {
|
||||||
|
track_action(e)
|
||||||
|
}
|
||||||
|
</script>
|
@ -3,7 +3,7 @@
|
|||||||
<li v-for="(skill,index) in get_data('skills')" :key="skill.id" :id="`cv-${skill.id}`" class="flex">
|
<li v-for="(skill,index) in get_data('skills')" :key="skill.id" :id="`cv-${skill.id}`" class="flex">
|
||||||
<div class="flex-grow">
|
<div class="flex-grow">
|
||||||
<label :for="skill.id" class="flex flex-row">
|
<label :for="skill.id" class="flex flex-row">
|
||||||
<span v-if="skill.auth.show" class="flex-grow text-base">{{ skill.title }}</span>
|
<span v-if="skill.auth.show" class="flex-grow text-sm">{{ skill.title }}</span>
|
||||||
<span v-if="skill.auth.show" class="mt-1 text-sm flex-grow-0">{{ skill.value }}%</span>
|
<span v-if="skill.auth.show" class="mt-1 text-sm flex-grow-0">{{ skill.value }}%</span>
|
||||||
</label>
|
</label>
|
||||||
<progress
|
<progress
|
||||||
@ -35,6 +35,11 @@
|
|||||||
import { PropType } from 'vue'
|
import { PropType } from 'vue'
|
||||||
import { AuthInfoType, SkillsType, DataLangsType } from '~/typs/cv'
|
import { AuthInfoType, SkillsType, DataLangsType } from '~/typs/cv'
|
||||||
const props = defineProps({
|
const props = defineProps({
|
||||||
|
src: {
|
||||||
|
type: String,
|
||||||
|
default: 'skill',
|
||||||
|
required: true,
|
||||||
|
},
|
||||||
data: {
|
data: {
|
||||||
type: Array as PropType<SkillsType[]>,
|
type: Array as PropType<SkillsType[]>,
|
||||||
default: [],
|
default: [],
|
||||||
@ -56,7 +61,7 @@ const get_data = (itm: string) => {
|
|||||||
return props.localedata.value && props.localedata.value.corelang && props.localedata.value.corelang[itm] ? props.localedata.value.corelang[itm] : props.data
|
return props.localedata.value && props.localedata.value.corelang && props.localedata.value.corelang[itm] ? props.localedata.value.corelang[itm] : props.data
|
||||||
}
|
}
|
||||||
const onItem = (idx: number) => {
|
const onItem = (idx: number) => {
|
||||||
emit('onItem', { src: 'skills', itm: props.data[idx], idx })
|
emit('onItem', { src: props.src, itm: props.data[idx], idx })
|
||||||
}
|
}
|
||||||
// const onItem = (itm: string) => {
|
// const onItem = (itm: string) => {
|
||||||
// const dom_id = document.getElementById(`cv-${itm}`)
|
// const dom_id = document.getElementById(`cv-${itm}`)
|
||||||
|
Loading…
Reference in New Issue
Block a user