Advertisement
Guest User

Untitled

a guest
Jan 22nd, 2021
117
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. import Employee from "../interfaces/employee"
  2. import { uniqWith } from "lodash"
  3. import Message from "../interfaces/message"
  4. import Product from "../interfaces/product"
  5. import ScannedLot from "../interfaces/scanned-lot"
  6. import gid from "../utils/gid"
  7. import { fetchEmployee, fetchProds } from "../utils/simple-fetches"
  8.  
  9. export const CLEAR_INPUT_DELAY = 150
  10. export const PARSE_INPUT_DELAY = 100
  11. export const HIDE_DURATION = 2000
  12.  
  13. const SCAN_LOTS_MSG = "Отсканируйте лоты"
  14. const SCAN_YOUR_ID_MSG = "Отсканируйте свой ID"
  15.  
  16. export enum Types {
  17.   Login,
  18.   StartLoading,
  19.   StopLoading,
  20.   RemoveLot,
  21.   SetErrorLot,
  22.   SetMessage,
  23.   FinallyLotSaving,
  24.   SetLot,
  25.   SetInput,
  26.   ClearErrorLots,
  27.   FinishLotSaving,
  28. }
  29.  
  30. type Payload = {
  31.   [Types.Login]: { employee: Employee; employeeAID: string }
  32.   [Types.StartLoading]: null
  33.   [Types.StopLoading]: null
  34.   [Types.RemoveLot]: ScannedLot
  35.   [Types.SetErrorLot]: { error: string; lot: ScannedLot }
  36.   [Types.SetMessage]: Message
  37.   [Types.FinallyLotSaving]: null
  38.   [Types.SetLot]: {
  39.     productAID: string
  40.     lotnum: number
  41.     order: string
  42.     product: Product
  43.     qty: number
  44.     orderQty: number
  45.   }
  46.   [Types.SetInput]: string
  47.   [Types.ClearErrorLots]: null
  48.   [Types.FinishLotSaving]: null
  49. }
  50.  
  51. type ActionMap<M> = {
  52.   [Key in keyof M]: M[Key] extends null
  53.     ? {
  54.         type: Key
  55.       }
  56.     : {
  57.         type: Key
  58.         payload: M[Key]
  59.       }
  60. }
  61.  
  62. export type Actions = ActionMap<Payload>[keyof ActionMap<Payload>]
  63.  
  64. export interface State {
  65.   input: string
  66.   placeholder: string
  67.   currentEmployee: Employee
  68.   scannedLots: ScannedLot[]
  69.   showBackdrop: boolean
  70.   message: Message
  71.   showMessage: boolean
  72.   loading: boolean
  73. }
  74.  
  75. export const initialState: State = {
  76.   input: "",
  77.   placeholder: SCAN_YOUR_ID_MSG,
  78.   currentEmployee: null,
  79.   scannedLots: [],
  80.   showBackdrop: false,
  81.   message: null,
  82.   showMessage: false,
  83.   loading: false,
  84. }
  85.  
  86. export const reducer = (state: State, action: Actions): State => {
  87.   switch (action.type) {
  88.     case Types.Login:
  89.       return action.payload.employee
  90.         ? {
  91.             ...state,
  92.             currentEmployee: action.payload.employee,
  93.             placeholder: SCAN_LOTS_MSG,
  94.             scannedLots: [],
  95.           }
  96.         : {
  97.             ...state,
  98.             placeholder: SCAN_YOUR_ID_MSG,
  99.             currentEmployee: null,
  100.             showMessage: true,
  101.             message: {
  102.               message: `Сотрудник ${action.payload.employeeAID} не найден`,
  103.               error: true,
  104.             },
  105.             scannedLots: [],
  106.           }
  107.     case Types.SetInput:
  108.       return { ...state, input: action.payload }
  109.     case Types.StartLoading:
  110.       return { ...state, loading: true }
  111.     case Types.StopLoading:
  112.       return { ...state, loading: false }
  113.     case Types.RemoveLot:
  114.       const scannedLots = state.scannedLots.filter(
  115.         l => gid(l) !== gid(action.payload)
  116.       )
  117.       return {
  118.         ...state,
  119.         scannedLots,
  120.         placeholder:
  121.           scannedLots.length === 0 ? SCAN_LOTS_MSG : state.placeholder,
  122.       }
  123.     case Types.SetErrorLot:
  124.       return {
  125.         ...state,
  126.         scannedLots: state.scannedLots.map(l =>
  127.           gid(l) === gid(action.payload.lot)
  128.             ? {
  129.                 ...l,
  130.                 error: action.payload.error,
  131.               }
  132.             : l
  133.         ),
  134.       }
  135.     case Types.SetMessage:
  136.       return {
  137.         ...state,
  138.         message: action.payload,
  139.         showMessage: !!action.payload.message,
  140.       }
  141.     case Types.FinishLotSaving:
  142.       return {
  143.         ...state,
  144.         message: state.scannedLots.some(l => l.error)
  145.           ? {
  146.               message: "Не удалось сохранить один или несколько лотов",
  147.               error: true,
  148.             }
  149.           : {
  150.               message: "Все лоты успешно сохранены",
  151.             },
  152.       }
  153.     case Types.FinallyLotSaving:
  154.       return {
  155.         ...state,
  156.         loading: false,
  157.         showMessage: true,
  158.         placeholder: SCAN_LOTS_MSG,
  159.       }
  160.     case Types.SetLot:
  161.       return action.payload.product
  162.         ? {
  163.             ...state,
  164.             placeholder: "Отсканируйте рабочий центр или другие лоты",
  165.             scannedLots: uniqWith(
  166.               [
  167.                 ...state.scannedLots,
  168.                 {
  169.                   lotnum: action.payload.lotnum,
  170.                   product: Number(action.payload.product.id),
  171.                   productCode: action.payload.product.code,
  172.                   order: action.payload.order,
  173.                   productAID: action.payload.productAID,
  174.                   qty: Number(action.payload.qty),
  175.                   orderQty: action.payload.orderQty,
  176.                 },
  177.               ],
  178.               (a, b) => gid(a) === gid(b)
  179.             ),
  180.           }
  181.         : {
  182.             ...state,
  183.             message: {
  184.               message: `Продукт ${action.payload.productAID} не найден`,
  185.               error: true,
  186.             },
  187.           }
  188.     case Types.ClearErrorLots:
  189.       return { ...state, scannedLots: state.scannedLots.filter(l => !l.error) }
  190.     default:
  191.       return state
  192.   }
  193. }
  194.  
  195. export interface LotRow {
  196.   productAID: string
  197.   lotnum: number
  198.   order: string
  199.   qty: number
  200.   orderQty: number
  201. }
  202.  
  203. export const setLotRow = async (row: LotRow, dispatch) => {
  204.   dispatch({ type: Types.StartLoading })
  205.   const {
  206.     data: { products },
  207.   } = await fetchProds(row.productAID)
  208.   dispatch({ type: Types.StopLoading })
  209.   dispatch({
  210.     type: Types.SetLot,
  211.     payload: {
  212.       product: products[0],
  213.       ...row,
  214.     },
  215.   })
  216. }
  217.  
  218. export const login = async (employeeAID: string, dispatch) => {
  219.   dispatch({ type: Types.StartLoading })
  220.   const {
  221.     data: { employees },
  222.   } = await fetchEmployee(employeeAID)
  223.   dispatch({ type: Types.StopLoading })
  224.   dispatch({
  225.     type: Types.Login,
  226.     payload: { employeeAID, employee: employees[0] },
  227.   })
  228. }
  229.  
  230. export interface SaveLotsProps {
  231.   workingCenterAID: string
  232.   handleLot: (
  233.     incompleteLot: ScannedLot,
  234.     workingCenterAID: string
  235.   ) => Promise<void>
  236.   lots: ScannedLot[]
  237.   dispatch: any
  238. }
  239.  
  240. export const saveLots = async (props: SaveLotsProps) => {
  241.   try {
  242.     props.dispatch({ type: Types.StartLoading })
  243.     await Promise.all(
  244.       props.lots.map(l => props.handleLot(l, props.workingCenterAID))
  245.     )
  246.     props.dispatch({ type: Types.FinishLotSaving })
  247.   } catch (e) {
  248.     props.dispatch({
  249.       type: Types.SetMessage,
  250.       payload: {
  251.         message: e.toString(),
  252.         error: true,
  253.       },
  254.     })
  255.   } finally {
  256.     props.dispatch({ type: Types.FinallyLotSaving })
  257.   }
  258. }
  259.  
  260. export interface MainEffectProps {
  261.   state: State
  262.   debouncedInputClear: () => void
  263.   login: (employeeAID: string) => void
  264.   dispatch: any
  265.   setLot: (props: LotRow) => void
  266.   saveLots: (workingCenterAID: string) => void
  267. }
  268.  
  269. export const mainEffect = (props: MainEffectProps) => {
  270.   const employeeAID = props.state.input
  271.   const [order, , productAID, orderQty, qty, lotnum] = props.state.input.split(
  272.     "/"
  273.   )
  274.   const [workingCenterAID] = props.state.input.split("_")
  275.  
  276.   if (!props.state.input) return
  277.  
  278.   props.debouncedInputClear()
  279.  
  280.   if (!isNaN(Number(employeeAID))) {
  281.     props.login(employeeAID)
  282.   } else if (props.state.currentEmployee && lotnum) {
  283.     props.dispatch({ type: Types.ClearErrorLots })
  284.     props.setLot({
  285.       productAID,
  286.       lotnum: Number(lotnum),
  287.       order,
  288.       qty: Number(qty),
  289.       orderQty: Number(orderQty),
  290.     })
  291.   } else if (
  292.     props.state.currentEmployee &&
  293.     workingCenterAID &&
  294.     props.state.scannedLots.filter(l => !l.error).length > 0
  295.   ) {
  296.     props.saveLots(workingCenterAID)
  297.   }
  298. }
  299.  
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement