@learnpack/learnpack 5.0.168 → 5.0.176

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (36) hide show
  1. package/README.md +13 -13
  2. package/lib/commands/serve.js +42 -2
  3. package/{src/creatorDist/assets/index-C_YTggyk.css → lib/creatorDist/assets/index-CrWESWmj.css} +43 -11
  4. package/lib/creatorDist/assets/index-T7usmMYO.js +32991 -0
  5. package/lib/creatorDist/index.html +2 -2
  6. package/lib/utils/api.d.ts +1 -1
  7. package/lib/utils/api.js +2 -1
  8. package/lib/utils/readDocuments.d.ts +0 -0
  9. package/lib/utils/readDocuments.js +1 -0
  10. package/oclif.manifest.json +1 -1
  11. package/package.json +3 -1
  12. package/src/commands/serve.ts +56 -2
  13. package/src/creator/src/App.tsx +51 -34
  14. package/src/creator/src/components/ConsumablesManager.tsx +1 -0
  15. package/src/creator/src/components/FileUploader.tsx +64 -52
  16. package/src/creator/src/components/Login.tsx +172 -82
  17. package/src/creator/src/components/ResumeCourseModal.tsx +38 -0
  18. package/src/creator/src/components/StepWizard.tsx +12 -10
  19. package/src/creator/src/components/TurnstileChallenge.tsx +2 -7
  20. package/src/creator/src/components/syllabus/ContentIndex.tsx +1 -0
  21. package/src/creator/src/components/syllabus/SyllabusEditor.tsx +63 -29
  22. package/src/creator/src/utils/constants.ts +2 -1
  23. package/src/creator/src/utils/lib.ts +55 -0
  24. package/src/creator/src/utils/rigo.ts +12 -5
  25. package/src/creator/src/utils/store.ts +22 -1
  26. package/{lib/creatorDist/assets/index-C_YTggyk.css → src/creatorDist/assets/index-CrWESWmj.css} +43 -11
  27. package/src/creatorDist/assets/index-T7usmMYO.js +32991 -0
  28. package/src/creatorDist/index.html +2 -2
  29. package/src/ui/_app/app.js +286 -286
  30. package/src/ui/app.tar.gz +0 -0
  31. package/src/utils/api.ts +2 -1
  32. package/src/utils/readDocuments.ts +0 -0
  33. package/lib/creatorDist/assets/index-4XkqESUr.js +0 -83719
  34. package/lib/creatorDist/assets/pdf.worker-DSVOJ9H9.js +0 -56037
  35. package/src/creatorDist/assets/index-4XkqESUr.js +0 -83719
  36. package/src/creatorDist/assets/pdf.worker-DSVOJ9H9.js +0 -56037
@@ -4,61 +4,88 @@ import { SVGS } from "../assets/svgs"
4
4
  import toast from "react-hot-toast"
5
5
  import useStore from "../utils/store"
6
6
  import { useShallow } from "zustand/react/shallow"
7
- import { login4Geeks } from "../utils/lib"
7
+ import { login4Geeks, registerUserWithFormData } from "../utils/lib"
8
8
 
