diff --git a/packages/portal/src/elements/forms/point-entry/create/PointEntryCreator.tsx b/packages/portal/src/elements/forms/point-entry/create/PointEntryCreator.tsx index 21383b762..ae75f4f9c 100644 --- a/packages/portal/src/elements/forms/point-entry/create/PointEntryCreator.tsx +++ b/packages/portal/src/elements/forms/point-entry/create/PointEntryCreator.tsx @@ -1,5 +1,7 @@ -import { App, Button, Flex, Form, Input, InputNumber } from "antd"; -import { useReducer } from "react"; +import { QuestionOutlined } from "@ant-design/icons"; +import type { InputRef, TourProps } from "antd"; +import { App, Button, Flex, Form, Input, InputNumber, Tour } from "antd"; +import { useReducer, useRef, useState } from "react"; import { PointEntryOpportunityLookup } from "./PointEntryOpportunityLookup"; import { PointEntryPersonLookup } from "./PointEntryPersonLookup"; @@ -14,6 +16,59 @@ export function PointEntryCreator({ }) { const { message } = App.useApp(); + const [tourVisible, setTourVisible] = useState(false); + + const commentFieldRef = useRef(null); + const pointsFieldRef = useRef(null); + const nameFieldRef = useRef(null); + const linkblueFieldRef = useRef(null); + const selectedPersonRef = useRef(null); + const clearButtonRef = useRef(null); + const submitButtonRef = useRef(null); + + const steps: TourProps["steps"] = [ + { + title: "Comment", + description: + "Enter a comment for the point entry, the comment is not shown anywhere outside of this page and is just for your reference.", + target: commentFieldRef.current?.input ?? null, + }, + { + title: "Points", + description: "Enter the number of points to give for the point entry.", + target: pointsFieldRef.current ?? null, + }, + { + title: "Name", + description: + "If you know the name of the person that the point entry is for, you can search for them here. If they have signed in before their name will appear in the list. Click on their name to select them.", + target: nameFieldRef.current, + }, + { + title: "Linkblue", + description: + "If you know the linkblue of the person that the point entry is for, you can enter it here. Click lookup to check for the person. If they have already been added to the system they will be selected automatically. Otherwise, a create button will appear that will allow you to create a new person with that linkblue.", + target: linkblueFieldRef.current?.input ?? null, + }, + { + title: "Clear", + description: "Click the clear button to clear the person selection.", + target: clearButtonRef.current ?? null, + }, + { + title: "Selected person", + description: + "Once you have selected a person, their info will appear here.", + target: selectedPersonRef.current ?? null, + }, + { + title: "Submit", + description: + "Once you have filled out the form, click the submit button to create the point entry.", + target: submitButtonRef.current ?? null, + }, + ]; + const [personLookupKey, resetLookup] = useReducer( (prev: number) => prev + 1, 0 @@ -31,6 +86,13 @@ export function PointEntryCreator({ return ( + setTourVisible(false)} + />
{ formApi.handleSubmit().catch((error) => { @@ -63,6 +125,7 @@ export function PointEntryCreator({ value={field.state.value ?? undefined} onBlur={field.handleBlur} onChange={(e) => field.handleChange(e.target.value)} + ref={commentFieldRef} /> )} @@ -91,6 +154,7 @@ export function PointEntryCreator({ value={field.state.value} onBlur={field.handleBlur} onChange={(num) => field.handleChange(num ?? 0)} + ref={pointsFieldRef} /> )} @@ -101,10 +165,22 @@ export function PointEntryCreator({ formApi={formApi} teamUuid={teamUuid} key={personLookupKey} + nameFieldRef={nameFieldRef} + linkblueFieldRef={linkblueFieldRef} + selectedPersonRef={selectedPersonRef} + clearButtonRef={clearButtonRef} /> - + + + +
); diff --git a/packages/portal/src/elements/forms/point-entry/create/PointEntryPersonLookup.tsx b/packages/portal/src/elements/forms/point-entry/create/PointEntryPersonLookup.tsx index d8e642fb8..7a0c783b2 100644 --- a/packages/portal/src/elements/forms/point-entry/create/PointEntryPersonLookup.tsx +++ b/packages/portal/src/elements/forms/point-entry/create/PointEntryPersonLookup.tsx @@ -2,6 +2,7 @@ import { ClearOutlined, PlusOutlined, SearchOutlined } from "@ant-design/icons"; import { useAskConfirm, useUnknownErrorHandler } from "@hooks/useAntFeedback"; import { useQueryStatusWatcher } from "@hooks/useQueryStatusWatcher"; import { AutoComplete, Button, Descriptions, Flex, Form, Input } from "antd"; +import type { LegacyRef } from "react"; import { useEffect, useState } from "react"; import { useMutation, useQuery } from "urql"; import { useDebouncedCallback } from "use-debounce"; @@ -18,9 +19,17 @@ const generalLinkblueRegex = new RegExp(/^[A-Za-z]{3,4}\d{3}$/); export function PointEntryPersonLookup({ formApi, teamUuid, + nameFieldRef, + linkblueFieldRef, + selectedPersonRef, + clearButtonRef, }: { formApi: ReturnType["formApi"]; teamUuid: string; + nameFieldRef: LegacyRef; + linkblueFieldRef: Parameters[0]["ref"]; + selectedPersonRef: LegacyRef; + clearButtonRef: Parameters[0]["ref"]; }) { const { showErrorMessage } = useUnknownErrorHandler(); // Form state (shared with parent) @@ -179,30 +188,32 @@ export function PointEntryPersonLookup({ > - {/* Three options to choose a person, autocomplete name, autocomplete linkblue, or manual entry */} - { - setSearchByNameField(value); - if (value) { - updateAutocomplete(value); - } else { - setNameAutocomplete([]); +
+ {/* Three options to choose a person, autocomplete name, autocomplete linkblue, or manual entry */} + { - field.handleChange(value); - updateSelectedPerson(); - }} - options={nameAutocomplete} - /> + onBlur={field.handleBlur} + disabled={!!field.state.value} + onChange={(value) => { + setSearchByNameField(value); + if (value) { + updateAutocomplete(value); + } else { + setNameAutocomplete([]); + } + }} + onSelect={(value) => { + field.handleChange(value); + updateSelectedPerson(); + }} + options={nameAutocomplete} + /> +
{!linkblueKnownDoesNotExist ? (