@learnpack/learnpack 5.0.65 → 5.0.67

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 (43) hide show
  1. package/README.md +13 -13
  2. package/lib/commands/serve.js +15 -15
  3. package/{src/creatorDist/assets/index-tt9JBVY0.css → lib/creatorDist/assets/index-t6ma_gVm.css} +118 -20
  4. package/lib/creatorDist/assets/index-tZYXMzIW.js +75067 -0
  5. package/lib/creatorDist/assets/pdf.worker-DSVOJ9H9.js +56037 -0
  6. package/lib/creatorDist/index.html +10 -5
  7. package/lib/creatorDist/logo-192 copy.png +0 -0
  8. package/lib/creatorDist/logo.png +0 -0
  9. package/oclif.manifest.json +1 -1
  10. package/package.json +1 -1
  11. package/src/commands/serve.ts +24 -20
  12. package/src/creator/index.html +8 -3
  13. package/src/creator/package-lock.json +394 -0
  14. package/src/creator/package.json +3 -0
  15. package/src/creator/public/logo-192 copy.png +0 -0
  16. package/src/creator/public/logo.png +0 -0
  17. package/src/creator/src/App.tsx +30 -4
  18. package/src/creator/src/assets/svgs.tsx +138 -0
  19. package/src/creator/src/components/FileUploader.tsx +91 -0
  20. package/src/creator/src/components/LessonItem.tsx +70 -0
  21. package/src/creator/src/components/Loader.tsx +64 -19
  22. package/src/creator/src/components/Login.tsx +6 -12
  23. package/src/creator/src/components/Message.tsx +28 -0
  24. package/src/creator/src/components/RigoLoader.tsx +14 -0
  25. package/src/creator/src/components/StepWizard.tsx +1 -0
  26. package/src/creator/src/components/SyllabusEditor.tsx +111 -261
  27. package/src/creator/src/index.css +64 -0
  28. package/src/creator/src/utils/creatorUtils.ts +136 -0
  29. package/src/creator/src/utils/eventBus.ts +2 -0
  30. package/src/creator/src/utils/lib.ts +6 -0
  31. package/src/creator/src/utils/store.ts +6 -1
  32. package/{lib/creatorDist/assets/index-tt9JBVY0.css → src/creatorDist/assets/index-t6ma_gVm.css} +118 -20
  33. package/src/creatorDist/assets/index-tZYXMzIW.js +75067 -0
  34. package/src/creatorDist/assets/pdf.worker-DSVOJ9H9.js +56037 -0
  35. package/src/creatorDist/index.html +10 -5
  36. package/src/creatorDist/logo-192 copy.png +0 -0
  37. package/src/creatorDist/logo.png +0 -0
  38. package/src/ui/_app/app.css +1 -1
  39. package/src/ui/_app/app.js +299 -299
  40. package/src/ui/app.tar.gz +0 -0
  41. package/lib/creatorDist/assets/index-CrrS9sA3.js +0 -23718
  42. package/src/creator/src/App.css +0 -42
  43. package/src/creatorDist/assets/index-CrrS9sA3.js +0 -23718
@@ -85,4 +85,142 @@ export const SVGS = {
85
85
  </g>
86
86
  </svg>
87
87
  ),