9
9
  export default function Login({ onFinish }: { onFinish: () => void }) {
10
+ // Login states
10
11
  const [email, setEmail] = useState("")
11
12
  const [password, setPassword] = useState("")
12
13
  const [isLoading, setIsLoading] = useState(false)
13
14
  const [showForm, setShowForm] = useState(false)
14
- const planToRedirect = useStore((state) => state.planToRedirect)
15
-
15
+ // Signup states
16
+ const [showSignup, setShowSignup] = useState(false)
17
+ const [signupData, setSignupData] = useState({
18
+ firstName: "",
19
+ lastName: "",
20
+ email: "",
21
+ })
22
+ // const planToRedirect = useStore((state) => state.planToRedirect)
16
23
  const { setAuth } = useStore(
17
24
  useShallow((state) => ({ setAuth: state.setAuth }))
18
25
  )
19
26
 
20
- const login = async (e: React.FormEvent) => {
27
+ // Login handler
28
+ const login = async (e: React.FormEvent<HTMLFormElement>) => {
21
29
  e.preventDefault()
22
30
  setIsLoading(true)
23
31
  const tid = toast.loading("Logging in…")
24
-
25
32
  if (!email || !password) {
26
33
  setIsLoading(false)
27
34
  toast.error("Please fill all fields", { id: tid })
28
35
  return
29
36
  }
30
-
31
37
  const resp = await login4Geeks({ email, password })
32
38
  if (!resp) {
33
39
  setIsLoading(false)
34
40
  toast.error("Invalid credentials", { id: tid })
35
41
  return
36
42
  }
37
-
38
43
  toast.success("Logged in successfully", { id: tid })
39
44
  setAuth({
40
45
  bcToken: resp.token,
41
46
  userId: resp.user.id,
42
47
  rigoToken: resp.rigobot.key,
43
48
  user: resp.user,
49
+ publicToken: "",
44
50
  })
45
51
  setIsLoading(false)
46
52
  onFinish()
47
53
  }
48
54
 
55
+ // Signup handler
56
+ const handleSignup = async (e: React.FormEvent<HTMLFormElement>) => {
57
+ e.preventDefault()
58
+ setIsLoading(true)
59
+ const tid = toast.loading("Creating account…")
60
+ const { firstName, lastName, email } = signupData
61
+ if (!firstName || !lastName || !email) {
62
+ setIsLoading(false)
63
+ toast.error("Please fill all fields", { id: tid })
64
+ return
65
+ }
66
+ try {
67
+ await registerUserWithFormData(firstName, lastName, email)
68
+ toast.success("Account created! Check your email.", { id: tid })
69
+ setShowSignup(false)
70
+ setShowForm(true)
71
+ setEmail(email)
72
+ } catch (err) {
73
+ toast.error("Registration failed. Try again.", { id: tid })
74
+ } finally {
75
+ setIsLoading(false)
76
+ }
77
+ }
78
+
49
79
  function stringToBase64(str: string) {
50
80
  return btoa(unescape(encodeURIComponent(str)))
51
81
  }
52
-
53
82
  function getCurrentUrlWithQueryParams() {
54
83
  return window.location.href
55
84
  }
56
-
57
85
  const redirectGithub = () => {
58
86
  const url = stringToBase64(getCurrentUrlWithQueryParams())
59
87
  window.location.href = `${BREATHECODE_HOST}/v1/auth/github/?url=${url}`
60
88
  }
61
-
62
89
  const redirectGoogle = () => {
63
90
  const url = stringToBase64(getCurrentUrlWithQueryParams())
64
91
  window.location.href = `${BREATHECODE_HOST}/v1/auth/google?url=${url}`
@@ -73,89 +100,152 @@ export default function Login({ onFinish }: { onFinish: () => void }) {
73
100
  className="bg-white p-8 rounded-xl shadow-md max-w-sm w-full"
74
101
  onClick={(e) => e.stopPropagation()}
75
102
  >
76
- <p className="mb-4 text-center text-gray-700">
77
- You need to have a 4Geeks account with a creator plan to create a
78
- tutorial.
79
- </p>
80
- <button
81
- onClick={redirectGithub}
82
- className="w-full border border-gray-300 py-2 rounded-md font-semibold flex items-center justify-center gap-2 mb-4 cursor-pointer"
83
- >
84
- {SVGS.github} LOGIN WITH GITHUB
85
- </button>
86
- <button
87
- onClick={redirectGoogle}
88
- className="w-full border border-gray-300 py-2 rounded-md font-semibold flex items-center justify-center gap-2 mb-4 cursor-pointer"
89
- >
90
- {SVGS.google} LOGIN WITH GOOGLE
91
- </button>
92
-
93
- <div className="flex items-center mb-4">
94
- <hr className="flex-grow border-gray-300" />
95
- <span className="mx-2 text-gray-400 text-sm">or</span>
96
- <hr className="flex-grow border-gray-300" />
97
- </div>
98
-
99
- {showForm ? (
100
- <form className="space-y-3" onSubmit={login}>
101
- <input
102
- type="email"
103
- placeholder="Email"
104
- className="w-full border border-gray-300 px-3 py-2 rounded-md"
105
- onChange={(e) => setEmail(e.target.value)}
106
- />
107
- <input
108
- type="password"
109
- placeholder="Password"
110
- className="w-full border border-gray-300 px-3 py-2 rounded-md"
111
- onChange={(e) => setPassword(e.target.value)}
112
- />
113
- <div className="flex gap-2 mt-4">
103
+ {showSignup ? (
104
+ <>
105
+ <h2 className="mb-4 text-xl font-semibold text-center">
106
+ Create your account
107
+ </h2>
108
+ <form className="space-y-3" onSubmit={handleSignup}>
109
+ <input
110
+ type="text"
111
+ placeholder="First name"
112
+ className="w-full border border-gray-300 px-3 py-2 rounded-md"
113
+ value={signupData.firstName}
114
+ onChange={(e) =>
115
+ setSignupData({ ...signupData, firstName: e.target.value })
116
+ }
117
+ />
118
+ <input
119
+ type="text"
120
+ placeholder="Last name"
121
+ className="w-full border border-gray-300 px-3 py-2 rounded-md"
122
+ value={signupData.lastName}
123
+ onChange={(e) =>
124
+ setSignupData({ ...signupData, lastName: e.target.value })
125
+ }
126
+ />
127
+ <input
128
+ type="email"
129
+ placeholder="Email"
130
+ className="w-full border border-gray-300 px-3 py-2 rounded-md"
131
+ value={signupData.email}
132
+ onChange={(e) =>
133
+ setSignupData({ ...signupData, email: e.target.value })
134
+ }
135
+ />
114
136
  <button
115
137
  type="submit"
116
- className="flex-1 bg-sky-500 text-white py-2 rounded-md font-semibold cursor-pointer"
138
+ className="w-full bg-blue-600 text-white py-2 rounded-md font-semibold cursor-pointer"
139
+ disabled={isLoading}
117
140
  >
118
- {isLoading ? "Logging in..." : "Log in"}
141
+ {isLoading ? "Creating..." : "Sign up"}
119
142
  </button>
143
+ </form>
144
+ <div className="mt-4 text-sm text-center">
145
+ Already have an account?{" "}
120
146
  <button
121
- type="button"
122
- onClick={() => setShowForm(false)}
123
- className="flex-1 border border-sky-500 text-sky-600 py-2 rounded-md font-semibold cursor-pointer"
147
+ className="text-blue-600 font-medium"
148
+ onClick={() => {
149
+ setShowSignup(false)
150
+ setShowForm(true)
151
+ }}
124
152
  >
125
- Skip
153
+ Log in here
126
154
  </button>
127
155
  </div>
128
- <div className="text-sm text-gray-600 mt-2">
129
- Forgot your password?{" "}
130
- <a
131
- href={`${BREATHECODE_HOST}/v1/auth/password/reset?url=${getCurrentUrlWithQueryParams()}`}
132
- className="text-sky-600 font-medium"
156
+ </>
157
+ ) : (
158
+ <>
159
+ <p className="mb-4 text-center text-gray-700">
160
+ You need to have a 4Geeks account with a creator plan to create a
161
+ tutorial.
162
+ </p>
163
+ <button
164
+ onClick={redirectGithub}
165
+ className="w-full border border-gray-300 py-2 rounded-md font-semibold flex items-center justify-center gap-2 mb-4 cursor-pointer"
166
+ >
167
+ {SVGS.github} LOGIN WITH GITHUB
168
+ </button>
169
+ <button
170
+ onClick={redirectGoogle}
171
+ className="w-full border border-gray-300 py-2 rounded-md font-semibold flex items-center justify-center gap-2 mb-4 cursor-pointer"
172
+ >
173
+ {SVGS.google} LOGIN WITH GOOGLE
174
+ </button>
175
+ <div className="flex items-center mb-4">
176
+ <hr className="flex-grow border-gray-300" />
177
+ <span className="mx-2 text-gray-400 text-sm">or</span>
178
+ <hr className="flex-grow border-gray-300" />
179
+ </div>
180
+ {showForm ? (
181
+ <form className="space-y-3" onSubmit={login}>
182
+ <input
183
+ type="email"
184
+ placeholder="Email"
185
+ className="w-full border border-gray-300 px-3 py-2 rounded-md"
186
+ value={email}
187
+ onChange={(e) => setEmail(e.target.value)}
188
+ />
189
+ <input
190
+ type="password"
191
+ placeholder="Password"
192
+ className="w-full border border-gray-300 px-3 py-2 rounded-md"
193
+ value={password}
194
+ onChange={(e) => setPassword(e.target.value)}
195
+ />
196
+ <div className="flex gap-2 mt-4">
197
+ <button
198
+ type="submit"
199
+ className="flex-1 bg-blue-500 text-white py-2 rounded-md font-semibold cursor-pointer"
200
+ >
201
+ {isLoading ? "Logging in..." : "Log in"}
202
+ </button>
203
+ <button
204
+ type="button"
205
+ onClick={() => setShowForm(false)}
206
+ className="flex-1 border border-blue-500 text-blue-600 py-2 rounded-md font-semibold cursor-pointer"
207
+ >
208
+ Skip
209
+ </button>
210
+ </div>
211
+ <div className="text-sm text-gray-600 mt-2">
212
+ Forgot your password?{" "}
213
+ <a
214
+ href={`${BREATHECODE_HOST}/v1/auth/password/reset?url=${getCurrentUrlWithQueryParams()}`}
215
+ className="text-blue-600 font-medium"
216
+ >
217
+ Recover it here.
218
+ </a>
219
+ </div>
220
+ </form>
221
+ ) : (
222
+ <button
223
+ onClick={() => setShowForm(true)}
224
+ className="w-full bg-blue-600 text-white py-2 rounded-md font-semibold cursor-pointer"
133
225
  >
134
- Recover it here.
135
- </a>
226
+ Login with Email
227
+ </button>
228
+ )}
229
+ <div className="flex justify-between items-center mt-4">
230
+ <div className="bg-blue-50 text-sm p-2 rounded text-left">
231
+ <p className="text-gray-700 m-0">You don't have an account?</p>
232
+ {/* <button
233
+ className="text-blue-600 font-medium cursor-pointer"
234
+ onClick={() => setShowSignup(true)}
235
+ >
236
+ Register here.
237
+ </button> */}
238
+ <a
239
+ href={`https://www.learnpack.co/register`}
240
+ target="_blank"
241
+ className="text-blue-600 font-medium"
242
+ >
243
+ Register here.
244
+ </a>
245
+ </div>
136
246
  </div>
137
- </form>
138
- ) : (
139
- <button
140
- onClick={() => setShowForm(true)}
141
- className="w-full bg-blue-600 text-white py-2 rounded-md font-semibold cursor-pointer"
142
- >
143
- Login with Email
144
- </button>
247
+ </>
145
248
  )}
146
-
147
- <div className="flex justify-between items-center mt-4">
148
- <div className="bg-blue-50 text-sm p-2 rounded text-left">
149
- <p className="text-gray-700 m-0">You don't have an account?</p>
150
- <a
151
- href={`https://4geeks.com/checkout?plan=${planToRedirect}`}
152
- target="_blank"
153
- className="text-blue-600 font-medium"
154
- >
155
- Register here.
156
- </a>
157
- </div>
158
- </div>
159
249
  </div>
160
250
  </div>
161
251
  )
@@ -0,0 +1,38 @@
1
+ interface ResumeCourseModalProps {
2
+ onContinue: () => void
3
+ onStartOver: () => void
4
+ }
5
+
6
+ export default function ResumeCourseModal({
7
+ onContinue,
8
+ onStartOver,
9
+ }: ResumeCourseModalProps) {
10
+ return (
11
+ <div className="fixed inset-0 bg-black/60 flex items-center justify-center z-50">
12
+ <div className="bg-white shadow-xl rounded-lg p-8 max-w-md w-full animate-fade-in">
13
+ <h2 className="text-xl font-bold text-gray-800 mb-3 text-center">
14
+ You have an unfinished course
15
+ </h2>
16
+ <p className="text-gray-600 mb-6 text-center">
17
+ You didn't finish creating your previous course.
18
+ <br />
19
+ What would you like to do?
20
+ </p>
21
+ <div className="flex flex-col gap-4">
22
+ <button
23
+ onClick={onContinue}
24
+ className="w-full bg-blue-600 hover:bg-blue-700 text-white py-2 rounded-md font-semibold transition cursor-pointer"
25
+ >
26
+ Continue previous course
27
+ </button>
28
+ <button
29
+ onClick={onStartOver}
30
+ className="w-full border border-blue-600 text-blue-700 py-2 rounded-md font-semibold hover:bg-blue-50 transition cursor-pointer"
31
+ >
32
+ Erase previous answers and start a new course
33
+ </button>
34
+ </div>
35
+ </div>
36
+ </div>
37
+ )
38
+ }
@@ -17,6 +17,7 @@ type Props = {
17
17
  formState: any
18
18
  setFormState: (formState: any) => void
19
19
  onFinish: () => void
20
+ hideLastButton?: boolean
20
21
  }
21
22
 
22
23
  const StepWizard: React.FC<Props> = ({
@@ -24,6 +25,7 @@ const StepWizard: React.FC<Props> = ({
24
25
  formState,
25
26
  setFormState,
26
27
  onFinish,
28
+ hideLastButton = false,
27
29
  }) => {
28
30
  const currentStep = formState.currentStep
29
31
  const index = steps.findIndex((step) => step.slug === currentStep)
@@ -48,8 +50,6 @@ const StepWizard: React.FC<Props> = ({
48
50
  setFormState({ ...formState, currentStep: steps[index - 1].slug })
49
51
  }
50
52
 
51
- console.log(index, totalSteps, steps)
52
-
53
53
  return (
54
54
  <div className="min-h-screen flex flex-col items-center justify-center text-center px-4">
55
55
  <div className=" rounded-xl p-8 w-full max-w-xl">
@@ -99,14 +99,16 @@ const StepWizard: React.FC<Props> = ({
99
99
  >
100
100
  ⬅ Back
101
101
  </button>
102
- <button
103
- onClick={index === totalSteps - 1 ? onFinish : goNext}
104
- className={`text-sm text-blue-600 hover:text-blue-800 cursor-pointer disabled:opacity-40 disabled:cursor-not-allowed p-2 rounded-md ${
105
- index === totalSteps - 1 ? "bg-blue-600 text-white" : ""
106
- }`}
107
- >
108
- {index === totalSteps - 1 ? "Finish 🚀" : "Next ➡"}
109
- </button>
102
+ {!(hideLastButton && index === totalSteps - 1) && (
103
+ <button
104
+ onClick={index === totalSteps - 1 ? onFinish : goNext}
105
+ className={`text-sm text-blue-600 hover:text-blue-800 cursor-pointer disabled:opacity-40 disabled:cursor-not-allowed p-2 rounded-md ${
106
+ index === totalSteps - 1 ? "bg-blue-600 text-white" : ""
107
+ }`}
108
+ >
109
+ {index === totalSteps - 1 ? "Finish 🚀" : "Next ➡"}
110
+ </button>
111
+ )}
110
112
  </div>
111
113
  </div>
112
114
  </div>
@@ -1,6 +1,6 @@
1
1
  // components/TurnstileChallenge.tsx
2
2
  import { useEffect, useRef, useState } from "react"
3
- import toast from "react-hot-toast"
3
+ // import toast from "react-hot-toast"
4
4
 
5
5
  interface TurnstileChallengeProps {
6
6
  siteKey: string
@@ -34,8 +34,6 @@ const TurnstileChallenge = ({
34
34
  const id = window.turnstile.render(`#${containerId}`, {
35
35
  sitekey: siteKey,
36
36
  callback: (token: string) => {
37
- console.log("token to send", token)
38
-
39
37
  onSuccess(token)
40
38
  },
41
39
  "error-callback": () => {
@@ -43,7 +41,7 @@ const TurnstileChallenge = ({
43
41
  },
44
42
  "refresh-callback": () => {
45
43
  console.log("refresh callback CALLEd")
46
- toast.error("Refresh callback called")
44
+ // toast.error("Refresh callback called")
47
45
  },
48
46
  })
49
47
 
@@ -61,11 +59,8 @@ const TurnstileChallenge = ({
61
59
  return () => clearInterval(interval)
62
60
  }, [siteKey, autoStart, onSuccess, onError])
63
61
 
64
-
65
62
  return (
66
-
67
63
  <div className="">
68
-
69
64
  <div id={containerId} data-refresh-timeout="auto" />
70
65
  {!ready && <p className="">...</p>}
71
66
  {/* <button onClick={reset}>RESET</button> */}
@@ -126,6 +126,7 @@ export const GenerateButton = ({
126
126
  bcToken: "",
127
127
  userId: "",
128
128
  user: null,
129
+ publicToken: "",
129
130
  })
130
131
  openLogin()
131
132
  }}
@@ -1,10 +1,10 @@
1
1
  import React, { useState, useEffect } from "react"
2
2
  import { useShallow } from "zustand/react/shallow"
3
3
  import useStore from "../../utils/store"
4
- import { interactiveCreation } from "../../utils/rigo"
4
+ import { publicInteractiveCreation } from "../../utils/rigo"
5
5
  import {
6
6
  parseLesson,
7
- useConsumableCall,
7
+ // useConsumableCall,
8
8
  validateTokens,
9
9
  checkParams,
10
10
  loginWithToken,
@@ -28,6 +28,27 @@ import { RIGO_FLOAT_GIT } from "../../utils/constants"
28
28
 
29
29
  const SyllabusEditor: React.FC = () => {
30
30
  const navigate = useNavigate()
31
+
32
+ const {
33
+ history,
34
+ auth,
35
+ setAuth,
36
+ push,
37
+ uploadedFiles,
38
+ cleanHistory,
39
+ formState,
40
+ } = useStore(
41
+ useShallow((state) => ({
42
+ history: state.history,
43
+ auth: state.auth,
44
+ setAuth: state.setAuth,
45
+ push: state.push,
46
+ uploadedFiles: state.uploadedFiles,
47
+ cleanHistory: state.cleanHistory,
48
+ formState: state.formState,
49
+ }))
50
+ )
51
+
31
52
  const [messages, setMessages] = useState<TMessage[]>([
32
53
  {
33
54
  type: "assistant",
@@ -43,26 +64,35 @@ const SyllabusEditor: React.FC = () => {
43
64
  const [showLoginModal, setShowLoginModal] = useState(false)
44
65
  const [isThinking, setIsThinking] = useState(false)
45
66
 
46
- const { history, auth, setAuth, push, uploadedFiles, cleanHistory } =
47
- useStore(
48
- useShallow((state) => ({
49
- history: state.history,
50
- auth: state.auth,
51
- setAuth: state.setAuth,
52
- push: state.push,
53
- uploadedFiles: state.uploadedFiles,
54
- cleanHistory: state.cleanHistory,
55
- }))
56
- )
57
-
58
67
  const syllabus = history[history.length - 1]
59
68
 
60
69
  useEffect(() => {
61
70
  if (!syllabus) {
62
71
  navigate("/creator", { replace: true })
72
+ } else {
63
73
  }
64
74
  }, [syllabus, navigate])
65
75
 
76
+ useEffect(() => {
77
+ console.log(formState.description, "DESCRIPTION")
78
+
79
+ if (formState.description) {
80
+ setMessages((prevMessages) => {
81
+ if (prevMessages.length === 0 || prevMessages[0].type !== "user") {
82
+ // Si no hay mensajes o el primero no es de usuario, lo agrego al inicio
83
+ return [
84
+ { type: "user", content: formState.description },
85
+ ...prevMessages,
86
+ ]
87
+ } else {
88
+ // Si el primero ya es de usuario, lo reemplazo y mantengo el resto
89
+ const [, ...rest] = prevMessages
90
+ return [{ type: "user", content: formState.description }, ...rest]
91
+ }
92
+ })
93
+ }
94
+ }, [formState.description])
95
+
66
96
  useEffect(() => {
67
97
  ;(async () => {
68
98
  const { token } = checkParams(["token"])
@@ -74,6 +104,7 @@ const SyllabusEditor: React.FC = () => {
74
104
  userId: user.id,
75
105
  rigoToken: user.rigobot.key,
76
106
  user,
107
+ publicToken: "",
77
108
  })
78
109
  }
79
110
  }
@@ -108,19 +139,22 @@ const SyllabusEditor: React.FC = () => {
108
139
  { type: "assistant", content: "" },
109
140
  ])
110
141
 
111
- const res = await interactiveCreation({
112
- courseInfo: `${JSON.stringify(syllabus.courseInfo)}
142
+ const res = await publicInteractiveCreation(
143
+ {
144
+ courseInfo: `${JSON.stringify(syllabus.courseInfo)}
113
145
  ${
114
146
  uploadedFiles.length > 0 &&
115
147
  "The user has uploaded files, take them in consideration while generating the course structure." +
116
148
  JSON.stringify(uploadedFiles)
117
149
  }
118
150
  `,
119
- prevInteractions:
120
- messages
121
- .map((message) => `${message.type}: ${message.content}`)
122
- .join("\n") + `\nUSER: ${prompt}`,
123
- })
151
+ prevInteractions:
152
+ messages
153
+ .map((message) => `${message.type}: ${message.content}`)
154
+ .join("\n") + `\nUSER: ${prompt}`,
155
+ },
156
+ auth.publicToken
157
+ )
124
158
 
125
159
  const lessons: Lesson[] = res.parsed.listOfSteps.map((step: any) =>
126
160
  parseLesson(step, syllabus.lessons)
@@ -166,14 +200,14 @@ const SyllabusEditor: React.FC = () => {
166
200
  setShowLoginModal(true)
167
201
  return
168
202
  }
169
- const success = await useConsumableCall(
170
- auth.bcToken,
171
- "ai-course-generation"
172
- )
173
- if (!success) {
174
- toast.error("You don't have enough credits to generate a course!")
175
- return
176
- }
203
+ // const success = await useConsumableCall(
204
+ // auth.bcToken,
205
+ // "ai-course-generation"
206
+ // )
207
+ // if (!success) {
208
+ // toast.error("You don't have enough credits to generate a course!")
209
+ // return
210
+ // }
177
211
  syllabus.sources = uploadedFiles
178
212
  console.log(syllabus)
179
213
 
@@ -1,4 +1,5 @@
1
- export const RIGOBOT_HOST = "https://rigobot.herokuapp.com"
1
+ // export const RIGOBOT_HOST = "https://rigobot.herokuapp.com"
2
+ export const RIGOBOT_HOST = "https://rigobot-test-cca7d841c9d8.herokuapp.com"
2
3
  export const BREATHECODE_HOST = "https://breathecode.herokuapp.com"
3
4
 
4
5
  export const RIGO_FLOAT_GIT =
@@ -364,3 +364,58 @@ export const reWriteTitle = async (title: string, token: string) => {
364
364
  return `${title} ${Math.random().toString(36).substring(2, 6)}`
365
365
  }
366
366
  }
367
+
368
+ export async function registerUserWithFormData(
369
+ firstName: string,
370
+ lastName: string,
371
+ email: string
372
+ ): Promise<any> {
373
+ const formData = new FormData()
374
+ formData.append("1_first_name", firstName)
375
+ formData.append("1_last_name", lastName)
376
+ formData.append("1_email", email)
377
+
378
+ // Puedes modificar este objeto para agregar info real de tracking si la tienes.
379
+ const conversionArray = [
380
+ "$K1",
381
+ {
382
+ user_agent: navigator.userAgent,
383
+ landing_url: "www.learnpack.co/my-tutorials",
384
+ conversion_url: "app.learnpack.co/login",
385
+ translations: "$undefined",
386
+ utm_placement: "$undefined",
387
+ utm_referrer: "$undefined",
388
+ utm_medium: "$undefined",
389
+ utm_source: "$undefined",
390
+ utm_term: "$undefined",
391
+ utm_content: "$undefined",
392
+ utm_campaign: "$undefined",
393
+ internal_cta_placement: "$undefined",
394
+ internal_cta_content: "$undefined",
395
+ internal_cta_campaign: "$undefined",
396
+ },
397
+ ]
398
+
399
+ formData.append("0", JSON.stringify(conversionArray))
400
+
401
+ try {
402
+ const response = await axios.post(
403
+ "https://www.learnpack.co/register",
404
+ formData,
405
+ {
406
+ headers: {
407
+ "Content-Type": "multipart/form-data",
408
+ },
409
+ }
410
+ )
411
+ return response.data
412
+ } catch (error: any) {
413
+ // Manejo de errores básico
414
+ console.error(error, "ERROR REGISTERING IN LEARNPACK")
415
+ return {
416
+ success: false,
417
+ message: error?.response?.data?.detail || "Registration error",
418
+ data: error?.response?.data || null,
419
+ }
420
+ }
421
+ }