1- "use client"
2-
3- import { useState } from "react"
4- import { Button } from "@/components/ui/button"
5- import { Card , CardContent , CardHeader , CardTitle } from "@/components/ui/card"
6- import type { NodeDefinition } from "@/model/NodeDefinition"
7- import { OptionsStructureType } from "@/model/OptionsModel"
8- import { StepInfo } from "@/components/shop/create-node/StepInfo"
9- import { StepGeneralInfo } from "@/components/shop/create-node/StepGeneralInfo"
10- import { StepOptionsConfig } from "@/components/shop/create-node/StepOptionsConfig"
11- import { StepServerConfig } from "@/components/shop/create-node/StepServerConfig"
12- import { Progress } from "@/components/ui/progress"
13- import { Check , ChevronLeft , ChevronRight , Save } from "lucide-react"
14- import { useTranslations } from "next-intl" ;
15- import PreviewDynamicOptions from "@/components/shop/details/PreviewDynamicOptions" ;
16-
17- export default function CreateNodePage ( ) {
18- const t = useTranslations ( "shop.create-node" )
19- const [ currentStep , setCurrentStep ] = useState ( 1 )
20- const [ nodeDefinition , setNodeDefinition ] = useState < NodeDefinition > ( {
21- id : undefined ,
22- name : "" ,
23- icon : undefined ,
24- shortDescription : "" ,
25- markdownDocumentation : "" ,
26- executionMode : "Manual" ,
27- executionUrl : "" ,
28- optionsDefinition : {
29- title : "" ,
30- nodeId : "" ,
31- structure : [ ] ,
32- } ,
33- } )
34-
35- const updateNodeDefinition = ( updatedDefinition : NodeDefinition ) => {
36- setNodeDefinition ( updatedDefinition )
37- }
38-
39- const handleNext = ( ) => {
40- if ( currentStep < 4 ) {
41- setCurrentStep ( currentStep + 1 )
42- }
43- }
44-
45- const handlePrevious = ( ) => {
46- if ( currentStep > 1 ) {
47- setCurrentStep ( currentStep - 1 )
48- }
49- }
50-
51- const processNestedStructure = ( structure : any [ ] ) : any [ ] => {
52- return structure . map ( ( option ) => {
53- const processedOption = { ...option }
54- if ( "label" in option && option . label ) {
55- let keyString = toCamelCase ( option . label as string )
56- if (
57- option . type === OptionsStructureType . VARIABLE_NAME_INPUT ||
58- option . type === OptionsStructureType . MULTIPLE_VARIABLE_NAME_INPUT
59- ) {
60- keyString = `outputs.${ keyString } `
61- }
62- processedOption . keyString = keyString
63- } else {
64- processedOption . keyString = undefined
65- }
66-
67- if ( option . type === OptionsStructureType . ROW && "structure" in option ) {
68- processedOption . structure = processNestedStructure ( option . structure )
69- }
70-
71- if ( "options" in option && Array . isArray ( option . options ) ) {
72- processedOption . options = option . options . map ( ( opt : { dependentStructure : any [ ] } ) => ( {
73- ...opt ,
74- dependentStructure : opt . dependentStructure ? processNestedStructure ( opt . dependentStructure ) : undefined ,
75- } ) )
76- }
77-
78- return processedOption
79- } )
1+ import { cookies } from "next/headers" ;
2+ import { createClient } from "@/utils/supabase/server" ;
3+ import { redirect } from "next/navigation" ;
4+ import CreateNodePage from "@/components/shop/create-node/CreateNodePage" ;
5+
6+ export default async function CreateNode ( { params } : { params : { teamId : number } } ) {
7+
8+ const cookieStore = cookies ( )
9+ const supabase = createClient ( cookieStore )
10+ const { data : userData , error} = await supabase . auth . getUser ( )
11+ if ( error || ! userData . user || ! userData . user . id ) {
12+ redirect ( "/authenticate" )
8013 }
8114
82- const saveNodeDefinition = ( ) => {
83- const definitionWithKeyStrings = {
84- ...nodeDefinition ,
85- optionsDefinition : {
86- ...nodeDefinition . optionsDefinition ,
87- structure : processNestedStructure ( nodeDefinition . optionsDefinition . structure ) ,
88- } ,
89- }
90- console . log ( JSON . stringify ( definitionWithKeyStrings , null , 2 ) )
91- }
92-
93- return (
94- < div className = "container mx-auto py-10 px-4 max-w-6xl" >
95- < h1 className = "text-3xl font-bold mb-8 text-center" > { t ( "title" ) } </ h1 >
96-
97- < div className = "mb-10" >
98- < div className = "flex justify-between mb-3" >
99- { [ 1 , 2 , 3 , 4 ] . map ( ( step ) => (
100- < div
101- key = { step }
102- className = { `flex items-center ${ currentStep === step ? "text-primary font-medium" : "text-muted-foreground" } ` }
103- >
104- < div
105- className = { `flex items-center justify-center w-10 h-10 rounded-full mr-2
106- ${
107- currentStep > step
108- ? "bg-primary text-primary-foreground"
109- : currentStep === step
110- ? "border-2 border-primary text-primary"
111- : "border-2 border-muted-foreground text-muted-foreground"
112- } `}
113- >
114- { currentStep > step ? < Check className = "h-5 w-5" /> : step }
115- </ div >
116- < span className = "hidden sm:inline" >
117- { step === 1 && t ( "steps.information" ) }
118- { step === 2 && t ( "steps.general-details" ) }
119- { step === 3 && t ( "steps.options" ) }
120- { step === 4 && t ( "steps.server-config" ) }
121- </ span >
122- </ div >
123- ) ) }
124- </ div >
125- < Progress value = { ( currentStep / 4 ) * 100 } indicatorColor = "bg-primary" className = "h-2" />
126- </ div >
127-
128- < div className = "flex flex-row space-x-4" >
129- < Card className = "p-8 shadow-sm" >
130- { currentStep === 1 && < StepInfo onNext = { handleNext } /> }
131-
132- { currentStep === 2 && (
133- < StepGeneralInfo
134- nodeDefinition = { nodeDefinition }
135- updateNodeDefinition = { updateNodeDefinition }
136- onNext = { handleNext }
137- onPrevious = { handlePrevious }
138- />
139- ) }
140-
141- { currentStep === 3 && (
142- < StepOptionsConfig
143- nodeDefinition = { nodeDefinition }
144- updateNodeDefinition = { updateNodeDefinition }
145- onNext = { handleNext }
146- onPrevious = { handlePrevious }
147- />
148- ) }
149-
150- { currentStep === 4 && (
151- < StepServerConfig
152- nodeDefinition = { nodeDefinition }
153- updateNodeDefinition = { updateNodeDefinition }
154- onPrevious = { handlePrevious }
155- onSave = { saveNodeDefinition }
156- />
157- ) }
158- </ Card >
159-
160- { currentStep === 3 && < Card className = "pt-4 shadow-sm w-[500px]" >
161- < CardHeader >
162- < CardTitle > Preview</ CardTitle >
163- </ CardHeader >
164- < CardContent className = "overscroll-y-auto" >
165- < PreviewDynamicOptions optionsDefinition = { nodeDefinition . optionsDefinition } />
166- </ CardContent >
167- </ Card > }
168- </ div >
169-
170- < div className = "flex justify-between mt-8" >
171- { currentStep !== 1 ? < Button variant = "outline" onClick = { handlePrevious } size = "lg" className = "px-6" >
172- < ChevronLeft className = "mr-2 h-5 w-5" />
173- { t ( "navigation.previous" ) }
174- </ Button > : < div > </ div > }
175-
176- { currentStep < 4 ? (
177- < Button onClick = { handleNext } size = "lg" className = "px-6" >
178- { t ( "navigation.next" ) }
179- < ChevronRight className = "ml-2 h-5 w-5" />
180- </ Button >
181- ) : (
182- < Button onClick = { saveNodeDefinition } size = "lg" className = "px-6 bg-green-600 hover:bg-green-700" >
183- < Save className = "mr-2 h-5 w-5" />
184- { t ( "navigation.save" ) }
185- </ Button >
186- ) }
187- </ div >
188- </ div >
189- )
190- }
191-
192- // Helper function
193- function toCamelCase ( str : string ) : string {
194- return str
195- . replace ( / (?: ^ \w | [ A - Z ] | \b \w ) / g, ( word , index ) => {
196- return index === 0 ? word . toLowerCase ( ) : word . toUpperCase ( )
197- } )
198- . replace ( / \s + / g, "" )
199- }
200-
15+ return < CreateNodePage teamId = { params . teamId } userId = { userData . user . id } />
16+ }
0 commit comments