|
7 | 7 | CheckCircle2, XCircle, AlertTriangle, ArrowUpDown, ListFilter, |
8 | 8 | Maximize2, Minimize2, Brain, Loader2, |
9 | 9 | } from 'lucide-vue-next' |
10 | | -import { z } from 'zod' |
11 | 10 | import { usePreviewReadOnly } from '~/composables/usePreviewReadOnly' |
12 | 11 | import { APPLICATION_STATUS_TRANSITIONS, JOB_STATUS_TRANSITIONS, INTERVIEW_STATUS_TRANSITIONS } from '~~/shared/status-transitions' |
13 | 12 |
|
@@ -934,82 +933,6 @@ async function handleJobTransition(newStatus: string) { |
934 | 933 | } |
935 | 934 | } |
936 | 935 |
|
937 | | -// ───────────────────────────────────────────── |
938 | | -// Edit Job modal |
939 | | -// ───────────────────────────────────────────── |
940 | | -
|
941 | | -const showEditModal = ref(false) |
942 | | -const editForm = ref({ |
943 | | - title: '', |
944 | | - description: '', |
945 | | - location: '', |
946 | | - type: 'full_time' as string, |
947 | | -}) |
948 | | -
|
949 | | -const editSchema = z.object({ |
950 | | - title: z.string().min(1, 'Title is required').max(200), |
951 | | - description: z.string().optional(), |
952 | | - location: z.string().optional(), |
953 | | - type: z.enum(['full_time', 'part_time', 'contract', 'internship']), |
954 | | -}) |
955 | | -
|
956 | | -const isSaving = ref(false) |
957 | | -const editErrors = ref<Record<string, string>>({}) |
958 | | -
|
959 | | -function startEdit() { |
960 | | - if (!jobData.value) return |
961 | | - editForm.value = { |
962 | | - title: jobData.value.title, |
963 | | - description: jobData.value.description ?? '', |
964 | | - location: jobData.value.location ?? '', |
965 | | - type: jobData.value.type, |
966 | | - } |
967 | | - editErrors.value = {} |
968 | | - showEditModal.value = true |
969 | | - showMoreMenu.value = false |
970 | | -} |
971 | | -
|
972 | | -function cancelEdit() { |
973 | | - showEditModal.value = false |
974 | | - editErrors.value = {} |
975 | | -} |
976 | | -
|
977 | | -async function handleSave() { |
978 | | - const result = editSchema.safeParse(editForm.value) |
979 | | - if (!result.success) { |
980 | | - editErrors.value = {} |
981 | | - for (const issue of result.error.issues) { |
982 | | - const field = issue.path[0]?.toString() |
983 | | - if (field) editErrors.value[field] = issue.message |
984 | | - } |
985 | | - return |
986 | | - } |
987 | | - editErrors.value = {} |
988 | | -
|
989 | | - isSaving.value = true |
990 | | - try { |
991 | | - await updateJob({ |
992 | | - title: editForm.value.title, |
993 | | - description: editForm.value.description || undefined, |
994 | | - location: editForm.value.location || undefined, |
995 | | - type: editForm.value.type as any, |
996 | | - }) |
997 | | - showEditModal.value = false |
998 | | - } catch (err: any) { |
999 | | - if (handlePreviewReadOnlyError(err)) return |
1000 | | - toast.error('Failed to save changes', { message: err.data?.statusMessage, statusCode: err.data?.statusCode }) |
1001 | | - } finally { |
1002 | | - isSaving.value = false |
1003 | | - } |
1004 | | -} |
1005 | | -
|
1006 | | -const typeOptions = [ |
1007 | | - { value: 'full_time', label: 'Full-time' }, |
1008 | | - { value: 'part_time', label: 'Part-time' }, |
1009 | | - { value: 'contract', label: 'Contract' }, |
1010 | | - { value: 'internship', label: 'Internship' }, |
1011 | | -] |
1012 | | -
|
1013 | 936 | // ───────────────────────────────────────────── |
1014 | 937 | // Delete |
1015 | 938 | // ───────────────────────────────────────────── |
@@ -1264,13 +1187,14 @@ function closeDocPreview() { |
1264 | 1187 | v-if="showMoreMenu" |
1265 | 1188 | class="absolute right-0 top-full mt-1.5 z-50 w-52 rounded-xl border border-surface-200 dark:border-surface-700/80 bg-white dark:bg-surface-900 shadow-xl shadow-surface-900/5 dark:shadow-black/20 py-1.5 origin-top-right" |
1266 | 1189 | > |
1267 | | - <button |
1268 | | - class="flex w-full cursor-pointer items-center gap-2.5 px-3.5 py-2 text-sm text-surface-700 dark:text-surface-300 hover:bg-surface-50 dark:hover:bg-surface-800/80 transition-colors" |
1269 | | - @click="startEdit" |
| 1190 | + <NuxtLink |
| 1191 | + :to="$localePath(`/dashboard/jobs/${jobId}/settings`)" |
| 1192 | + class="flex w-full items-center gap-2.5 px-3.5 py-2 text-sm text-surface-700 dark:text-surface-300 hover:bg-surface-50 dark:hover:bg-surface-800/80 transition-colors" |
| 1193 | + @click="showMoreMenu = false" |
1270 | 1194 | > |
1271 | 1195 | <Pencil class="size-3.5 text-surface-400" /> |
1272 | 1196 | Edit Job |
1273 | | - </button> |
| 1197 | + </NuxtLink> |
1274 | 1198 | <button |
1275 | 1199 | class="flex w-full cursor-pointer items-center gap-2.5 px-3.5 py-2 text-sm text-surface-700 dark:text-surface-300 hover:bg-surface-50 dark:hover:bg-surface-800/80 transition-colors sm:hidden" |
1276 | 1200 | @click="showApplyModal = true; showMoreMenu = false" |
@@ -2361,88 +2285,6 @@ function closeDocPreview() { |
2361 | 2285 | <!-- MODALS --> |
2362 | 2286 | <!-- ═══════════════════════════════════════ --> |
2363 | 2287 |
|
2364 | | - <!-- Edit Job Modal --> |
2365 | | - <Teleport :to="teleportTarget"> |
2366 | | - <div v-if="showEditModal" class="fixed inset-0 z-50 flex items-center justify-center"> |
2367 | | - <div class="absolute inset-0 bg-black/40 backdrop-blur-sm" @click="cancelEdit" /> |
2368 | | - <div class="relative bg-white dark:bg-surface-900 rounded-2xl shadow-2xl shadow-surface-900/10 dark:shadow-black/30 ring-1 ring-surface-200/80 dark:ring-surface-700/60 p-6 max-w-lg w-full mx-4 max-h-[90vh] overflow-y-auto"> |
2369 | | - <h3 class="text-lg font-semibold text-surface-900 dark:text-surface-100 mb-4">Edit Job</h3> |
2370 | | - |
2371 | | - <form class="space-y-4" @submit.prevent="handleSave"> |
2372 | | - <div> |
2373 | | - <label for="edit-title" class="block text-sm font-medium text-surface-700 dark:text-surface-300 mb-1"> |
2374 | | - Title <span class="text-danger-500">*</span> |
2375 | | - </label> |
2376 | | - <input |
2377 | | - id="edit-title" |
2378 | | - v-model="editForm.title" |
2379 | | - type="text" |
2380 | | - class="w-full rounded-lg border px-3 py-2 text-sm text-surface-900 dark:text-surface-100 bg-white dark:bg-surface-800 placeholder:text-surface-400 focus:outline-none focus:ring-2 focus:ring-brand-500 focus:border-brand-500 transition-colors" |
2381 | | - :class="editErrors.title ? 'border-danger-300' : 'border-surface-300 dark:border-surface-700'" |
2382 | | - /> |
2383 | | - <p v-if="editErrors.title" class="mt-1 text-xs text-danger-600 dark:text-danger-400">{{ editErrors.title }}</p> |
2384 | | - </div> |
2385 | | - |
2386 | | - <div> |
2387 | | - <label for="edit-description" class="block text-sm font-medium text-surface-700 dark:text-surface-300 mb-1"> |
2388 | | - Description |
2389 | | - </label> |
2390 | | - <textarea |
2391 | | - id="edit-description" |
2392 | | - v-model="editForm.description" |
2393 | | - rows="4" |
2394 | | - class="w-full rounded-lg border border-surface-300 dark:border-surface-700 px-3 py-2 text-sm text-surface-900 dark:text-surface-100 bg-white dark:bg-surface-800 placeholder:text-surface-400 focus:outline-none focus:ring-2 focus:ring-brand-500 focus:border-brand-500 transition-colors" |
2395 | | - /> |
2396 | | - </div> |
2397 | | - |
2398 | | - <div> |
2399 | | - <label for="edit-location" class="block text-sm font-medium text-surface-700 dark:text-surface-300 mb-1"> |
2400 | | - Location |
2401 | | - </label> |
2402 | | - <input |
2403 | | - id="edit-location" |
2404 | | - v-model="editForm.location" |
2405 | | - type="text" |
2406 | | - class="w-full rounded-lg border border-surface-300 dark:border-surface-700 px-3 py-2 text-sm text-surface-900 dark:text-surface-100 bg-white dark:bg-surface-800 placeholder:text-surface-400 focus:outline-none focus:ring-2 focus:ring-brand-500 focus:border-brand-500 transition-colors" |
2407 | | - /> |
2408 | | - </div> |
2409 | | - |
2410 | | - <div> |
2411 | | - <label for="edit-type" class="block text-sm font-medium text-surface-700 dark:text-surface-300 mb-1"> |
2412 | | - Employment Type |
2413 | | - </label> |
2414 | | - <select |
2415 | | - id="edit-type" |
2416 | | - v-model="editForm.type" |
2417 | | - class="w-full rounded-lg border border-surface-300 dark:border-surface-700 px-3 py-2 text-sm text-surface-900 dark:text-surface-100 focus:outline-none focus:ring-2 focus:ring-brand-500 focus:border-brand-500 transition-colors bg-white dark:bg-surface-800" |
2418 | | - > |
2419 | | - <option v-for="opt in typeOptions" :key="opt.value" :value="opt.value"> |
2420 | | - {{ opt.label }} |
2421 | | - </option> |
2422 | | - </select> |
2423 | | - </div> |
2424 | | - |
2425 | | - <div class="flex items-center justify-end gap-3 pt-2"> |
2426 | | - <button |
2427 | | - type="button" |
2428 | | - class="cursor-pointer rounded-lg border border-surface-300 dark:border-surface-700 px-4 py-2 text-sm font-medium text-surface-700 dark:text-surface-300 hover:bg-surface-50 dark:hover:bg-surface-800 transition-colors" |
2429 | | - @click="cancelEdit" |
2430 | | - > |
2431 | | - Cancel |
2432 | | - </button> |
2433 | | - <button |
2434 | | - type="submit" |
2435 | | - :disabled="isSaving" |
2436 | | - class="cursor-pointer rounded-lg bg-brand-600 px-4 py-2 text-sm font-medium text-white hover:bg-brand-700 disabled:opacity-50 disabled:cursor-not-allowed transition-colors" |
2437 | | - > |
2438 | | - {{ isSaving ? 'Saving…' : 'Save Changes' }} |
2439 | | - </button> |
2440 | | - </div> |
2441 | | - </form> |
2442 | | - </div> |
2443 | | - </div> |
2444 | | - </Teleport> |
2445 | | - |
2446 | 2288 | <!-- Delete Job Confirm --> |
2447 | 2289 | <Teleport :to="teleportTarget"> |
2448 | 2290 | <div v-if="showDeleteConfirm" class="fixed inset-0 z-50 flex items-center justify-center"> |
|
0 commit comments