MDK Logo
ReferenceUI KitReactUI Kit foundationComponentsDialogs

AddSparePartModal

Modal for registering a new spare part. Presents a part-type tab strip and a form for miner model, part model, serial number, MAC address (controllers only),…

Modal for registering a new spare part. Presents a part-type tab strip and a form for miner model, part model, serial number, MAC address (controllers only), status, location, tags, and a comment. Validation is controller-aware: controllers require a MAC address, other parts require a serial number. Receives option lists and the submit handler as props.

import { AddSparePartModal } from "@tetherto/mdk-react-devkit";
PropStatusTypeDefaultDescription
isOpenRequiredboolean
onCloseRequiredVoidFunction
partTypesRequiredSparePartSubTypesModalPartType[]
defaultPartTypeIdOptionalstring | undefined
modelOptionsRequiredFormSelectOption[]
isModelOptionsLoadingOptionalboolean | undefined
minerModelOptionsRequiredFormSelectOption[]
statusOptionsRequiredFormSelectOption[]
locationOptionsRequiredFormSelectOption[]
isControllerPartTypeSelectedOptionalboolean | undefined
onPartTypeChangeRequired(partTypeId: string) => void
onSubmitRequired(values: AddSparePartFormValues) => Promise<void | { fieldErrors?: { field: string; message: string; }[] | undefined; }>
isLoadingOptionalboolean | undefined
subTypesPartTypesOptionalSparePartSubTypesModalPartType[] | undefined
subTypesActivePartTypeIdOptionalstring | undefined
subTypesOptionalstring[] | undefined
onSubTypesPartTypeChangeOptional((id: string) => void) | undefined
onAddSubTypeOptional((name: string) => Promise<void | { error?: string | undefined; }>) | undefined
isSubTypesLoadingOptionalboolean | undefined

Usage

Modal for registering a new spare part. Presents a part-type tab strip (Controller, PSU, Hashboard, …) and a form for miner model, part model, serial number, MAC address, status, location, tags, and a comment. Validation is controller-aware — the MAC address field appears and is required only when a controller part type is selected; other part types require a serial number.

When to use

Use this in an inventory "Spare Parts" view when an operator needs to register a single new part. Pair it with SparePartSubTypesModal (via the subTypes* props) so the user can manage the allowed part models without leaving the dialog.

Notes

  • Select fields default to "" (empty), which renders the placeholder. Switching part type clears the part model and any serial/MAC validation errors.
  • MAC validation uses the format 00:1A:2B:3C:4D:5E (case-insensitive, : or - separators).

Example

import { useState } from "react";import {  AddSparePartModal,  Button,  SPARE_PART_LOCATION_LABELS,  SPARE_PART_LOCATIONS,  SPARE_PART_STATUS_NAMES,  SPARE_PART_STATUSES,  SparePartNames,  SparePartTypes,} from "@tetherto/mdk-react-devkit";const PART_TYPES = Object.entries(SparePartTypes).map(([, value]) => ({  value,  label: SparePartNames[value as keyof typeof SparePartNames] ?? value,}));const MINER_MODEL_OPTIONS = [  { value: "antminer-s19", label: "Antminer S19" },  { value: "antminer-s19j", label: "Antminer S19j" },  { value: "whatsminer-m30s", label: "Whatsminer M30S" },];const MODEL_OPTIONS_MAP: Record<string, Array<{ value: string; label: string }>> = {  [SparePartTypes.CONTROLLER]: [    { value: "CT-S19", label: "CT-S19" },    { value: "CT-S19j", label: "CT-S19j" },  ],  [SparePartTypes.PSU]: [{ value: "PSU-3000W", label: "PSU-3000W" }],  [SparePartTypes.HASHBOARD]: [    { value: "HB-S19", label: "HB-S19" },    { value: "HB-S19j", label: "HB-S19j" },  ],};const STATUS_OPTIONS = Object.values(SPARE_PART_STATUSES).map((value) => ({  value,  label: SPARE_PART_STATUS_NAMES[value as keyof typeof SPARE_PART_STATUS_NAMES] ?? value,}));const LOCATION_OPTIONS = Object.values(SPARE_PART_LOCATIONS).map((value) => ({  value,  label: SPARE_PART_LOCATION_LABELS[value] ?? value,}));export const AddSparePartModalExample = () => {  const [isOpen, setIsOpen] = useState(false);  const [activePartType, setActivePartType] = useState(PART_TYPES[0]?.value ?? "");  const modelOptions = MODEL_OPTIONS_MAP[activePartType] ?? [];  const isController = activePartType === SparePartTypes.CONTROLLER;  return (    <div>      <Button variant="primary" onClick={() => setIsOpen(true)}>        Register Part      </Button>      <AddSparePartModal        isOpen={isOpen}        onClose={() => setIsOpen(false)}        partTypes={PART_TYPES}        defaultPartTypeId={activePartType}        modelOptions={modelOptions}        minerModelOptions={MINER_MODEL_OPTIONS}        statusOptions={STATUS_OPTIONS}        locationOptions={LOCATION_OPTIONS}        isControllerPartTypeSelected={isController}        onPartTypeChange={(id) => setActivePartType(id)}        onSubmit={async () => {          setIsOpen(false);        }}      />    </div>  );};