helpers.ts 2.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103
  1. import { toPng } from 'html-to-image'
  2. import { isIOS } from '~/utils/ua'
  3. export const formatNumber = (value: number) =>
  4. new Intl.NumberFormat().format(value)
  5. export interface IdrFormatOptions {
  6. /** Format with currency symbol (Rp) */
  7. withSymbol?: boolean
  8. /** Minimum fraction digits */
  9. minimumFractionDigits?: number
  10. /** Maximum fraction digits */
  11. maximumFractionDigits?: number
  12. /** Fallback string for invalid input */
  13. fallback?: string
  14. }
  15. export const idrFormat = (
  16. value: number | string | null | undefined,
  17. options: IdrFormatOptions = {},
  18. ): string => {
  19. const {
  20. withSymbol = false,
  21. minimumFractionDigits = 0,
  22. maximumFractionDigits = 0,
  23. fallback = '0',
  24. } = options
  25. const n = typeof value === 'number'
  26. ? value
  27. : Number(String(value ?? '').replace(/,/g, '').trim())
  28. if (!Number.isFinite(n)) return fallback
  29. if (withSymbol) {
  30. return new Intl.NumberFormat('id-ID', {
  31. style: 'currency',
  32. currency: 'IDR',
  33. minimumFractionDigits,
  34. maximumFractionDigits,
  35. }).format(n)
  36. }
  37. return new Intl.NumberFormat('id-ID', {
  38. style: 'decimal',
  39. minimumFractionDigits,
  40. maximumFractionDigits,
  41. }).format(n)
  42. }
  43. export const sleep = (ms: number): Promise<void> => new Promise(resolve => setTimeout(resolve, ms))
  44. export const buildPng = async (element: HTMLElement) => {
  45. let dataUrl = ''
  46. const minDataLength = 100000
  47. let i = 0
  48. const minAttempts = 3
  49. const maxAttempts = 10
  50. while (i < minAttempts || (dataUrl.length < minDataLength && i < maxAttempts)) {
  51. dataUrl = await toPng(element, {
  52. cacheBust: true,
  53. })
  54. i += 1
  55. }
  56. return dataUrl
  57. }
  58. export const getDeviceLanguage = () => {
  59. try {
  60. const language = navigator.language
  61. if (language.includes('id')) {
  62. return 'id'
  63. }
  64. else if (language.includes('zh')) {
  65. return 'zh'
  66. }
  67. else {
  68. return 'en'
  69. }
  70. }
  71. catch {
  72. return 'en'
  73. }
  74. }
  75. export const isNativeContext = () => {
  76. return typeof window !== 'undefined' && window.GAMI_BRIDGE !== undefined
  77. }
  78. export const callNativeScheme = (scheme: string) => {
  79. if (import.meta.client && isNativeContext()) {
  80. window.location.href = scheme
  81. }
  82. }
  83. export const callDeepLink = (url: string) => {
  84. if (import.meta.client && !isIOS()) {
  85. window.location.href = url
  86. }
  87. }