88
+ rigoSoftBlue: (
89
+ <svg
90
+ width="25"
91
+ height="15"
92
+ viewBox="0 0 18 11"
93
+ fill="none"
94
+ xmlns="http://www.w3.org/2000/svg"
95
+ >
96
+ <path
97
+ d="M17.1812 3.46636H16.7418V3.32743C16.7418 2.09446 15.7417 1.09375 14.51 1.09375H13.3627L13.7718 1.85133C14.2502 1.94685 14.642 2.28548 14.8195 2.73699H2.64959C2.86173 2.20299 3.37477 1.82529 3.97439 1.82529H11.54L11.934 1.09592H2.96131C1.72743 1.09375 0.727339 2.09228 0.727339 3.32743V3.46636H0.287905C0.127717 3.46636 0 3.59443 0 3.75289V7.56252C0 7.72098 0.129882 7.84905 0.287905 7.84905H1.82051V7.99015C1.82051 8.13125 1.8703 8.26366 1.95256 8.36569C1.96338 8.38088 1.97637 8.39391 1.98936 8.40693C2.01533 8.43298 2.04348 8.45686 2.07378 8.47857C2.11924 8.51113 2.17119 8.535 2.22531 8.55237C2.27943 8.56974 2.33787 8.57842 2.39632 8.57842H2.54785H7.58078L8.27997 6.38815L8.59386 5.40047C8.63931 5.25721 8.83197 5.25721 8.87743 5.40047L9.19131 6.38815L9.89051 8.57842H14.9234H15.075C15.1637 8.57842 15.2481 8.55671 15.3239 8.51981C15.365 8.4981 15.404 8.47422 15.4408 8.44383C15.4689 8.41996 15.4949 8.39391 15.5187 8.36352C15.536 8.34181 15.5534 8.31793 15.5664 8.29405C15.6183 8.20505 15.6508 8.10086 15.6508 7.98798V7.84688H17.1812C17.3414 7.84688 17.4691 7.71881 17.4691 7.56035V3.75072C17.4691 3.59226 17.3392 3.46418 17.1812 3.46418V3.46636ZM15.2958 7.82301C15.2958 8.04008 15.1204 8.21374 14.9061 8.21374H10.0723L9.61992 6.96991L8.85578 4.87082C8.81466 4.75577 8.6523 4.75577 8.60901 4.87082L7.84487 6.96991L7.39245 8.21374H2.563C2.34653 8.21374 2.17336 8.03791 2.17336 7.82301V3.46853C2.17336 3.25145 2.3487 3.07779 2.563 3.07779H14.9061C15.1226 3.07779 15.2958 3.25362 15.2958 3.46853V7.82084V7.82301Z"
98
+ fill="url(#paint0_linear_1485_1767)"
99
+ />
100
+ <path
101
+ d="M2.6496 2.73592C2.86174 2.20193 3.37477 1.82422 3.97439 1.82422H11.54H3.97656C3.37694 1.82422 2.8639 2.20193 2.65176 2.73592H2.6496Z"
102
+ fill="#080B16"
103
+ />
104
+ <path
105
+ d="M14.8196 2.73722C14.6421 2.28788 14.2502 1.94707 13.7719 1.85156C14.2502 1.94707 14.6421 2.28571 14.8196 2.73722Z"
106
+ fill="#080B16"
107
+ />
108
+ <path
109
+ d="M13.0033 8.57837H9.89045L9.19125 6.3881L8.87737 5.40042C8.83191 5.25715 8.63925 5.25715 8.5938 5.40042L8.27991 6.3881L7.58072 8.57837H2.54779V9.49441C2.54779 10.2976 3.18638 10.951 3.97649 10.951H8.11973C13.7934 10.8403 13.0119 8.59573 13.0055 8.57837H13.0033Z"
110
+ fill="#B0EFFF"
111
+ />
112
+ <path
113
+ d="M8.11768 10.9507H13.4948C14.2827 10.9507 14.9235 10.2995 14.9235 9.49417V8.57812H13.0034C13.0099 8.59549 13.7914 10.84 8.11768 10.9507Z"
114
+ fill="url(#paint1_linear_1485_1767)"
115
+ />
116
+ <path
117
+ d="M13.0445 2.7362H14.8195C14.642 2.28469 14.2502 1.94606 13.7718 1.85055L13.3627 1.09296L12.8259 0.100939C12.7523 -0.0336463 12.5444 -0.0336463 12.473 0.100939L12.1028 0.784718L12.6224 1.8614C13.2718 2.26298 13.0488 2.72752 13.0445 2.7362Z"
118
+ fill="url(#paint2_linear_1485_1767)"
119
+ />
120
+ <path
121
+ d="M2.65176 2.73664H13.0445C13.0445 2.73664 13.2696 2.26342 12.6224 1.86184C12.6029 1.84881 12.5812 1.83579 12.5596 1.82493L12.1028 0.785156L11.9362 1.09557L11.5422 1.82493H3.97439C3.37477 1.82493 2.86174 2.20264 2.6496 2.73664H2.65176Z"
122
+ fill="#B0EFFF"
123
+ />
124
+ <path
125
+ d="M12.6202 1.86184L12.1007 0.785156L12.5575 1.82493C12.5791 1.83796 12.6008 1.84881 12.6202 1.86184Z"
126
+ fill="#C7F3FD"
127
+ />
128
+ <path
129
+ d="M14.9062 3.07812H2.56305C2.34658 3.07812 2.1734 3.25395 2.1734 3.46886V7.82117C2.1734 8.03824 2.34874 8.2119 2.56305 8.2119H7.39465L7.84708 6.96807L8.61122 4.86898C8.65234 4.75393 8.8147 4.75393 8.85799 4.86898L9.62213 6.96807L10.0746 8.2119H14.9083C15.1248 8.2119 15.298 8.03607 15.298 7.82117V3.46886C15.298 3.25178 15.1226 3.07812 14.9083 3.07812H14.9062ZM5.27758 3.82268V6.38414V7.30453C5.27758 7.50207 5.11523 7.6627 4.91391 7.6627C4.71259 7.6627 4.55024 7.50207 4.55024 7.30453V3.82268C4.55024 3.62515 4.71259 3.46451 4.91391 3.46451C5.11523 3.46451 5.27758 3.62515 5.27758 3.82268ZM12.9233 3.82268V6.38414V7.30453C12.9233 7.50207 12.7609 7.6627 12.5596 7.6627C12.3583 7.6627 12.196 7.50207 12.196 7.30453V3.82268C12.196 3.62515 12.3583 3.46451 12.5596 3.46451C12.7609 3.46451 12.9233 3.62515 12.9233 3.82268Z"
130
+ fill="#080B16"
131
+ />
132
+ <path
133
+ d="M4.91384 3.46484C4.71252 3.46484 4.55017 3.62548 4.55017 3.82301V7.30486C4.55017 7.5024 4.71252 7.66303 4.91384 7.66303C5.11516 7.66303 5.27751 7.5024 5.27751 7.30486V6.38664V3.82301C5.27751 3.62548 5.11516 3.46484 4.91384 3.46484Z"
134
+ fill="#E95B17"
135
+ />
136
+ <path
137
+ d="M12.5574 3.46484C12.3561 3.46484 12.1937 3.62548 12.1937 3.82301V7.30486C12.1937 7.5024 12.3561 7.66303 12.5574 7.66303C12.7587 7.66303 12.9211 7.5024 12.9211 7.30486V6.38664V3.82301C12.9211 3.62548 12.7587 3.46484 12.5574 3.46484Z"
138
+ fill="#0084FF"
139
+ />
140
+ <defs>
141
+ <linearGradient
142
+ id="paint0_linear_1485_1767"
143
+ x1="10.5789"
144
+ y1="0.294922"
145
+ x2="7.57889"
146
+ y2="8.97052"
147
+ gradientUnits="userSpaceOnUse"
148
+ >
149
+ <stop stopColor="#080B16" />
150
+ <stop offset="1" stopColor="#161F2C" />
151
+ </linearGradient>
152
+ <linearGradient
153
+ id="paint1_linear_1485_1767"
154
+ x1="8.11768"
155
+ y1="9.76334"
156
+ x2="14.9235"
157
+ y2="9.76334"
158
+ gradientUnits="userSpaceOnUse"
159
+ >
160
+ <stop stopColor="#B0EFFF" />
161
+ <stop offset="0.44" stopColor="#ADECFE" />
162
+ <stop offset="0.67" stopColor="#A5E4FE" />
163
+ <stop offset="0.85" stopColor="#98D7FD" />
164
+ <stop offset="1" stopColor="#86C5FD" />
165
+ </linearGradient>
166
+ <linearGradient
167
+ id="paint2_linear_1485_1767"
168
+ x1="11.2543"
169
+ y1="1.91784"
170
+ x2="13.5278"
171
+ y2="1.41473"
172
+ gradientUnits="userSpaceOnUse"
173
+ >
174
+ <stop stopColor="#B0EFFF" />
175
+ <stop offset="0.44" stopColor="#ADECFE" />
176
+ <stop offset="0.67" stopColor="#A5E4FE" />
177
+ <stop offset="0.85" stopColor="#98D7FD" />
178
+ <stop offset="1" stopColor="#86C5FD" />
179
+ </linearGradient>
180
+ </defs>
181
+ </svg>
182
+ ),
183
+ send: (
184
+ <svg
185
+ width="12"
186
+ height="15"
187
+ viewBox="0 0 12 15"
188
+ fill="none"
189
+ xmlns="http://www.w3.org/2000/svg"
190
+ >
191
+ <path
192
+ d="M6.12812 3.64814L0.384343 0.0378137C0.213539 -0.0696296 0 0.0647108 0 0.279307V5.34833C0 5.47075 0.0733163 5.57892 0.18082 5.61498L2.90314 6.52715L5.01075 7.23331C5.25193 7.31415 5.25193 7.68577 5.01075 7.76646L2.90314 8.47262L0.18082 9.38509C0.0733163 9.42114 0 9.52931 0 9.65173V14.7206C0 14.9354 0.213539 15.0695 0.384343 14.9622L6.12812 11.3519L11.8719 7.7416C12.0427 7.6343 12.0427 7.36576 11.8719 7.25847L6.12812 3.64814Z"
193
+ fill="#C7F3FD"
194
+ />
195
+ </svg>
196
+ ),
197
+ clip: (
198
+ <svg
199
+ fill="#C7F3FD"
200
+ width="20"
201
+ height="20"
202
+ viewBox="0 0 32 32"
203
+ version="1.1"
204
+ xmlns="http://www.w3.org/2000/svg"
205
+ >
206
+ <title>clip</title>
207
+ <path d="M5.469 16.688l8.75-8.75c0.094-0.094 0.844-0.844 2.031-1.25 1.656-0.531 3.344-0.094 4.688 1.25 1.375 1.344 1.781 3 1.25 4.656-0.375 1.188-1.156 2-1.25 2.094l-9.406 9.406c-1.625 1.625-5.688 3.719-9.438 0-3.719-3.719-1.594-7.813 0-9.406l10.094-10.125c0.375-0.375 0.969-0.375 1.344 0s0.375 0.969 0 1.344l-10.063 10.125c-0.156 0.125-3.313 3.406 0 6.719 3.219 3.219 6.375 0.344 6.719 0l9.406-9.438s0.531-0.531 0.781-1.281c0.313-1 0.094-1.875-0.781-2.75-1.875-1.875-3.688-0.313-4.031 0l-8.75 8.719c-0.313 0.313-0.531 0.844 0 1.375s1.031 0.281 1.344 0l6.063-6.063c0.375-0.344 1-0.344 1.344 0 0.375 0.375 0.375 1 0 1.375l-6.063 6.031c-0.844 0.813-2.563 1.469-4.031 0-1.5-1.469-0.844-3.219 0-4.031z"></path>
208
+ </svg>
209
+ ),
210
+ user: (
211
+ <svg
212
+ width="20"
213
+ height="20"
214
+ viewBox="0 0 24 24"
215
+ fill="none"
216
+ xmlns="http://www.w3.org/2000/svg"
217
+ >
218
+ <circle cx="12" cy="6" r="4" stroke="#1C398E" strokeWidth="1.5" />
219
+ <path
220
+ d="M20 17.5C20 19.9853 20 22 12 22C4 22 4 19.9853 4 17.5C4 15.0147 7.58172 13 12 13C16.4183 13 20 15.0147 20 17.5Z"
221
+ stroke="#1C398E"
222
+ strokeWidth="1.5"
223
+ />
224
+ </svg>
225
+ ),
88
226
  }
