Extract admin dashboard from ghabilee-frontend2 into a dedicated Next.js app for backoffice.ghabilee.ir (no SEO indexing / Clarity).
33 lines
1.0 KiB
TypeScript
33 lines
1.0 KiB
TypeScript
/**
|
|
* Client-side unique id for list keys / draft rows / visitor ids.
|
|
* Prefer Web Crypto when available; some non-secure contexts (e.g. http://LAN-IP)
|
|
* expose `crypto` without `randomUUID`.
|
|
*/
|
|
export function createClientId(): string {
|
|
const webCrypto = globalThis.crypto
|
|
|
|
if (typeof webCrypto?.randomUUID === 'function') {
|
|
return webCrypto.randomUUID()
|
|
}
|
|
|
|
if (typeof webCrypto?.getRandomValues === 'function') {
|
|
const bytes = new Uint8Array(16)
|
|
|
|
webCrypto.getRandomValues(bytes)
|
|
// نسخه ۴ UUID
|
|
bytes[6] = (bytes[6] & 0x0f) | 0x40
|
|
bytes[8] = (bytes[8] & 0x3f) | 0x80
|
|
|
|
const hex = Array.from(bytes, (byte) => byte.toString(16).padStart(2, '0')).join('')
|
|
|
|
return `${hex.slice(0, 8)}-${hex.slice(8, 12)}-${hex.slice(12, 16)}-${hex.slice(16, 20)}-${hex.slice(20)}`
|
|
}
|
|
|
|
return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, (char) => {
|
|
const nibble = (Math.random() * 16) | 0
|
|
const value = char === 'x' ? nibble : (nibble & 0x3) | 0x8
|
|
|
|
return value.toString(16)
|
|
})
|
|
}
|