refactor(ui): T1 (suite) — unifier les formatters variants vers les canoniques (formats cohérents)
Sur autorisation user (changement d'affichage OK si ça améliore l'UI) : - date+heure → formatDateTimeShort : Settings, GiftsInventory, EmailQueue - date → formatDate : Subcontractors - initials → staffInitials (1er+dernier) : Historique - fmtDur → useHelpers.fmtDur («30m»/«1h30») : RendezVous LAISSÉS (UX volontaire/niche) : ConversationPanel formatDate (relatif auj/hier), PublishScheduleModal (d/m compact), TechTasks fmtDate (weekday terrain), Planif fmtH (axe timeline), SupplierInvoices fmtMoney (multi-devise). Build vert, leak 0 ; 12 copies locales éliminées au total (T1). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
parent
1017cab649
commit
7ab71ce6a8
|
|
@ -145,6 +145,7 @@
|
|||
|
||||
<script setup>
|
||||
import { ref, computed, onMounted } from 'vue'
|
||||
import { formatDateTimeShort as formatDate } from 'src/composables/useFormatters' // date+heure canonique (source unique)
|
||||
import { useRoute } from 'vue-router'
|
||||
import DataTable from 'src/components/shared/DataTable.vue'
|
||||
import { useQuasar } from 'quasar'
|
||||
|
|
@ -263,10 +264,7 @@ function giftbitAdminUrl (giftUrl) {
|
|||
if (!code || code.length < 4) return null
|
||||
return `https://app.giftbit.com/app/rewards?search=${encodeURIComponent(code)}`
|
||||
}
|
||||
function formatDate (iso) {
|
||||
if (!iso) return ''
|
||||
return new Date(iso).toLocaleString('fr-CA', { dateStyle: 'medium', timeStyle: 'short' })
|
||||
}
|
||||
// formatDate → useFormatters.formatDateTimeShort (date+heure canonique)
|
||||
|
||||
async function copy (text, customMsg) {
|
||||
try {
|
||||
|
|
|
|||
|
|
@ -72,6 +72,7 @@
|
|||
|
||||
<script setup>
|
||||
import { ref, computed, onMounted } from 'vue'
|
||||
import { formatDateTimeShort as fmtDate } from 'src/composables/useFormatters' // date+heure canonique (source unique)
|
||||
import DataTable from 'src/components/shared/DataTable.vue'
|
||||
import { useQuasar } from 'quasar'
|
||||
import { listEmailQueue, deleteEmailQueueItem, purgeEmailQueue } from 'src/api/emailQueue'
|
||||
|
|
@ -105,9 +106,7 @@ const notSentCount = computed(() => byStatus.value['Not Sent'] || 0)
|
|||
function statusColor (s) {
|
||||
return { 'Not Sent': 'orange-8', Sending: 'blue-6', Sent: 'green-7', Error: 'negative', Expired: 'grey-6' }[s] || 'grey-7'
|
||||
}
|
||||
function fmtDate (iso) {
|
||||
return iso ? new Date(iso.replace(' ', 'T')).toLocaleString('fr-CA', { dateStyle: 'medium', timeStyle: 'short' }) : ''
|
||||
}
|
||||
// fmtDate → useFormatters.formatDateTimeShort (date+heure canonique)
|
||||
|
||||
async function load () {
|
||||
loading.value = true
|
||||
|
|
|
|||
|
|
@ -143,6 +143,7 @@
|
|||
|
||||
<script setup>
|
||||
import { ref, computed, onMounted } from 'vue'
|
||||
import { staffInitials as initials } from 'src/composables/useFormatters' // initiales 1er+dernier (source unique)
|
||||
import { Notify } from 'quasar'
|
||||
import { HUB_URL } from 'src/config/hub'
|
||||
|
||||
|
|
@ -161,10 +162,7 @@ async function hubGet (path) {
|
|||
}
|
||||
|
||||
// ── Affichage commun ──
|
||||
function initials (name) {
|
||||
const parts = String(name || '?').trim().split(/\s+/).filter(Boolean)
|
||||
return ((parts[0]?.[0] || '') + (parts.length > 1 ? parts[parts.length - 1][0] : '')).toUpperCase() || '?'
|
||||
}
|
||||
// initials → useFormatters.staffInitials (1er + dernier mot, source unique)
|
||||
function prettyDate (iso) {
|
||||
if (!iso) return ''
|
||||
const [y, m, d] = iso.split('-').map(Number)
|
||||
|
|
|
|||
|
|
@ -123,6 +123,7 @@
|
|||
|
||||
<script setup>
|
||||
import { ref, reactive, computed, onMounted, onBeforeUnmount } from 'vue'
|
||||
import { fmtDur } from 'src/composables/useHelpers' // durée canonique (source unique : «30m»/«1h»/«1h30»)
|
||||
import { MapPin } from 'lucide-vue-next' // pin monochrome outline (style menu Dispatch)
|
||||
import { useQuasar } from 'quasar'
|
||||
import * as roster from 'src/api/roster'
|
||||
|
|
@ -155,7 +156,7 @@ function dayLabel (iso) { const dt = d2(iso); return FR_DOW_FULL[dt.getUTCDay()]
|
|||
// Titre LISIBLE d'un job : type de service + client (l'ID DJ-… est secondaire). Lieu = adresse lisible si dispo.
|
||||
function jobTitle (j) { if (!j) return ''; const t = (j.service_type || '').trim(); const c = (j.customer_name || '').trim(); if (t) return c ? (t + ' — ' + c) : t; return c || j.location_label || j.name }
|
||||
function jobLoc (j) { return (j && (j.location_label || j.service_location)) || '—' }
|
||||
function fmtDur (h) { h = Number(h) || 0; const H = Math.floor(h); const M = Math.round((h - H) * 60); return M ? (H + 'h' + String(M).padStart(2, '0')) : (H + 'h') }
|
||||
// fmtDur → useHelpers.fmtDur (source unique)
|
||||
function wkMon (iso) { const dt = d2(iso); const off = (dt.getUTCDay() + 6) % 7; dt.setUTCDate(dt.getUTCDate() - off); return dt.toISOString().slice(0, 10) }
|
||||
function wkLabel (m) { const a = d2(m); const b = new Date(a); b.setUTCDate(b.getUTCDate() + 6); return 'Semaine du ' + a.getUTCDate() + ' ' + MO[a.getUTCMonth()] + ' – ' + b.getUTCDate() + ' ' + MO[b.getUTCMonth()] }
|
||||
|
||||
|
|
|
|||
|
|
@ -749,6 +749,7 @@
|
|||
|
||||
<script setup>
|
||||
import { ref, reactive, onMounted, watch, defineAsyncComponent, h, resolveComponent } from 'vue'
|
||||
import { formatDateTimeShort as formatDate } from 'src/composables/useFormatters' // date+heure canonique (source unique)
|
||||
import { Notify } from 'quasar'
|
||||
import { authFetch } from 'src/api/auth'
|
||||
import { BASE_URL, ERP_DESK_URL as erpDeskUrl } from 'src/config/erpnext'
|
||||
|
|
@ -857,10 +858,7 @@ function initial (u) {
|
|||
return (u.name || u.username || '?')[0].toUpperCase()
|
||||
}
|
||||
|
||||
function formatDate (d) {
|
||||
if (!d) return ''
|
||||
return new Date(d).toLocaleDateString('fr-CA', { year: 'numeric', month: 'short', day: 'numeric', hour: '2-digit', minute: '2-digit' })
|
||||
}
|
||||
// formatDate → useFormatters.formatDateTimeShort (date+heure canonique)
|
||||
|
||||
function savePhone () {
|
||||
savePhoneConfig(phoneConfig.value)
|
||||
|
|
|
|||
|
|
@ -196,7 +196,7 @@
|
|||
import { ref, reactive, computed, onMounted } from 'vue'
|
||||
import { useQuasar } from 'quasar'
|
||||
import { usePermissions } from 'src/composables/usePermissions'
|
||||
import { formatMoney as money } from 'src/composables/useFormatters'
|
||||
import { formatMoney as money, formatDate as fmtDate } from 'src/composables/useFormatters'
|
||||
import { getRates, saveRates, listSubmissions, sendLink, approve, imgUrl, getSubs, saveSub, getReleve, markPaid, exportUrl, getEntente, saveEntente } from 'src/api/subcontractor'
|
||||
import { listDocs } from 'src/api/erp'
|
||||
|
||||
|
|
@ -218,7 +218,7 @@ const entente = reactive({ url: '', isPdf: false, edit: false, input: '', saving
|
|||
|
||||
function unitLabel (u) { return ({ case: 'Case (oui/non)', qte: 'Quantité', metres: 'Mètres', heures: 'Heures' })[u] || u }
|
||||
// money() unifié via useFormatters (import ci-dessus) — format fr-CA cohérent
|
||||
function fmtDate (d) { try { return new Date(d).toLocaleDateString('fr-CA', { day: '2-digit', month: 'short', year: 'numeric' }) } catch (e) { return '' } }
|
||||
// fmtDate → useFormatters.formatDate (date canonique, source unique)
|
||||
function statusColor (s) { return s === 'approuvé' ? 'green-7' : s === 'payé' ? 'blue-7' : s === 'refusé' ? 'red-7' : s === 'infructueuse' ? 'orange-8' : 'grey-6' }
|
||||
function statusLabel (s) { return s === 'infructueuse' ? 'infructueuse' : (s || 'soumis') }
|
||||
function photosOf (s) { return (Array.isArray(s.photos) ? s.photos : []).map(p => (typeof p === 'string' ? { file: p } : p)) }
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user