@@ -0,0 +1,91 @@
1
+ import React, { useRef } from "react"
2
+ import * as pdfjsLib from "pdfjs-dist"
3
+ import mammoth from "mammoth"
4
+ import { SVGS } from "../assets/svgs"
5
+ import pdfWorker from "pdfjs-dist/build/pdf.worker?worker"
6
+
7
+ pdfjsLib.GlobalWorkerOptions.workerPort = new pdfWorker()
8
+
9
+ const allowedTypes = [
10
+ "application/pdf",
11
+ "application/vnd.openxmlformats-officedocument.wordprocessingml.document",
12
+ "text/plain",
13
+ "text/markdown",
14
+ ]
15
+
16
+ export interface ParsedFile {
17
+ name: string
18
+ text: string
19
+ }
20
+
21
+ interface FileUploaderProps {
22
+ onResult: (files: ParsedFile[]) => void
23
+ }
24
+
25
+ const FileUploader: React.FC<FileUploaderProps> = ({ onResult }) => {
26
+ const inputRef = useRef<HTMLInputElement>(null)
27
+
28
+ const extractText = async (file: File): Promise<ParsedFile> => {
29
+ const { type, name } = file
30
+
31
+ if (type === "application/pdf") {
32
+ const arrayBuffer = await file.arrayBuffer()
33
+ const pdf = await pdfjsLib.getDocument({ data: arrayBuffer }).promise
34
+ let text = ""
35
+
36
+ for (let i = 0; i < pdf.numPages; i++) {
37
+ const page = await pdf.getPage(i + 1)
38
+ const content = await page.getTextContent()
39
+ text += content.items.map((item: any) => item.str).join(" ") + "\n"
40
+ }
41
+
42
+ return { name, text }
43
+ }
44
+
45
+ if (
46
+ type ===
47
+ "application/vnd.openxmlformats-officedocument.wordprocessingml.document"
48
+ ) {
49
+ const arrayBuffer = await file.arrayBuffer()
50
+ const { value } = await mammoth.extractRawText({ arrayBuffer })
51
+ return { name, text: value }
52
+ }
53
+
54
+ const text = await file.text()
55
+ return { name, text }
56
+ }
57
+
58
+ const handleFiles = async (e: React.ChangeEvent<HTMLInputElement>) => {
59
+ const inputFiles = e.target.files
60
+ if (!inputFiles) return
61
+
62
+ const files = Array.from(inputFiles).filter((file) =>
63
+ allowedTypes.includes(file.type)
64
+ )
65
+ const parsed = await Promise.all(files.map(extractText))
66
+ onResult(parsed)
67
+ }
68
+
69
+ return (
70
+ <>
71
+ <button
72
+ type="button"
73
+ className="cursor-pointer blue-on-hover flex items-center justify-center w-6 h-6"
74
+ onClick={() => inputRef.current?.click()}
75
+ >
76
+ {SVGS.clip}
77
+ </button>
78
+
79
+ <input
80
+ ref={inputRef}
81
+ type="file"
82
+ multiple
83
+ accept=".pdf,.docx,.txt,.md"
84
+ onChange={handleFiles}
85
+ style={{ display: "none" }}
86
+ />
87
+ </>
88
+ )
89
+ }
90
+
91
+ export default FileUploader
@@ -0,0 +1,70 @@
1
+ import { useState } from "react"
2
+ import { SVGS } from "../assets/svgs"
3
+
4
+ export interface Lesson {
5
+ id: string
6
+ title: string
7
+ type: "READ" | "CODE" | "QUIZ"
8
+ description: string
9
+ duration?: number
10
+ }
11
+
12
+ interface LessonItemProps {
13
+ lesson: Lesson
14
+ index: string
15
+ isNew: boolean
16
+ onChange: (id: string, newTitle: string) => void
17
+ onRemove: (id: string) => void
18
+ }
19
+
20
+ export const LessonItem: React.FC<LessonItemProps> = ({
21
+ lesson,
22
+ index,
23
+ onChange,
24
+ onRemove,
25
+ isNew,
26
+ }) => {
27
+ const [isEditing, setIsEditing] = useState(false)
28
+
29
+ return (
30
+ <div
31
+ className={`flex items-center space-x-2 border border-gray-200 rounded-md p-3 ${
32
+ isNew ? "bg-yellow-50" : ""
33
+ }`}
34
+ >
35
+ <span className="index-circle">{index}</span>
36
+ <span className="text-gray-500 text-sm">
37
+ {lesson.type[0] + lesson.type.slice(1).toLowerCase()} ●
38
+ </span>
39
+
40
+ {isEditing ? (
41
+ <input
42
+ value={lesson.title}
43
+ onChange={(e) => onChange(lesson.id, e.target.value)}
44
+ onBlur={() => setIsEditing(false)}
45
+ autoFocus
46
+ className="flex-1 bg-white border border-gray-300 rounded-md px-2 py-1 text-sm"
47
+ />
48
+ ) : (
49
+ <span className="flex-1 text-sm text-gray-800">{lesson.title}</span>
50
+ )}
51
+
52
+ <span className="text-sm text-gray-600 bg-blue-100 px-2 py-1 rounded-full">
53
+ {lesson.duration} min
54
+ </span>
55
+
56
+ <button
57
+ onClick={() => setIsEditing(!isEditing)}
58
+ className="text-gray-500 hover:text-blue-500 cursor-pointer "
59
+ >
60
+ {SVGS.pen}
61
+ </button>
62
+ <button
63
+ onClick={() => onRemove(lesson.id)}
64
+ className="text-red-500 hover:text-red-700 cursor-pointer"
65
+ >
66
+ {SVGS.trash}
67
+ </button>
68
+ </div>
69
+ )
70
+ }
@@ -1,28 +1,73 @@
1
- import React from 'react';
1
+ import React, { useEffect, useRef, useState } from "react"
2
+ import { eventBus } from "../utils/eventBus"
2
3
 
