From 014dd06a90c48a64d02e912a993397994139d2c0 Mon Sep 17 00:00:00 2001 From: AbdulWahab3181 Date: Sat, 21 Sep 2024 06:02:19 +0500 Subject: [PATCH 1/2] feat(input): created test button --- .../ModalsContainer/CreateBounty/index.tsx | 98 +++++++++++++++++++ .../CreateBountyModal/index.tsx | 65 ++++++++++++ src/components/ModalsContainer/index.tsx | 5 + .../Universe/Graph/UI/NodeControls/index.tsx | 38 +++++++ src/network/fetchSourcesData/index.ts | 17 ++++ src/stores/useModalStore/index.ts | 2 + src/utils/colors/index.tsx | 1 + 7 files changed, 226 insertions(+) create mode 100644 src/components/ModalsContainer/CreateBounty/index.tsx create mode 100644 src/components/ModalsContainer/CreateBountyModal/index.tsx diff --git a/src/components/ModalsContainer/CreateBounty/index.tsx b/src/components/ModalsContainer/CreateBounty/index.tsx new file mode 100644 index 000000000..b134d1faf --- /dev/null +++ b/src/components/ModalsContainer/CreateBounty/index.tsx @@ -0,0 +1,98 @@ +import { Button } from '@mui/material' +import { FC } from 'react' +import styled from 'styled-components' +import { Flex } from '~/components/common/Flex' +import { Text } from '~/components/common/Text' +import { useFormContext } from 'react-hook-form' +import { TextInput } from '~/components/common/TextInput' +import { AutoComplete, TAutocompleteOption } from '~/components/common/AutoComplete' +import { requiredRule } from '~/constants' + +type Props = { + errMessage: string + handleClose: () => void +} + +export const CreateBounty: FC = ({ errMessage, handleClose }) => { + const { setValue, watch } = useFormContext() + + const watchBudget = watch('budget', '') + const watchNodeType = watch('nodeType', '') + + const onSelect = (val: TAutocompleteOption | null) => { + const selectedValue = val?.label || 'SecondBrain' + + setValue('nodeType', selectedValue, { shouldValidate: true }) + } + + const options = [{ label: 'SecondBrain', value: 'SecondBrain' }] + + const isDisable = !!(watchBudget && watchNodeType) + + return ( + + + Create Bounty + + + + Select Workspace + + + + + Set Budget + + + + + + + + + + + + {errMessage && {errMessage}} + + ) +} + +const StyledText = styled(Text)` + font-size: 14px; + font-weight: 600; + font-family: 'Barlow'; + margin-bottom: 6px; +` + +const StyledHeadingText = styled(Text)` + font-size: 18px; + font-weight: 600; + font-family: 'Barlow'; + margin-bottom: 6px; +` + +const StyledError = styled(Flex)` + font-size: 13px; + font-family: Barlow; + color: #ff8f80; + line-height: 0.2px; + margin-top: 12px; + padding-top: 20px; +` diff --git a/src/components/ModalsContainer/CreateBountyModal/index.tsx b/src/components/ModalsContainer/CreateBountyModal/index.tsx new file mode 100644 index 000000000..86972c834 --- /dev/null +++ b/src/components/ModalsContainer/CreateBountyModal/index.tsx @@ -0,0 +1,65 @@ +import { FormProvider, useForm } from 'react-hook-form' +import { BaseModal, ModalKind } from '~/components/Modal' +import { useModal } from '~/stores/useModalStore' +import { useSelectedNode } from '~/stores/useGraphStore' +import { postBountyData } from '~/network/fetchSourcesData' +import { useState } from 'react' +import * as React from 'react' +import { CreateBounty } from '~/components/ModalsContainer/CreateBounty' + +export type FormData = { + nodeType: string + budget: string +} & Partial<{ [k: string]: string }> + +export const CreateBountyModal = () => { + const [errMessage, setErrMessage] = useState('') + const { close } = useModal('createBounty') + const selectedNode = useSelectedNode() + const form = useForm({ mode: 'onChange' }) + const { handleSubmit, setValue } = form + + const handleClose = () => { + setValue('budget', '') + setValue('nodeType', '') + close() + } + + const onSubmit = async (data: FormData) => { + const { budget, nodeType } = data + + const nodeData = { name: nodeType } + + const payload = { + type: 'code_generation', + amount: Number(budget), + workspace_uuid: 'ck9drb84nncjnaefo090', + jwt_token: null, + ref_id: selectedNode?.ref_id as string, + node_data: nodeData, + } + + try { + await postBountyData(payload) + // eslint-disable-next-line @typescript-eslint/no-explicit-any + } catch (err: any) { + setErrMessage(err) + } finally { + setValue('budget', '') + setValue('nodeType', '') + handleClose() + } + } + + const modalKind: ModalKind = 'small' + + return ( + + +
+ + +
+
+ ) +} diff --git a/src/components/ModalsContainer/index.tsx b/src/components/ModalsContainer/index.tsx index 558eb60e4..664489b77 100644 --- a/src/components/ModalsContainer/index.tsx +++ b/src/components/ModalsContainer/index.tsx @@ -42,6 +42,10 @@ const LazyUserFeedBackModal = lazy(() => import('./UserFeedBackModal').then(({ UserFeedBackModal }) => ({ default: UserFeedBackModal })), ) +const LazyCreateBountyModal = lazy(() => + import('./CreateBountyModal').then(({ CreateBountyModal }) => ({ default: CreateBountyModal })), +) + export const ModalsContainer = () => ( <> @@ -55,5 +59,6 @@ export const ModalsContainer = () => ( + ) diff --git a/src/components/Universe/Graph/UI/NodeControls/index.tsx b/src/components/Universe/Graph/UI/NodeControls/index.tsx index 8cfc6c20f..99a5b82a6 100644 --- a/src/components/Universe/Graph/UI/NodeControls/index.tsx +++ b/src/components/Universe/Graph/UI/NodeControls/index.tsx @@ -32,6 +32,7 @@ export const NodeControls = memo(() => { const { open: openEditNodeNameModal } = useModal('editNodeName') const { open: addEdgeToNodeModal } = useModal('addEdgeToNode') const { open: mergeTopicModal } = useModal('mergeToNode') + const { open: createBountyModal } = useModal('createBounty') const [isAdmin] = useUserStore((s) => [s.isAdmin]) const [addNewNode] = useDataStore((s) => [s.addNewNode]) @@ -163,6 +164,8 @@ export const NodeControls = memo(() => { const id = open ? 'simple-popover' : undefined + const isShowCreateTestButton = !!(selectedNode && selectedNode.node_type === 'function') + return ( { ))} + {isShowCreateTestButton && ( + { + createBountyModal() + }} + > + Create Test + + )} + ` box-shadow: 0px 2px 12px rgba(0, 0, 0, 0.5); ` +const CreateTestButton = styled.div` + position: fixed; + top: 40px; + left: ${(p: ButtonProps) => -53 + p.left}px; + width: 100px; + padding: 6px; + border-radius: 4px; + display: flex; + justify-content: center; + align-items: center; + background: ${(p: ButtonProps) => (p.backgroundColor ? p.backgroundColor : '#000000bb')}; + color: ${(p: ButtonProps) => (p.fontColor ? p.fontColor : '#ffffff')}; + font-size: 14px; + font-family: Barlow; + font-weight: 600; + cursor: pointer; + + &:hover { + transform: scale(1.05); + } +` + const PopoverOption = styled(Flex).attrs({ direction: 'row', px: 12, diff --git a/src/network/fetchSourcesData/index.ts b/src/network/fetchSourcesData/index.ts index a7de57185..5d9c2adcc 100644 --- a/src/network/fetchSourcesData/index.ts +++ b/src/network/fetchSourcesData/index.ts @@ -181,6 +181,23 @@ export interface UpdateSchemaParams { } } +type BountyPayload = { + type: string + amount: number + workspace_uuid: string + jwt_token: string | null + ref_id: string + node_data: { + name: string + } +} + +export const postBountyData = async (payload: BountyPayload) => { + const response = await api.post('/bounty', JSON.stringify(payload)) + + return response +} + export const editNodeSchemaUpdate = async (ref_id: string, data: UpdateSchemaParams) => { const response = await api.put(`/schema/${ref_id}`, JSON.stringify(data)) diff --git a/src/stores/useModalStore/index.ts b/src/stores/useModalStore/index.ts index 771e9741d..5dbf17182 100644 --- a/src/stores/useModalStore/index.ts +++ b/src/stores/useModalStore/index.ts @@ -20,6 +20,7 @@ export type AvailableModals = | 'blueprintGraph' | 'changeNodeType' | 'feedback' + | 'createBounty' type ModalStore = { currentModals: Record @@ -49,6 +50,7 @@ const defaultData = { blueprintGraph: false, changeNodeType: false, feedback: false, + createBounty: false, }, } diff --git a/src/utils/colors/index.tsx b/src/utils/colors/index.tsx index 1f3cb9140..662fd0a4d 100644 --- a/src/utils/colors/index.tsx +++ b/src/utils/colors/index.tsx @@ -102,6 +102,7 @@ export const colors = { COLLAPSE_BUTTON: 'rgba(48, 51, 66, 1)', SOURCE_TABLE_LINK: 'rgba(171, 204, 254, 1)', AI_HIGHLIGHT: 'rgba(0, 123, 255, 0.1)', + createTestButton: 'rgb(178, 255, 102)', } as const export type ColorName = keyof typeof colors From 9a94cf03709e07900b037ff68c17ebc709f77a16 Mon Sep 17 00:00:00 2001 From: AbdulWahab3181 Date: Mon, 23 Sep 2024 23:31:27 +0500 Subject: [PATCH 2/2] fix(fulfill-all-required-changes): all required changes are fulfilled --- .../CreateBountyModal/Body/index.tsx | 60 +++++++++++++++++++ .../CreateBounty/index.tsx | 0 .../CreateBountyModal/index.tsx | 44 ++------------ .../Universe/Graph/UI/NodeControls/index.tsx | 47 +++++++-------- src/network/fetchSourcesData/index.ts | 17 ------ src/network/postBounty/index.ts | 18 ++++++ 6 files changed, 105 insertions(+), 81 deletions(-) create mode 100644 src/components/ModalsContainer/CreateBountyModal/Body/index.tsx rename src/components/ModalsContainer/{ => CreateBountyModal}/CreateBounty/index.tsx (100%) create mode 100644 src/network/postBounty/index.ts diff --git a/src/components/ModalsContainer/CreateBountyModal/Body/index.tsx b/src/components/ModalsContainer/CreateBountyModal/Body/index.tsx new file mode 100644 index 000000000..979689ee6 --- /dev/null +++ b/src/components/ModalsContainer/CreateBountyModal/Body/index.tsx @@ -0,0 +1,60 @@ +import { FormProvider, useForm } from 'react-hook-form' +import { useModal } from '~/stores/useModalStore' +import { useSelectedNode } from '~/stores/useGraphStore' +import { postBountyData } from '~/network/postBounty' +import { useState } from 'react' +import * as React from 'react' +import { CreateBounty } from '../CreateBounty' + +export type FormData = { + nodeType: string + budget: string +} & Partial<{ [k: string]: string }> + +export const Body = () => { + const [errMessage, setErrMessage] = useState('') + const { close } = useModal('createBounty') + const selectedNode = useSelectedNode() + const form = useForm({ mode: 'onChange' }) + const { handleSubmit, setValue } = form + + const handleClose = () => { + setValue('budget', '') + setValue('nodeType', '') + close() + } + + const onSubmit = async (data: FormData) => { + const { budget, nodeType } = data + + const nodeData = { name: nodeType } + + const payload = { + type: 'code_generation', + amount: Number(budget), + workspace_uuid: 'ck9drb84nncjnaefo090', + jwt_token: null, + ref_id: selectedNode?.ref_id as string, + node_data: nodeData, + } + + try { + await postBountyData(payload) + // eslint-disable-next-line @typescript-eslint/no-explicit-any + } catch (err: any) { + setErrMessage(err) + } finally { + setValue('budget', '') + setValue('nodeType', '') + handleClose() + } + } + + return ( + +
+ + +
+ ) +} diff --git a/src/components/ModalsContainer/CreateBounty/index.tsx b/src/components/ModalsContainer/CreateBountyModal/CreateBounty/index.tsx similarity index 100% rename from src/components/ModalsContainer/CreateBounty/index.tsx rename to src/components/ModalsContainer/CreateBountyModal/CreateBounty/index.tsx diff --git a/src/components/ModalsContainer/CreateBountyModal/index.tsx b/src/components/ModalsContainer/CreateBountyModal/index.tsx index 86972c834..d35bec38f 100644 --- a/src/components/ModalsContainer/CreateBountyModal/index.tsx +++ b/src/components/ModalsContainer/CreateBountyModal/index.tsx @@ -1,11 +1,9 @@ -import { FormProvider, useForm } from 'react-hook-form' +import { useForm } from 'react-hook-form' import { BaseModal, ModalKind } from '~/components/Modal' import { useModal } from '~/stores/useModalStore' -import { useSelectedNode } from '~/stores/useGraphStore' -import { postBountyData } from '~/network/fetchSourcesData' -import { useState } from 'react' import * as React from 'react' -import { CreateBounty } from '~/components/ModalsContainer/CreateBounty' + +import { Body } from '~/components/ModalsContainer/CreateBountyModal/Body' export type FormData = { nodeType: string @@ -13,11 +11,9 @@ export type FormData = { } & Partial<{ [k: string]: string }> export const CreateBountyModal = () => { - const [errMessage, setErrMessage] = useState('') const { close } = useModal('createBounty') - const selectedNode = useSelectedNode() const form = useForm({ mode: 'onChange' }) - const { handleSubmit, setValue } = form + const { setValue } = form const handleClose = () => { setValue('budget', '') @@ -25,41 +21,11 @@ export const CreateBountyModal = () => { close() } - const onSubmit = async (data: FormData) => { - const { budget, nodeType } = data - - const nodeData = { name: nodeType } - - const payload = { - type: 'code_generation', - amount: Number(budget), - workspace_uuid: 'ck9drb84nncjnaefo090', - jwt_token: null, - ref_id: selectedNode?.ref_id as string, - node_data: nodeData, - } - - try { - await postBountyData(payload) - // eslint-disable-next-line @typescript-eslint/no-explicit-any - } catch (err: any) { - setErrMessage(err) - } finally { - setValue('budget', '') - setValue('nodeType', '') - handleClose() - } - } - const modalKind: ModalKind = 'small' return ( - -
- - -
+
) } diff --git a/src/components/Universe/Graph/UI/NodeControls/index.tsx b/src/components/Universe/Graph/UI/NodeControls/index.tsx index 99a5b82a6..ee53f93da 100644 --- a/src/components/Universe/Graph/UI/NodeControls/index.tsx +++ b/src/components/Universe/Graph/UI/NodeControls/index.tsx @@ -164,7 +164,7 @@ export const NodeControls = memo(() => { const id = open ? 'simple-popover' : undefined - const isShowCreateTestButton = !!(selectedNode && selectedNode.node_type === 'function') + const isShowCreateTestButton = !!(selectedNode && selectedNode?.node_type?.toLowerCase() === 'function') return ( @@ -199,8 +199,6 @@ export const NodeControls = memo(() => { {isShowCreateTestButton && ( { createBountyModal() @@ -271,28 +269,6 @@ const IconButton = styled.div` box-shadow: 0px 2px 12px rgba(0, 0, 0, 0.5); ` -const CreateTestButton = styled.div` - position: fixed; - top: 40px; - left: ${(p: ButtonProps) => -53 + p.left}px; - width: 100px; - padding: 6px; - border-radius: 4px; - display: flex; - justify-content: center; - align-items: center; - background: ${(p: ButtonProps) => (p.backgroundColor ? p.backgroundColor : '#000000bb')}; - color: ${(p: ButtonProps) => (p.fontColor ? p.fontColor : '#ffffff')}; - font-size: 14px; - font-family: Barlow; - font-weight: 600; - cursor: pointer; - - &:hover { - transform: scale(1.05); - } -` - const PopoverOption = styled(Flex).attrs({ direction: 'row', px: 12, @@ -327,3 +303,24 @@ const PopoverWrapper = styled(Popover)` font-weight: 500; } ` + +const CreateTestButton = styled.div` + position: fixed; + top: 40px; + left: ${(p: ButtonProps) => -53 + p.left}px; + width: 100px; + padding: 6px; + border-radius: 4px; + display: flex; + justify-content: center; + align-items: center; + background: ${colors.createTestButton}; + color: ${colors.black}; + font-size: 14px; + font-family: Barlow; + font-weight: 600; + cursor: pointer; + &:hover { + transform: scale(1.05); + } +` diff --git a/src/network/fetchSourcesData/index.ts b/src/network/fetchSourcesData/index.ts index 5d9c2adcc..a7de57185 100644 --- a/src/network/fetchSourcesData/index.ts +++ b/src/network/fetchSourcesData/index.ts @@ -181,23 +181,6 @@ export interface UpdateSchemaParams { } } -type BountyPayload = { - type: string - amount: number - workspace_uuid: string - jwt_token: string | null - ref_id: string - node_data: { - name: string - } -} - -export const postBountyData = async (payload: BountyPayload) => { - const response = await api.post('/bounty', JSON.stringify(payload)) - - return response -} - export const editNodeSchemaUpdate = async (ref_id: string, data: UpdateSchemaParams) => { const response = await api.put(`/schema/${ref_id}`, JSON.stringify(data)) diff --git a/src/network/postBounty/index.ts b/src/network/postBounty/index.ts new file mode 100644 index 000000000..ce8d5b8c7 --- /dev/null +++ b/src/network/postBounty/index.ts @@ -0,0 +1,18 @@ +import { api } from '~/network/api' + +type BountyPayload = { + type: string + amount: number + workspace_uuid: string + jwt_token: string | null + ref_id: string + node_data: { + name: string + } +} + +export const postBountyData = async (payload: BountyPayload) => { + const response = await api.post('/bounty', JSON.stringify(payload)) + + return response +}