usAppAuth.ts 5.76 KB
import type { UsAppBoundLocationDto } from '../types/usAppBound'
import { usAppApiRequest } from '../utils/usAppApiRequest'
import { fetchWithOfflineCache } from '../utils/sqliteSync'

/** GET /api/app/us-app-auth/my-profile → UsAppMyProfileOutputDto */
export interface UsAppMyProfileOutputDto {
  fullName: string
  email: string
  phone: string
  employeeId: string
  roleDisplay: string
  primaryRoleCode: string | null
}

export interface UsAppChangePasswordInput {
  currentPassword: string
  newPassword: string
  confirmNewPassword: string
}

/** GET /api/app/us-app-auth/location-detail/{locationId} */
export interface UsAppLocationDetailOutputDto {
  locationId: string
  locationName: string
  fullAddress: string
  storePhone: string
  operatingHours: string
  managerName: string
  managerPhone: string
}

export type { UsAppBoundLocationDto }

export interface UsAppLoginInput {
  email: string
  password: string
  uuid?: string
  code?: string
}

export interface UsAppLoginOutputDto {
  token: string
  refreshToken: string
  locations: UsAppBoundLocationDto[]
}

function normalizeLocation(raw: Record<string, unknown>): UsAppBoundLocationDto {
  return {
    id: String(raw.id ?? raw.Id ?? ''),
    locationCode: String(raw.locationCode ?? raw.LocationCode ?? ''),
    locationName: String(raw.locationName ?? raw.LocationName ?? ''),
    fullAddress: String(raw.fullAddress ?? raw.FullAddress ?? ''),
    state: raw.state !== false && raw.State !== false,
  }
}

function normalizeLoginOutput(raw: unknown): UsAppLoginOutputDto {
  const o = raw as Record<string, unknown>
  const locs = o.locations ?? o.Locations
  const arr = Array.isArray(locs) ? locs : []
  return {
    token: String(o.token ?? o.Token ?? ''),
    refreshToken: String(o.refreshToken ?? o.RefreshToken ?? ''),
    locations: arr.map((x) => normalizeLocation(x as Record<string, unknown>)),
  }
}

function normalizeLocationList(raw: unknown): UsAppBoundLocationDto[] {
  const arr = Array.isArray(raw) ? raw : []
  return arr.map((x) => normalizeLocation(x as Record<string, unknown>))
}

/** POST /api/app/us-app-auth/login(401 不触发全局跳转) */
export async function usAppLogin(input: UsAppLoginInput): Promise<UsAppLoginOutputDto> {
  const raw = await usAppApiRequest<unknown>({
    path: '/api/app/us-app-auth/login',
    method: 'POST',
    skipUnauthorizedRedirect: true,
    data: {
      email: input.email.trim(),
      password: input.password,
      ...(input.uuid ? { uuid: input.uuid } : {}),
      ...(input.code != null ? { code: input.code } : {}),
    },
  })
  return normalizeLoginOutput(raw)
}

/** GET /api/app/us-app-auth/my-locations */
export async function usAppFetchMyLocations(): Promise<UsAppBoundLocationDto[]> {
  return fetchWithOfflineCache('auth', 'my-locations', async () => {
    const raw = await usAppApiRequest<unknown>({
      path: '/api/app/us-app-auth/my-locations',
      method: 'GET',
      auth: true,
    })
    return normalizeLocationList(raw)
  })
}

function normalizeMyProfile(raw: unknown): UsAppMyProfileOutputDto {
  const o = (raw && typeof raw === 'object' ? raw : {}) as Record<string, unknown>
  const pr = o.primaryRoleCode ?? o.PrimaryRoleCode
  return {
    fullName: String(o.fullName ?? o.FullName ?? ''),
    email: String(o.email ?? o.Email ?? ''),
    phone: String(o.phone ?? o.Phone ?? ''),
    employeeId: String(o.employeeId ?? o.EmployeeId ?? ''),
    roleDisplay: String(o.roleDisplay ?? o.RoleDisplay ?? ''),
    primaryRoleCode: pr == null || pr === '' ? null : String(pr),
  }
}

/** GET /api/app/us-app-auth/my-profile */
export async function usAppFetchMyProfile(): Promise<UsAppMyProfileOutputDto> {
  return fetchWithOfflineCache('auth', 'my-profile', async () => {
    const raw = await usAppApiRequest<unknown>({
      path: '/api/app/us-app-auth/my-profile',
      method: 'GET',
      auth: true,
    })
    return normalizeMyProfile(unwrapIfNeeded(raw))
  })
}

function unwrapIfNeeded(raw: unknown): unknown {
  if (raw == null || typeof raw !== 'object') return raw
  const o = raw as Record<string, unknown>
  if ('result' in o && o.result !== undefined) return o.result
  if (o.data !== undefined) return o.data
  if (o.Data !== undefined) return o.Data
  return raw
}

function normalizeLocationDetail(raw: unknown): UsAppLocationDetailOutputDto {
  const o = (unwrapIfNeeded(raw) ?? {}) as Record<string, unknown>
  return {
    locationId: String(o.locationId ?? o.LocationId ?? ''),
    locationName: String(o.locationName ?? o.LocationName ?? ''),
    fullAddress: String(o.fullAddress ?? o.FullAddress ?? ''),
    storePhone: String(o.storePhone ?? o.StorePhone ?? ''),
    operatingHours: String(o.operatingHours ?? o.OperatingHours ?? ''),
    managerName: String(o.managerName ?? o.ManagerName ?? ''),
    managerPhone: String(o.managerPhone ?? o.ManagerPhone ?? ''),
  }
}

/**
 * GET /api/app/us-app-auth/location-detail/{locationId}
 * 文档:locationId 为路径参数;需当前用户已绑定该门店。
 */
export async function usAppFetchLocationDetail(locationId: string): Promise<UsAppLocationDetailOutputDto> {
  const id = (locationId || '').trim()
  return fetchWithOfflineCache('auth', `location-detail:${id}`, async () => {
    const raw = await usAppApiRequest<unknown>({
      path: `/api/app/us-app-auth/location-detail/${encodeURIComponent(id)}`,
      method: 'GET',
      auth: true,
    })
    return normalizeLocationDetail(raw)
  })
}

/** POST /api/app/us-app-auth/change-password */
export async function usAppChangePassword(input: UsAppChangePasswordInput): Promise<void> {
  await usAppApiRequest<unknown>({
    path: '/api/app/us-app-auth/change-password',
    method: 'POST',
    auth: true,
    data: {
      currentPassword: input.currentPassword,
      newPassword: input.newPassword,
      confirmNewPassword: input.confirmNewPassword,
    },
  })
}