3
4
  interface LoaderProps {
4
- text: string;
5
- icon?: React.ReactNode;
5
+ text: string
6
+ icon?: React.ReactNode
7
+ listeningTo?: string
8
+ initialBuffer?: string
6
9
  }
7
10
 
8
- const Loader: React.FC<LoaderProps> = ({ text, icon }) => {
11
+ const Loader: React.FC<LoaderProps> = ({
12
+ text,
13
+ icon,
14
+ listeningTo,
15
+ initialBuffer,
16
+ }) => {
17
+ const [buffer, setBuffer] = useState(initialBuffer || "")
18
+ const preRef = useRef<HTMLPreElement>(null)
19
+
20
+ useEffect(() => {
21
+ if (listeningTo) {
22
+ eventBus.on(listeningTo, (e: any) => {
23
+ setBuffer((prev) => prev + "\n" + e.message)
24
+ })
25
+ }
26
+ return () => {
27
+ if (listeningTo) {
28
+ eventBus.off(listeningTo)
29
+ }
30
+ }
31
+ }, [listeningTo])
32
+
33
+ useEffect(() => {
34
+ if (preRef.current) {
35
+ preRef.current.scrollTo({
36
+ top: preRef.current.scrollHeight,
37
+ behavior: "smooth",
38
+ })
39
+ }
40
+ }, [buffer])
41
+
9
42
  return (
10
43
  <div className="flex flex-col items-center justify-center min-h-screen bg-gray-50 text-center space-y-6">
11
- <div className="text-blue-500 text-4xl animate-pulse">
12
- {icon}
13
- </div>
44
+ <div className="text-blue-500 text-4xl animate-pulse">{icon}</div>
14
45
  <p className="text-gray-800 text-lg whitespace-pre-line">{text}</p>
15
- <div className="flex space-x-2 mt-2">
16
- {[0, 1, 2, 3].map((i) => (
17
- <span
18
- key={i}
19
- className="w-2 h-2 rounded-full bg-blue-400 opacity-30 animate-ping"
20
- style={{ animationDelay: `${i * 0.2}s`, animationDuration: '1.2s' }}
21
- />
22
- ))}
23
- </div>
46
+ {!buffer && (
47
+ <div className="flex space-x-2 mt-2">
48
+ {[0, 1, 2, 3].map((i) => (
49
+ <span
50
+ key={i}
51
+ className="w-2 h-2 rounded-full bg-blue-400 opacity-30 animate-ping"
52
+ style={{
53
+ animationDelay: `${i * 0.2}s`,
54
+ animationDuration: "1.2s",
55
+ }}
56
+ />
57
+ ))}
58
+ </div>
59
+ )}
60
+ {buffer && (
61
+ <pre
62
+ ref={preRef}
63
+ className="text-gray-800 text-sm border border-blue-200 rounded-md p-3 font-sans max-h-[300px] overflow-y-auto w-full max-w-[700px] text-left"
64
+ style={{ scrollbarWidth: "none" }}
65
+ >
66
+ {buffer.trim()}
67
+ </pre>
68
+ )}
24
69
  </div>
25
- );
26
- };
70
+ )
71
+ }
27
72
 
