diff --git a/src/components/FormModel.vue b/src/components/FormModel.vue
index 060a18bcc..6f91035ff 100644
--- a/src/components/FormModel.vue
+++ b/src/components/FormModel.vue
@@ -227,6 +227,7 @@ watch(formUrl, async () => {
 defineExpose({
     save,
     isLoading,
+    hasChanges,
 });
 </script>
 <template>
diff --git a/src/css/app.scss b/src/css/app.scss
index cac161d05..b36036df4 100644
--- a/src/css/app.scss
+++ b/src/css/app.scss
@@ -82,6 +82,11 @@ select:-webkit-autofill {
     color: $white;
 }
 
+.card-width {
+    max-width: 800px;
+    width: 100%;
+}
+
 .vn-card {
     background-color: var(--vn-section-color);
     color: var(--vn-text-color);
diff --git a/src/i18n/en/index.js b/src/i18n/en/index.js
index 685591c2d..9b6ec06e3 100644
--- a/src/i18n/en/index.js
+++ b/src/i18n/en/index.js
@@ -851,12 +851,14 @@ export default {
         pageTitles: {
             workers: 'Workers',
             list: 'List',
-            basicData: 'Basic data',
             summary: 'Summary',
-            notifications: 'Notifications',
             workerCreate: 'New worker',
             department: 'Department',
+            basicData: 'Basic data',
+            notes: 'Notes',
             pda: 'PDA',
+            notifications: 'Notifications',
+            pbx: 'Private Branch Exchange',
             log: 'Log',
         },
         list: {
diff --git a/src/i18n/es/index.js b/src/i18n/es/index.js
index abcc2a1bd..31e571565 100644
--- a/src/i18n/es/index.js
+++ b/src/i18n/es/index.js
@@ -850,12 +850,14 @@ export default {
         pageTitles: {
             workers: 'Trabajadores',
             list: 'Listado',
-            basicData: 'Datos básicos',
             summary: 'Resumen',
-            notifications: 'Notificaciones',
             workerCreate: 'Nuevo trabajador',
             department: 'Departamentos',
+            basicData: 'Datos básicos',
+            notes: 'Notas',
             pda: 'PDA',
+            notifications: 'Notificaciones',
+            pbx: 'Centralita',
             log: 'Historial',
         },
         list: {
diff --git a/src/pages/Worker/Card/WorkerBasicData.vue b/src/pages/Worker/Card/WorkerBasicData.vue
new file mode 100644
index 000000000..c59f4281d
--- /dev/null
+++ b/src/pages/Worker/Card/WorkerBasicData.vue
@@ -0,0 +1,168 @@
+<script setup>
+import { ref } from 'vue';
+import { useRoute } from 'vue-router';
+import { useI18n } from 'vue-i18n';
+
+import FetchData from 'components/FetchData.vue';
+import FormModel from 'src/components/FormModel.vue';
+import VnRow from 'components/ui/VnRow.vue';
+import VnInput from 'src/components/common/VnInput.vue';
+import VnSelectFilter from 'src/components/common/VnSelectFilter.vue';
+
+const route = useRoute();
+const { t } = useI18n();
+
+const workersOptions = ref([]);
+const countriesOptions = ref([]);
+const educationLevelsOptions = ref([]);
+
+const workerFilter = {
+    include: [
+        {
+            relation: 'user',
+            scope: {
+                fields: ['name', 'emailVerified'],
+                include: { relation: 'emailUser', scope: { fields: ['email'] } },
+            },
+        },
+        { relation: 'sip', scope: { fields: ['extension', 'secret'] } },
+        { relation: 'department', scope: { include: { relation: 'department' } } },
+    ],
+};
+const workersFilter = {
+    fields: ['id', 'nickname'],
+    order: 'nickname ASC',
+    limit: 30,
+};
+const countriesFilter = {
+    fields: ['id', 'country', 'code'],
+    order: 'country ASC',
+    limit: 30,
+};
+const educationLevelsFilter = { fields: ['id', 'name'], order: 'name ASC', limit: 30 };
+
+const maritalStatus = [
+    { code: 'M', name: t('Married') },
+    { code: 'S', name: t('Single') },
+];
+</script>
+
+<template>
+    <FetchData
+        :filter="workersFilter"
+        @on-fetch="(data) => (workersOptions = data)"
+        auto-load
+        url="Workers/search"
+    />
+    <FetchData
+        :filter="countriesFilter"
+        @on-fetch="(data) => (countriesOptions = data)"
+        auto-load
+        url="Countries"
+    />
+    <FetchData
+        :filter="educationLevelsFilter"
+        @on-fetch="(data) => (educationLevelsOptions = data)"
+        auto-load
+        url="EducationLevels"
+    />
+
+    <FormModel
+        :filter="workerFilter"
+        :url="`Workers/${route.params.id}`"
+        auto-load
+        model="Worker"
+    >
+        <template #form="{ data }">
+            <VnRow class="row q-gutter-md q-mb-md">
+                <VnInput :label="t('Name')" clearable v-model="data.firstName" />
+                <VnInput :label="t('Last name')" clearable v-model="data.lastName" />
+            </VnRow>
+
+            <VnRow class="row q-gutter-md q-mb-md">
+                <VnInput v-model="data.phone" :label="t('Business phone')" clearable />
+                <VnInput
+                    v-model="data.mobileExtension"
+                    :label="t('Mobile extension')"
+                    clearable
+                />
+            </VnRow>
+
+            <VnRow class="row q-gutter-md q-mb-md">
+                <VnSelectFilter
+                    :label="t('Boss')"
+                    :options="workersOptions"
+                    hide-selected
+                    option-label="nickname"
+                    option-value="id"
+                    v-model="data.bossFk"
+                >
+                    <template #option="scope">
+                        <QItem v-bind="scope.itemProps">
+                            <QItemSection>
+                                <QItemLabel>{{ scope.opt?.name }}</QItemLabel>
+                                <QItemLabel caption>
+                                    {{ scope.opt?.nickname }},
+                                    {{ scope.opt?.code }}
+                                </QItemLabel>
+                            </QItemSection>
+                        </QItem>
+                    </template>
+                </VnSelectFilter>
+                <VnSelectFilter
+                    :label="t('Marital status')"
+                    :options="maritalStatus"
+                    hide-selected
+                    option-label="name"
+                    option-value="code"
+                    v-model="data.maritalStatus"
+                />
+            </VnRow>
+
+            <VnRow class="row q-gutter-md q-mb-md">
+                <VnSelectFilter
+                    :label="t('Origin country')"
+                    :options="countriesOptions"
+                    hide-selected
+                    option-label="country"
+                    option-value="id"
+                    v-model="data.originCountryFk"
+                />
+                <VnSelectFilter
+                    :label="t('Education level')"
+                    :options="educationLevelsOptions"
+                    hide-selected
+                    option-label="name"
+                    option-value="id"
+                    v-model="data.educationLevelFk"
+                />
+            </VnRow>
+
+            <VnRow class="row q-gutter-md q-mb-md">
+                <VnInput v-model="data.SSN" :label="t('SSN')" clearable />
+                <VnInput
+                    v-model="data.locker"
+                    type="number"
+                    :label="t('Locker')"
+                    clearable
+                />
+            </VnRow>
+        </template>
+    </FormModel>
+</template>
+
+<i18n>
+es:
+    Name: Nombre
+    Last name: Apellidos
+    Business phone: Teléfono de empresa
+    Mobile extension: Extensión móvil
+    Boss: Jefe
+    Marital status: Estado civil
+    Married: Casado/a
+    Single: Soltero/a
+    Origin country: País origen
+    Education level: Nivel educación
+    SSN: NSS
+    Locker: Taquilla
+</i18n>
diff --git a/src/pages/Worker/Card/WorkerDescriptor.vue b/src/pages/Worker/Card/WorkerDescriptor.vue
index 5144b3bfa..a20ad5546 100644
--- a/src/pages/Worker/Card/WorkerDescriptor.vue
+++ b/src/pages/Worker/Card/WorkerDescriptor.vue
@@ -1,5 +1,5 @@
 <script setup>
-import { computed, ref } from 'vue';
+import { computed, ref, watch } from 'vue';
 import { useRoute } from 'vue-router';
 import { useI18n } from 'vue-i18n';
 import { useSession } from 'src/composables/useSession';
@@ -7,6 +7,7 @@ import CardDescriptor from 'src/components/ui/CardDescriptor.vue';
 import VnLv from 'src/components/ui/VnLv.vue';
 import VnLinkPhone from 'src/components/ui/VnLinkPhone.vue';
 import useCardDescription from 'src/composables/useCardDescription';
+import { useState } from 'src/composables/useState';
 
 const $props = defineProps({
     id: {
@@ -23,6 +24,7 @@ const $props = defineProps({
 const route = useRoute();
 const { t } = useI18n();
 const { getTokenMultimedia } = useSession();
+const state = useState();
 
 const entityId = computed(() => {
     return $props.id || route.params.id;
@@ -53,7 +55,18 @@ const filter = {
     ],
 };
 
-const sip = computed(() => worker.value?.sip && worker.value.sip.extension);
+const sip = ref(null);
+
+watch(
+    () => [worker.value?.sip?.extension, state.get('extension')],
+    ([newWorkerSip, newStateExtension], [oldWorkerSip, oldStateExtension]) => {
+        if (newStateExtension !== oldStateExtension || sip.value === oldStateExtension) {
+            sip.value = newStateExtension;
+        } else if (newWorkerSip !== oldWorkerSip && sip.value !== newStateExtension) {
+            sip.value = newWorkerSip;
+        }
+    }
+);
 
 function getWorkerAvatar() {
     const token = getTokenMultimedia();
diff --git a/src/pages/Worker/Card/WorkerNotes.vue b/src/pages/Worker/Card/WorkerNotes.vue
new file mode 100644
index 000000000..6c74aefa0
--- /dev/null
+++ b/src/pages/Worker/Card/WorkerNotes.vue
@@ -0,0 +1,38 @@
+<script setup>
+import { useRoute } from 'vue-router';
+
+import VnNotes from 'src/components/ui/VnNotes.vue';
+
+const route = useRoute();
+
+const filter = {
+    order: 'created DESC',
+    where: { workerFk: route.params.id },
+    include: {
+        relation: 'worker',
+        scope: {
+            fields: ['id', 'firstName', 'lastName'],
+            include: {
+                relation: 'user',
+                scope: {
+                    fields: ['id', 'nickname'],
+                },
+            },
+        },
+    },
+};
+
+const body = {
+    workerFk: route.params.id,
+};
+</script>
+
+<template>
+    <VnNotes
+        style="overflow-y: auto"
+        :add-note="{ type: Boolean, default: true }"
+        url="WorkerObservations"
+        :filter="filter"
+        :body="body"
+    />
+</template>
diff --git a/src/pages/Worker/Card/WorkerPBX.vue b/src/pages/Worker/Card/WorkerPBX.vue
new file mode 100644
index 000000000..681194061
--- /dev/null
+++ b/src/pages/Worker/Card/WorkerPBX.vue
@@ -0,0 +1,70 @@
+<script setup>
+import { watch, ref } from 'vue';
+import { useI18n } from 'vue-i18n';
+import { useRoute } from 'vue-router';
+
+import { useState } from 'src/composables/useState';
+
+import FormModel from 'src/components/FormModel.vue';
+import VnRow from 'components/ui/VnRow.vue';
+import VnInput from 'src/components/common/VnInput.vue';
+
+const { t } = useI18n();
+const state = useState();
+const route = useRoute();
+const workerPBXForm = ref();
+const extension = ref(null);
+
+const filter = {
+    include: [
+        {
+            relation: 'sip',
+        },
+    ],
+};
+
+watch(
+    () => route.params.id,
+    () => state.set('extension', null)
+);
+
+const onFetch = (data) => {
+    state.set('extension', data?.sip?.extension);
+    extension.value = state.get('extension');
+};
+
+const updateModelValue = (data) => {
+    state.set('extension', data);
+    workerPBXForm.value.hasChanges = true;
+};
+</script>
+
+<template>
+    <FormModel
+        ref="workerPBXForm"
+        :filter="filter"
+        :url="`Workers/${route.params.id}`"
+        url-update="Sips"
+        auto-load
+        :mapper="
+            () => ({
+                userFk: +route.params.id,
+                extension,
+            })
+        "
+        model="DeviceProductionUser"
+        @on-fetch="onFetch"
+    >
+        <template #form="{}">
+            <VnRow class="row q-gutter-md q-mb-md">
+                <div class="col">
+                    <VnInput
+                        :label="t('worker.summary.sipExtension')"
+                        v-model="extension"
+                        @update:model-value="updateModelValue"
+                    />
+                </div>
+            </VnRow>
+        </template>
+    </FormModel>
+</template>
diff --git a/src/router/modules/worker.js b/src/router/modules/worker.js
index 448aab79c..7ea82d71d 100644
--- a/src/router/modules/worker.js
+++ b/src/router/modules/worker.js
@@ -12,7 +12,14 @@ export default {
     redirect: { name: 'WorkerMain' },
     menus: {
         main: ['WorkerList', 'WorkerDepartment'],
-        card: ['WorkerNotificationsManager', 'WorkerPda', 'WorkerLog'],
+        card: [
+            'WorkerBasicData',
+            'WorkerNotes',
+            'WorkerPda',
+            'WorkerNotificationsManager',
+            'WorkerPBX',
+            'WorkerLog',
+        ],
         departmentCard: ['BasicData'],
     },
     children: [
@@ -66,6 +73,52 @@ export default {
                     },
                     component: () => import('src/pages/Worker/Card/WorkerSummary.vue'),
                 },
+                {
+                    path: 'basic-data',
+                    name: 'WorkerBasicData',
+                    meta: {
+                        title: 'basicData',
+                        icon: 'vn:settings',
+                    },
+                    component: () => import('src/pages/Worker/Card/WorkerBasicData.vue'),
+                },
+                {
+                    path: 'notes',
+                    name: 'NotesCard',
+                    redirect: { name: 'WorkerNotes' },
+                    children: [
+                        {
+                            path: '',
+                            name: 'WorkerNotes',
+                            meta: {
+                                title: 'notes',
+                                icon: 'vn:notes',
+                            },
+                            component: () =>
+                                import('src/pages/Worker/Card/WorkerNotes.vue'),
+                        },
+                        {
+                            path: 'create',
+                            name: 'WorkerNoteCreate',
+                            meta: {
+                                title: 'note-create',
+                            },
+                            component: () =>
+                                import(
+                                    'src/pages/Worker/components/WorkerNoteCreate.vue'
+                                ),
+                        },
+                    ],
+                },
+                {
+                    name: 'WorkerPda',
+                    path: 'pda',
+                    meta: {
+                        title: 'pda',
+                        icon: 'phone_android',
+                    },
+                    component: () => import('src/pages/Worker/Card/WorkerPda.vue'),
+                },
                 {
                     name: 'WorkerNotificationsManager',
                     path: 'notifications',
@@ -77,13 +130,13 @@ export default {
                         import('src/pages/Worker/Card/WorkerNotificationsManager.vue'),
                 },
                 {
-                    name: 'WorkerPda',
-                    path: 'pda',
+                    path: 'pbx',
+                    name: 'WorkerPBX',
                     meta: {
-                        title: 'pda',
-                        icon: 'phone_android',
+                        title: 'pbx',
+                        icon: 'vn:pbx',
                     },
-                    component: () => import('src/pages/Worker/Card/WorkerPda.vue'),
+                    component: () => import('src/pages/Worker/Card/WorkerPBX.vue'),
                 },
                 {
                     name: 'WorkerLog',