28
- export default Loader;
73
+ export default Loader
@@ -4,19 +4,13 @@ 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 { checkParams } from "../utils/lib"
7
8
 
8
9
  type LoginInfo = {
9
10
  email: string
10
11
  password: string
11
12
  }
12
13
 
13
- const checkParams = () => {
14
- const urlParams = new URLSearchParams(window.location.search)
15
- const token = urlParams.get("token")
16
-
17
- return { token }
18
- }
19
-
20
14
  const getRigobotJSON = async (breathecodeToken: string) => {
21
15
  const rigoUrl = `${RIGOBOT_HOST}/v1/auth/me/token?breathecode_token=${breathecodeToken}`
22
16
  const rigoResp = await fetch(rigoUrl)
@@ -80,7 +74,7 @@ const login4Geeks = async (loginInfo: LoginInfo) => {
80
74
  return returns
81
75
  }
82
76
 
83
- const loginWithToken = async (token: string) => {
77
+ export const loginWithToken = async (token: string) => {
84
78
  const rigoJson = await getRigobotJSON(token)
85
79
 
86
80
  const user = await validateUser(token)
@@ -198,7 +192,7 @@ export default function Login({ onFinish }: { onFinish: () => void }) {
198
192
 
199
193
  <button
200
194
  onClick={redirectGithub}
201
- className="w-full border border-gray-300 py-2 rounded-md font-semibold flex items-center justify-center gap-2 mb-4"
195
+ className="w-full border border-gray-300 py-2 rounded-md font-semibold flex items-center justify-center gap-2 mb-4 cursor-pointer"
202
196
  >
203
197
  {SVGS.github}
204
198
  LOGIN WITH GITHUB
@@ -227,14 +221,14 @@ export default function Login({ onFinish }: { onFinish: () => void }) {
227
221
  <div className="flex gap-2 mt-4">
228
222
  <button
229
223
  type="submit"
230
- className="flex-1 bg-sky-500 text-white py-2 rounded-md font-semibold"
224
+ className="flex-1 bg-sky-500 text-white py-2 rounded-md font-semibold cursor-pointer "
231
225
  >
232
226
  {isLoading ? "Logging in..." : "Log in"}
233
227
  </button>
234
228
  <button
235
229
  type="button"
236
230
  onClick={() => setShowForm(false)}
237
- className="flex-1 border border-sky-500 text-sky-600 py-2 rounded-md font-semibold"
231
+ className="flex-1 border border-sky-500 text-sky-600 py-2 rounded-md font-semibold cursor-pointer"
238
232
  >
239
233
  Skip
240
234
  </button>
@@ -252,7 +246,7 @@ export default function Login({ onFinish }: { onFinish: () => void }) {
252
246
  ) : (
253
247
  <button
254
248
  onClick={() => setShowForm(true)}
255
- className="w-full bg-blue-600 text-white py-2 rounded-md font-semibold"
249
+ className="w-full bg-blue-600 text-white py-2 rounded-md font-semibold cursor-pointer"
256
250
  >
257
251
  Login with Email
258
252
  </button>
@@ -0,0 +1,28 @@
1
+ import { RigoLoader } from "./RigoLoader"
2
+
3
+ import { SVGS } from "../assets/svgs"
4
+
5
+ export type TMessage = {
6
+ type: "user" | "assistant"
7
+ content: string
8
+ }
9
+
10
+ export const Message: React.FC<TMessage> = ({ type, content }) => {
11
+ const isAI = type === "assistant"
12
+
13
+ const isLoading = isAI && !content
14
+ return isLoading ? (
15
+ <RigoLoader text="Thinking..." svg={SVGS.rigoSoftBlue} />
16
+ ) : (
17
+ <div
18
+ className={`flex items-start space-x-2 p-3 rounded-md border ${
19
+ isAI
20
+ ? "bg-gray-50 border-gray-300 text-gray-800"
21
+ : "bg-blue-50 border-blue-200 text-blue-900"
22
+ }`}
23
+ >
24
+ <span className="mt-1">{isAI ? SVGS.rigoSoftBlue : SVGS.user}</span>
25
+ <p className="text-sm leading-relaxed">{content}</p>
26
+ </div>
27
+ )
28
+ }
@@ -0,0 +1,14 @@
1
+ export const RigoLoader = ({
2
+ text,
3
+ svg,
4
+ }: {
5
+ text: string
6
+ svg: React.ReactNode
7
+ }) => {
8
+ return (
9
+ <div className="loader">
10
+ <div className="loader-icon">{svg}</div>
11
+ <div className="loader-text">{text}</div>
12
+ </div>
13
+ )
14
+ }
@@ -4,6 +4,7 @@ export type Step = {
4
4
  title: string
5
5
  subtitle?: string
6
6
  content: React.ReactNode
7
+ slug: string
7
8
  }
8
9
 
9
10
  type Props = {