wadi 1.0.0

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 (294) hide show
  1. package/.agent/workflows/auto_sync.md +19 -0
  2. package/.agent/workflows/kivo_pipeline.md +27 -0
  3. package/.devcontainer/devcontainer.json +27 -0
  4. package/.github/workflows/kivo-cicd.yml +45 -0
  5. package/.github/workflows/monorepo-ci.yml +51 -0
  6. package/.github/workflows/wadi-ci.yml +38 -0
  7. package/.husky/pre-commit +2 -0
  8. package/.prettierignore +12 -0
  9. package/.prettierrc +9 -0
  10. package/.vscode/settings.json +19 -0
  11. package/CHANGELOG.md +56 -0
  12. package/CODE_OF_CONDUCT.md +43 -0
  13. package/CONTRIBUTING.md +42 -0
  14. package/DEPLOY_GUIDE.md +143 -0
  15. package/GO_LIVE_CHECKLIST.md +41 -0
  16. package/GO_LIVE_COMPLETE_REPORT.md +58 -0
  17. package/GO_LIVE_VALIDATION.md +39 -0
  18. package/LEGAL.md +38 -0
  19. package/MANIFESTO.md +40 -0
  20. package/MANUAL.md +82 -0
  21. package/OPS_PLAN.md +90 -0
  22. package/README.md +126 -0
  23. package/RELEASE_NOTES.md +51 -0
  24. package/ROADMAP.md +51 -0
  25. package/api_listado.txt +2197 -0
  26. package/apps/api/WADI_PROTOCOL.md +52 -0
  27. package/apps/api/debug-brain.js +11 -0
  28. package/apps/api/package.json +21 -0
  29. package/apps/api/src/core/analisis.js +17 -0
  30. package/apps/api/src/core/errors.js +31 -0
  31. package/apps/api/src/core/logger.js +32 -0
  32. package/apps/api/src/core/prompt-kivo.js +62 -0
  33. package/apps/api/src/index.js +212 -0
  34. package/apps/api/src/layers/human_pattern/composeResponse.js +35 -0
  35. package/apps/api/src/layers/human_pattern/detectPattern.js +39 -0
  36. package/apps/api/src/layers/human_pattern/heuristics.js +28 -0
  37. package/apps/api/src/layers/human_pattern/index.js +28 -0
  38. package/apps/api/src/layers/human_pattern/socialMemory.js +35 -0
  39. package/apps/api/src/middleware/errorHandler.js +24 -0
  40. package/apps/api/src/middleware/rateLimiter.js +38 -0
  41. package/apps/api/src/middleware/requestLogger.js +31 -0
  42. package/apps/api/src/middleware/upload.js +21 -0
  43. package/apps/api/src/middleware/validation.js +70 -0
  44. package/apps/api/src/modules/data.js +25 -0
  45. package/apps/api/src/modules/marketing.js +54 -0
  46. package/apps/api/src/modules/projects.js +40 -0
  47. package/apps/api/src/openai.js +16 -0
  48. package/apps/api/src/preferences/index.js +20 -0
  49. package/apps/api/src/register_user.js +22 -0
  50. package/apps/api/src/routes/kivo.js +58 -0
  51. package/apps/api/src/routes/monitoring.js +55 -0
  52. package/apps/api/src/routes.js +656 -0
  53. package/apps/api/src/supabase.js +17 -0
  54. package/apps/api/src/tools/index.js +57 -0
  55. package/apps/api/src/wadi-brain.js +171 -0
  56. package/apps/api/supabase/migrations/20251218_audit_logs.sql +27 -0
  57. package/apps/api/supabase/migrations/v2-chat-persistence.sql +83 -0
  58. package/apps/api/supabase/migrations/v3-cascade-delete.sql +11 -0
  59. package/apps/api/supabase/migrations/v3-security-fix.sql +90 -0
  60. package/apps/api/supabase/migrations/v3-storage.sql +36 -0
  61. package/apps/api/supabase/migrations/v4-gamification.sql +83 -0
  62. package/apps/api/supabase/migrations/v5-smoke-index.sql +6 -0
  63. package/apps/api/supabase/migrations/v6-schema-integrity-fix.sql +98 -0
  64. package/apps/api/supabase/migrations/v7-performance-indexes.sql +5 -0
  65. package/apps/api/supabase/migrations/v7-security-hardening.sql +132 -0
  66. package/apps/api/supabase/migrations/v8-security-hardening.sql +79 -0
  67. package/apps/api/test_human_pattern.js +30 -0
  68. package/apps/api/test_human_pattern_vague.js +30 -0
  69. package/apps/api/test_output.txt +76 -0
  70. package/apps/api/test_vague.js +30 -0
  71. package/apps/api/test_vague_block.js +30 -0
  72. package/apps/api/test_wadi.js +31 -0
  73. package/apps/api/tsconfig.json +13 -0
  74. package/apps/frontend/.env.local +3 -0
  75. package/apps/frontend/README.md +73 -0
  76. package/apps/frontend/eslint.config.js +27 -0
  77. package/apps/frontend/index.html +49 -0
  78. package/apps/frontend/package.json +41 -0
  79. package/apps/frontend/postcss.config.cjs +6 -0
  80. package/apps/frontend/public/cursors/wadi-neutral.svg +1 -0
  81. package/apps/frontend/public/cursors/wadi-select.svg +1 -0
  82. package/apps/frontend/public/icon-192.svg +1 -0
  83. package/apps/frontend/public/icon-512.svg +1 -0
  84. package/apps/frontend/public/manifest.webmanifest +23 -0
  85. package/apps/frontend/public/sw.js +57 -0
  86. package/apps/frontend/public/vite.svg +1 -0
  87. package/apps/frontend/public/wadi.svg +5 -0
  88. package/apps/frontend/src/assets/react.svg +1 -0
  89. package/apps/frontend/src/components/AuthLoader.tsx +50 -0
  90. package/apps/frontend/src/components/ChatInput.tsx +272 -0
  91. package/apps/frontend/src/components/ChatInterface.tsx +202 -0
  92. package/apps/frontend/src/components/ErrorBoundary.tsx +52 -0
  93. package/apps/frontend/src/components/InputArea.tsx +201 -0
  94. package/apps/frontend/src/components/Layout.tsx +73 -0
  95. package/apps/frontend/src/components/MessageBubble.tsx +66 -0
  96. package/apps/frontend/src/components/OnboardingModal.tsx +108 -0
  97. package/apps/frontend/src/components/SettingsModal.tsx +187 -0
  98. package/apps/frontend/src/components/Sidebar.tsx +171 -0
  99. package/apps/frontend/src/components/WadiOnboarding.tsx +71 -0
  100. package/apps/frontend/src/components/auditor/AuditReport.tsx +166 -0
  101. package/apps/frontend/src/components/auditor/AuditorHeader.tsx +34 -0
  102. package/apps/frontend/src/components/auditor/ContextPanel.tsx +138 -0
  103. package/apps/frontend/src/components/auditor/DataDeconstructor.tsx +85 -0
  104. package/apps/frontend/src/components/auditor/DecisionWall.tsx +65 -0
  105. package/apps/frontend/src/components/auditor/Dropzone.tsx +137 -0
  106. package/apps/frontend/src/components/common/Button.tsx +97 -0
  107. package/apps/frontend/src/components/common/Card.tsx +43 -0
  108. package/apps/frontend/src/components/common/Input.tsx +73 -0
  109. package/apps/frontend/src/components/common/Modal.tsx +53 -0
  110. package/apps/frontend/src/components/ui/Button.tsx +68 -0
  111. package/apps/frontend/src/components/ui/Card.tsx +86 -0
  112. package/apps/frontend/src/components/ui/Input.tsx +28 -0
  113. package/apps/frontend/src/components/ui/LogItem.tsx +64 -0
  114. package/apps/frontend/src/components/ui/MondayButton.tsx +40 -0
  115. package/apps/frontend/src/components/ui/MondayCard.tsx +24 -0
  116. package/apps/frontend/src/components/ui/Scouter.tsx +208 -0
  117. package/apps/frontend/src/components/ui/TerminalInput.tsx +202 -0
  118. package/apps/frontend/src/components/ui/Tooltip.tsx +67 -0
  119. package/apps/frontend/src/config/chatShortcuts.ts +20 -0
  120. package/apps/frontend/src/config/supabase.ts +6 -0
  121. package/apps/frontend/src/final_status.txt +3 -0
  122. package/apps/frontend/src/hooks/useScouter.ts +28 -0
  123. package/apps/frontend/src/hooks/useStoreHydration.ts +24 -0
  124. package/apps/frontend/src/improvement_status.txt +5 -0
  125. package/apps/frontend/src/index.css +88 -0
  126. package/apps/frontend/src/main.tsx +62 -0
  127. package/apps/frontend/src/monday_status.txt +7 -0
  128. package/apps/frontend/src/pages/ChatPage.tsx +201 -0
  129. package/apps/frontend/src/pages/DashboardPage.tsx +375 -0
  130. package/apps/frontend/src/pages/IntroWadi.tsx +114 -0
  131. package/apps/frontend/src/pages/LandingPage.tsx +103 -0
  132. package/apps/frontend/src/pages/Login.tsx +190 -0
  133. package/apps/frontend/src/pages/PrivacyPage.tsx +213 -0
  134. package/apps/frontend/src/pages/ProjectDetail.tsx +80 -0
  135. package/apps/frontend/src/pages/Projects.tsx +247 -0
  136. package/apps/frontend/src/pages/TermsPage.tsx +202 -0
  137. package/apps/frontend/src/router.tsx +83 -0
  138. package/apps/frontend/src/store/authStore.ts +152 -0
  139. package/apps/frontend/src/store/chatStore.ts +837 -0
  140. package/apps/frontend/src/store/documentStore.ts +89 -0
  141. package/apps/frontend/src/store/projectsStore.ts +111 -0
  142. package/apps/frontend/src/store/runsStore.ts +98 -0
  143. package/apps/frontend/src/utils/api.ts +34 -0
  144. package/apps/frontend/src/vite-env.d.ts +7 -0
  145. package/apps/frontend/tailwind.config.cjs +32 -0
  146. package/apps/frontend/tsconfig.app.json +27 -0
  147. package/apps/frontend/tsconfig.json +7 -0
  148. package/apps/frontend/tsconfig.node.json +26 -0
  149. package/apps/frontend/vite.config.ts +25 -0
  150. package/apps/kivo/.firebase/hosting.d3d3.cache +11 -0
  151. package/apps/kivo/.firebaserc +5 -0
  152. package/apps/kivo/BRANDING_GUIDE.md +71 -0
  153. package/apps/kivo/DEPLOYMENT_READY.md +46 -0
  154. package/apps/kivo/DEPLOY_URL.md +12 -0
  155. package/apps/kivo/IMPLEMENTATION_REPORT.md +35 -0
  156. package/apps/kivo/IMPLEMENTATION_REPORT_FINAL.md +49 -0
  157. package/apps/kivo/PLAN_MOBILE_2.0.md +44 -0
  158. package/apps/kivo/PWA_VERIFICATION_GUIDE.md +77 -0
  159. package/apps/kivo/README.md +28 -0
  160. package/apps/kivo/REBUILD_REPORT.md +34 -0
  161. package/apps/kivo/UPGRADE_REPORT.md +35 -0
  162. package/apps/kivo/android/app/build.gradle +54 -0
  163. package/apps/kivo/android/app/capacitor.build.gradle +19 -0
  164. package/apps/kivo/android/app/proguard-rules.pro +21 -0
  165. package/apps/kivo/android/app/src/androidTest/java/com/getcapacitor/myapp/ExampleInstrumentedTest.java +26 -0
  166. package/apps/kivo/android/app/src/main/AndroidManifest.xml +35 -0
  167. package/apps/kivo/android/app/src/main/java/com/kivo/app/MainActivity.java +5 -0
  168. package/apps/kivo/android/app/src/main/res/drawable/ic_launcher_background.xml +170 -0
  169. package/apps/kivo/android/app/src/main/res/drawable/splash.png +0 -0
  170. package/apps/kivo/android/app/src/main/res/drawable-land-hdpi/splash.png +0 -0
  171. package/apps/kivo/android/app/src/main/res/drawable-land-ldpi/splash.png +0 -0
  172. package/apps/kivo/android/app/src/main/res/drawable-land-mdpi/splash.png +0 -0
  173. package/apps/kivo/android/app/src/main/res/drawable-land-night-hdpi/splash.png +0 -0
  174. package/apps/kivo/android/app/src/main/res/drawable-land-night-ldpi/splash.png +0 -0
  175. package/apps/kivo/android/app/src/main/res/drawable-land-night-mdpi/splash.png +0 -0
  176. package/apps/kivo/android/app/src/main/res/drawable-land-night-xhdpi/splash.png +0 -0
  177. package/apps/kivo/android/app/src/main/res/drawable-land-night-xxhdpi/splash.png +0 -0
  178. package/apps/kivo/android/app/src/main/res/drawable-land-night-xxxhdpi/splash.png +0 -0
  179. package/apps/kivo/android/app/src/main/res/drawable-land-xhdpi/splash.png +0 -0
  180. package/apps/kivo/android/app/src/main/res/drawable-land-xxhdpi/splash.png +0 -0
  181. package/apps/kivo/android/app/src/main/res/drawable-land-xxxhdpi/splash.png +0 -0
  182. package/apps/kivo/android/app/src/main/res/drawable-night/splash.png +0 -0
  183. package/apps/kivo/android/app/src/main/res/drawable-port-hdpi/splash.png +0 -0
  184. package/apps/kivo/android/app/src/main/res/drawable-port-ldpi/splash.png +0 -0
  185. package/apps/kivo/android/app/src/main/res/drawable-port-mdpi/splash.png +0 -0
  186. package/apps/kivo/android/app/src/main/res/drawable-port-night-hdpi/splash.png +0 -0
  187. package/apps/kivo/android/app/src/main/res/drawable-port-night-ldpi/splash.png +0 -0
  188. package/apps/kivo/android/app/src/main/res/drawable-port-night-mdpi/splash.png +0 -0
  189. package/apps/kivo/android/app/src/main/res/drawable-port-night-xhdpi/splash.png +0 -0
  190. package/apps/kivo/android/app/src/main/res/drawable-port-night-xxhdpi/splash.png +0 -0
  191. package/apps/kivo/android/app/src/main/res/drawable-port-night-xxxhdpi/splash.png +0 -0
  192. package/apps/kivo/android/app/src/main/res/drawable-port-xhdpi/splash.png +0 -0
  193. package/apps/kivo/android/app/src/main/res/drawable-port-xxhdpi/splash.png +0 -0
  194. package/apps/kivo/android/app/src/main/res/drawable-port-xxxhdpi/splash.png +0 -0
  195. package/apps/kivo/android/app/src/main/res/drawable-v24/ic_launcher_foreground.xml +34 -0
  196. package/apps/kivo/android/app/src/main/res/layout/activity_main.xml +12 -0
  197. package/apps/kivo/android/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml +9 -0
  198. package/apps/kivo/android/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml +9 -0
  199. package/apps/kivo/android/app/src/main/res/mipmap-hdpi/ic_launcher.png +0 -0
  200. package/apps/kivo/android/app/src/main/res/mipmap-hdpi/ic_launcher_background.png +0 -0
  201. package/apps/kivo/android/app/src/main/res/mipmap-hdpi/ic_launcher_foreground.png +0 -0
  202. package/apps/kivo/android/app/src/main/res/mipmap-hdpi/ic_launcher_round.png +0 -0
  203. package/apps/kivo/android/app/src/main/res/mipmap-ldpi/ic_launcher.png +0 -0
  204. package/apps/kivo/android/app/src/main/res/mipmap-ldpi/ic_launcher_background.png +0 -0
  205. package/apps/kivo/android/app/src/main/res/mipmap-ldpi/ic_launcher_foreground.png +0 -0
  206. package/apps/kivo/android/app/src/main/res/mipmap-ldpi/ic_launcher_round.png +0 -0
  207. package/apps/kivo/android/app/src/main/res/mipmap-mdpi/ic_launcher.png +0 -0
  208. package/apps/kivo/android/app/src/main/res/mipmap-mdpi/ic_launcher_background.png +0 -0
  209. package/apps/kivo/android/app/src/main/res/mipmap-mdpi/ic_launcher_foreground.png +0 -0
  210. package/apps/kivo/android/app/src/main/res/mipmap-mdpi/ic_launcher_round.png +0 -0
  211. package/apps/kivo/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png +0 -0
  212. package/apps/kivo/android/app/src/main/res/mipmap-xhdpi/ic_launcher_background.png +0 -0
  213. package/apps/kivo/android/app/src/main/res/mipmap-xhdpi/ic_launcher_foreground.png +0 -0
  214. package/apps/kivo/android/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png +0 -0
  215. package/apps/kivo/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png +0 -0
  216. package/apps/kivo/android/app/src/main/res/mipmap-xxhdpi/ic_launcher_background.png +0 -0
  217. package/apps/kivo/android/app/src/main/res/mipmap-xxhdpi/ic_launcher_foreground.png +0 -0
  218. package/apps/kivo/android/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png +0 -0
  219. package/apps/kivo/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png +0 -0
  220. package/apps/kivo/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher_background.png +0 -0
  221. package/apps/kivo/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher_foreground.png +0 -0
  222. package/apps/kivo/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png +0 -0
  223. package/apps/kivo/android/app/src/main/res/values/ic_launcher_background.xml +4 -0
  224. package/apps/kivo/android/app/src/main/res/values/strings.xml +7 -0
  225. package/apps/kivo/android/app/src/main/res/values/styles.xml +22 -0
  226. package/apps/kivo/android/app/src/main/res/xml/file_paths.xml +5 -0
  227. package/apps/kivo/android/app/src/test/java/com/getcapacitor/myapp/ExampleUnitTest.java +18 -0
  228. package/apps/kivo/android/build.gradle +29 -0
  229. package/apps/kivo/android/capacitor.settings.gradle +3 -0
  230. package/apps/kivo/android/gradle/wrapper/gradle-wrapper.jar +0 -0
  231. package/apps/kivo/android/gradle/wrapper/gradle-wrapper.properties +7 -0
  232. package/apps/kivo/android/gradle.properties +22 -0
  233. package/apps/kivo/android/gradlew +252 -0
  234. package/apps/kivo/android/gradlew.bat +94 -0
  235. package/apps/kivo/android/settings.gradle +5 -0
  236. package/apps/kivo/android/variables.gradle +16 -0
  237. package/apps/kivo/assets/icon.png +0 -0
  238. package/apps/kivo/assets/splash.png +0 -0
  239. package/apps/kivo/capacitor.config.json +16 -0
  240. package/apps/kivo/firebase.json +6 -0
  241. package/apps/kivo/jest.config.js +4 -0
  242. package/apps/kivo/package.json +26 -0
  243. package/apps/kivo/tests_disabled/logic.test.js +34 -0
  244. package/apps/kivo/www/assets/icon-192.png +0 -0
  245. package/apps/kivo/www/assets/icon-512.png +0 -0
  246. package/apps/kivo/www/assets/kivo-icon.png +0 -0
  247. package/apps/kivo/www/assets/pop.mp3 +0 -0
  248. package/apps/kivo/www/favicon.ico +0 -0
  249. package/apps/kivo/www/firebase-config.js +75 -0
  250. package/apps/kivo/www/index.html +38 -0
  251. package/apps/kivo/www/manifest.json +29 -0
  252. package/apps/kivo/www/script.js +72 -0
  253. package/apps/kivo/www/style.css +82 -0
  254. package/apps/kivo/www/sw.js +46 -0
  255. package/apps/kivo-brain-api/.env.example +2 -0
  256. package/apps/kivo-brain-api/KIVO_BACKEND_SETUP.md +27 -0
  257. package/apps/kivo-brain-api/controllers/kivoController.js +31 -0
  258. package/apps/kivo-brain-api/index.js +24 -0
  259. package/apps/kivo-brain-api/package.json +17 -0
  260. package/apps/kivo-brain-api/routes/message.js +8 -0
  261. package/apps/kivo-brain-api/services/openaiService.js +64 -0
  262. package/apps/tests/wadi-tests.js +155 -0
  263. package/apps/wadi-brain/docs/README_REMOVE_OPTIONS.md +26 -0
  264. package/cli/commands/deploy.js +10 -0
  265. package/cli/commands/docs.js +16 -0
  266. package/cli/commands/explain.js +29 -0
  267. package/cli/commands/lint.js +14 -0
  268. package/cli/index.js +26 -0
  269. package/cli/package.json +12 -0
  270. package/docs/CNAME +1 -0
  271. package/docs/README.md +38 -0
  272. package/docs/USO.md +30 -0
  273. package/docs/index.html +46 -0
  274. package/eslint.config.js +101 -0
  275. package/final_validation.json +27 -0
  276. package/frontend_listado.txt +33387 -0
  277. package/listado.txt +12591 -0
  278. package/package.json +46 -0
  279. package/packages/logger/index.js +43 -0
  280. package/packages/logger/package.json +19 -0
  281. package/packages/logger/test-logger.js +7 -0
  282. package/packages_listado.txt +801 -0
  283. package/pnpm-workspace.yaml +6 -0
  284. package/reseteador_existencial.ps1 +40 -0
  285. package/scripts/bump-version.js +26 -0
  286. package/scripts/env.ps1 +13 -0
  287. package/scripts/setup_android.ps1 +25 -0
  288. package/scripts/setup_virtual_env.ps1 +77 -0
  289. package/scripts/smoke-test.js +84 -0
  290. package/scripts/trigger_render_deploy.ps1 +3 -0
  291. package/scripts/validate-release.js +34 -0
  292. package/temp_check.js +57 -0
  293. package/tsconfig.json +5 -0
  294. package/validation_report.json +27 -0
@@ -0,0 +1,65 @@
1
+ import React from "react";
2
+
3
+ interface DecisionWallProps {
4
+ onOptionA: () => void;
5
+ onOptionB: () => void;
6
+ }
7
+
8
+ export const DecisionWall: React.FC<DecisionWallProps> = ({
9
+ onOptionA,
10
+ onOptionB,
11
+ }) => {
12
+ return (
13
+ <div className="fixed inset-0 z-50 flex items-center justify-center bg-black/90 backdrop-blur-lg">
14
+ <div className="w-full max-w-md p-1 border-2 border-[var(--monday-amber)] bg-black relative">
15
+ {/* Title Bar */}
16
+ <div className="bg-[var(--monday-amber)] text-black font-bold font-mono px-2 py-1 flex justify-between items-center">
17
+ <span>[CHECK_DE_LUCIDEZ]</span>
18
+ <span className="animate-blink">⚠</span>
19
+ </div>
20
+
21
+ <div className="p-8 flex flex-col items-center text-center space-y-6">
22
+ <h2 className="text-2xl font-bold font-mono text-[var(--monday-amber)]">
23
+ DETECTADA DIVAGACIÓN
24
+ </h2>
25
+ <p className="text-[var(--monday-text)] text-sm leading-relaxed">
26
+ El sistema ha detectado una fuga de ejecución. Estás hablando mucho
27
+ y haciendo poco.
28
+ <br />
29
+ <br />
30
+ Seleccioná un protocolo para continuar:
31
+ </p>
32
+
33
+ <div className="flex flex-col w-full gap-4 mt-4">
34
+ <button
35
+ onClick={onOptionA}
36
+ className="w-full border border-[var(--monday-primary)] text-[var(--monday-primary)] p-4 hover:bg-[var(--monday-primary)] hover:text-white transition-all text-left font-mono text-sm group"
37
+ >
38
+ <span className="block text-xs opacity-50 mb-1">OPCIÓN A</span>
39
+ <span className="font-bold">VOLVER AL PLAN TÉCNICO</span>
40
+ <span className="block text-xs mt-2 opacity-0 group-hover:opacity-100 transition-opacity">
41
+ Prometo dejar de vender humo y escribir código.
42
+ </span>
43
+ </button>
44
+
45
+ <button
46
+ onClick={onOptionB}
47
+ className="w-full border border-[var(--monday-red)] text-[var(--monday-red)] p-4 hover:bg-[var(--monday-red)] hover:text-white transition-all text-left font-mono text-sm group"
48
+ >
49
+ <span className="block text-xs opacity-50 mb-1">OPCIÓN B</span>
50
+ <span className="font-bold">CERRAR CANAL</span>
51
+ <span className="block text-xs mt-2 opacity-0 group-hover:opacity-100 transition-opacity">
52
+ No estoy listo. Volveré cuando quiera trabajar.
53
+ </span>
54
+ </button>
55
+ </div>
56
+ </div>
57
+
58
+ {/* Footer */}
59
+ <div className="border-t border-[var(--monday-amber)]/30 p-2 text-center text-[10px] text-[var(--monday-amber)] font-mono">
60
+ BLOCK_ID: {Math.random().toString(36).substr(2, 6).toUpperCase()}
61
+ </div>
62
+ </div>
63
+ </div>
64
+ );
65
+ };
@@ -0,0 +1,137 @@
1
+ import React, { useState } from "react";
2
+ import { UploadCloud, FileText, X } from "lucide-react";
3
+ import { useDocumentStore } from "../../store/documentStore";
4
+ import { useShallow } from "zustand/react/shallow";
5
+
6
+ export function Dropzone() {
7
+ const [isDragging, setIsDragging] = useState(false);
8
+ const [isUploading, setIsUploading] = useState(false);
9
+ const {
10
+ uploadDocument,
11
+ activeDocument,
12
+ documents,
13
+ removeDocument,
14
+ setCurrentDocument,
15
+ } = useDocumentStore(
16
+ useShallow((state) => ({
17
+ uploadDocument: state.uploadDocument,
18
+ activeDocument: state.documents.find(
19
+ (d) => d.id === state.currentDocumentId
20
+ ),
21
+ documents: state.documents,
22
+ removeDocument: state.removeDocument,
23
+ setCurrentDocument: state.setCurrentDocument,
24
+ }))
25
+ );
26
+
27
+ const handleDragOver = (e: React.DragEvent) => {
28
+ e.preventDefault();
29
+ setIsDragging(true);
30
+ };
31
+
32
+ const handleDragLeave = () => {
33
+ setIsDragging(false);
34
+ };
35
+
36
+ const processFile = async (file: File) => {
37
+ if (!file) return;
38
+ setIsUploading(true);
39
+ try {
40
+ await uploadDocument(file);
41
+ } catch (e) {
42
+ console.error(e);
43
+ alert("Error subiendo archivo.");
44
+ } finally {
45
+ setIsUploading(false);
46
+ }
47
+ };
48
+
49
+ const handleDrop = async (e: React.DragEvent) => {
50
+ e.preventDefault();
51
+ setIsDragging(false);
52
+ const files = Array.from(e.dataTransfer.files);
53
+ if (files.length > 0) processFile(files[0]);
54
+ };
55
+
56
+ const handleFileSelect = (e: React.ChangeEvent<HTMLInputElement>) => {
57
+ if (e.target.files && e.target.files.length > 0) {
58
+ processFile(e.target.files[0]);
59
+ }
60
+ };
61
+
62
+ return (
63
+ <div className="w-full flex flex-col gap-4">
64
+ {/* ACTIVE DOCUMENTS LIST */}
65
+ {documents.length > 0 && (
66
+ <div className="flex gap-2 flex-wrap mb-2">
67
+ {documents.map((doc) => (
68
+ <div
69
+ key={doc.id}
70
+ className={`flex items-center gap-2 px-3 py-1.5 rounded border text-xs cursor-pointer transition-colors ${activeDocument?.id === doc.id ? "bg-[var(--wadi-primary)]/10 border-[var(--wadi-primary)] text-[var(--wadi-primary)]" : "bg-[var(--wadi-surface)] border-[var(--wadi-border)] text-[var(--wadi-text-muted)] hover:border-[var(--wadi-text-muted)]"}`}
71
+ onClick={() => setCurrentDocument(doc.id)}
72
+ >
73
+ <FileText size={12} />
74
+ <span className="max-w-[100px] truncate">{doc.filename}</span>
75
+ <button
76
+ onClick={(e) => {
77
+ e.stopPropagation();
78
+ removeDocument(doc.id);
79
+ }}
80
+ className="hover:text-[var(--wadi-alert)]"
81
+ >
82
+ <X size={12} />
83
+ </button>
84
+ </div>
85
+ ))}
86
+ </div>
87
+ )}
88
+
89
+ <div
90
+ onDragOver={handleDragOver}
91
+ onDragLeave={handleDragLeave}
92
+ onDrop={handleDrop}
93
+ className={`relative border border-dashed rounded-3xl p-8 transition-all duration-300 flex flex-col items-center justify-center text-center cursor-pointer overflow-hidden bg-[var(--wadi-bg)]
94
+ ${
95
+ isDragging
96
+ ? "border-[var(--wadi-primary)] bg-zinc-100 scale-[1.005]"
97
+ : "border-zinc-300 hover:border-zinc-400"
98
+ }`}
99
+ >
100
+ <input
101
+ type="file"
102
+ className="absolute inset-0 opacity-0 cursor-pointer"
103
+ accept=".pdf,.txt,.md"
104
+ onChange={handleFileSelect}
105
+ />
106
+
107
+ {isUploading ? (
108
+ <div className="flex flex-col items-center gap-2 animate-pulse">
109
+ <UploadCloud size={32} className="text-[var(--wadi-primary)]" />
110
+ <p className="text-xs font-mono-wadi text-[var(--wadi-primary)] tracking-widest">
111
+ INGIRIENDO DATOS...
112
+ </p>
113
+ </div>
114
+ ) : (
115
+ <div className="flex flex-col items-center gap-2 pointer-events-none">
116
+ <UploadCloud
117
+ size={24}
118
+ className={
119
+ isDragging
120
+ ? "text-[var(--wadi-primary)]"
121
+ : "text-[var(--wadi-text-muted)]"
122
+ }
123
+ />
124
+ <div className="flex flex-col gap-1">
125
+ <p className="text-sm font-medium text-[var(--wadi-text)]">
126
+ Arrastrá tus documentos (sí, los que evitás leer)
127
+ </p>
128
+ <p className="text-[10px] text-[var(--wadi-text-muted)] uppercase tracking-wide">
129
+ PDF, TXT, MD (EVIDENCIA REQUERIDA)
130
+ </p>
131
+ </div>
132
+ </div>
133
+ )}
134
+ </div>
135
+ </div>
136
+ );
137
+ }
@@ -0,0 +1,97 @@
1
+ import { type ButtonHTMLAttributes, forwardRef } from "react";
2
+
3
+ interface ButtonProps extends ButtonHTMLAttributes<HTMLButtonElement> {
4
+ variant?: "primary" | "secondary" | "outline" | "ghost" | "danger";
5
+ size?: "sm" | "md" | "lg";
6
+ fullWidth?: boolean;
7
+ }
8
+
9
+ export const Button = forwardRef<HTMLButtonElement, ButtonProps>(
10
+ (
11
+ {
12
+ className,
13
+ variant = "primary",
14
+ size = "md",
15
+ fullWidth = false,
16
+ style,
17
+ ...props
18
+ },
19
+ ref
20
+ ) => {
21
+ let bg = "var(--accent-primary)";
22
+ let color = "var(--accent-text)";
23
+ let border = "none";
24
+ let padding = "var(--space-2) var(--space-4)";
25
+ let fontSize = "1rem";
26
+
27
+ if (variant === "secondary") {
28
+ bg = "var(--bg-element)";
29
+ color = "var(--text-primary)";
30
+ } else if (variant === "outline") {
31
+ bg = "transparent";
32
+ border = "1px solid var(--border-subtle)";
33
+ color = "var(--text-primary)";
34
+ } else if (variant === "ghost") {
35
+ bg = "transparent";
36
+ color = "var(--text-secondary)";
37
+ } else if (variant === "danger") {
38
+ bg = "transparent";
39
+ color = "var(--error)";
40
+ border = "1px solid var(--error)";
41
+ }
42
+
43
+ if (size === "sm") {
44
+ padding = "var(--space-1) var(--space-3)";
45
+ fontSize = "0.875rem";
46
+ } else if (size === "lg") {
47
+ padding = "var(--space-3) var(--space-5)";
48
+ fontSize = "1.125rem";
49
+ }
50
+
51
+ const baseStyle = {
52
+ display: "inline-flex",
53
+ alignItems: "center",
54
+ justifyContent: "center",
55
+ borderRadius: "var(--radius-md)",
56
+ fontWeight: 500,
57
+ cursor: props.disabled ? "not-allowed" : "pointer",
58
+ opacity: props.disabled ? 0.6 : 1,
59
+ transition: "all 0.2s ease",
60
+ backgroundColor: bg,
61
+ color: color,
62
+ border: border,
63
+ padding: padding,
64
+ fontSize: fontSize,
65
+ width: fullWidth ? "100%" : "auto",
66
+ ...style,
67
+ };
68
+
69
+ return (
70
+ <button
71
+ ref={ref}
72
+ className={className}
73
+ style={baseStyle}
74
+ onMouseEnter={(e) => {
75
+ if (!props.disabled && variant === "primary") {
76
+ e.currentTarget.style.backgroundColor =
77
+ "var(--accent-primary-hover)";
78
+ }
79
+ if (!props.disabled && variant === "outline") {
80
+ e.currentTarget.style.borderColor = "var(--border-focus)";
81
+ }
82
+ }}
83
+ onMouseLeave={(e) => {
84
+ if (!props.disabled && variant === "primary") {
85
+ e.currentTarget.style.backgroundColor = "var(--accent-primary)";
86
+ }
87
+ if (!props.disabled && variant === "outline") {
88
+ e.currentTarget.style.borderColor = "var(--border-subtle)";
89
+ }
90
+ }}
91
+ {...props}
92
+ />
93
+ );
94
+ }
95
+ );
96
+
97
+ Button.displayName = "Button";
@@ -0,0 +1,43 @@
1
+ import { type HTMLAttributes, forwardRef } from "react";
2
+
3
+ interface CardProps extends HTMLAttributes<HTMLDivElement> {
4
+ hoverable?: boolean;
5
+ }
6
+
7
+ export const Card = forwardRef<HTMLDivElement, CardProps>(
8
+ ({ hoverable, style, children, ...props }, ref) => {
9
+ return (
10
+ <div
11
+ ref={ref}
12
+ style={{
13
+ backgroundColor: "var(--bg-panel)",
14
+ border: "1px solid var(--border-subtle)",
15
+ borderRadius: "var(--radius-lg)",
16
+ padding: "var(--space-4)",
17
+ transition: "transform 0.2s, border-color 0.2s, box-shadow 0.2s",
18
+ cursor: hoverable ? "pointer" : "default",
19
+ ...style,
20
+ }}
21
+ onMouseEnter={(e) => {
22
+ if (hoverable) {
23
+ e.currentTarget.style.transform = "translateY(-2px)";
24
+ e.currentTarget.style.borderColor = "var(--border-focus)";
25
+ e.currentTarget.style.boxShadow = "var(--shadow-md)";
26
+ }
27
+ }}
28
+ onMouseLeave={(e) => {
29
+ if (hoverable) {
30
+ e.currentTarget.style.transform = "translateY(0)";
31
+ e.currentTarget.style.borderColor = "var(--border-subtle)";
32
+ e.currentTarget.style.boxShadow = "none";
33
+ }
34
+ }}
35
+ {...props}
36
+ >
37
+ {children}
38
+ </div>
39
+ );
40
+ }
41
+ );
42
+
43
+ Card.displayName = "Card";
@@ -0,0 +1,73 @@
1
+ import { type InputHTMLAttributes, forwardRef } from "react";
2
+
3
+ interface InputProps extends InputHTMLAttributes<HTMLInputElement> {
4
+ label?: string;
5
+ error?: string;
6
+ fullWidth?: boolean;
7
+ }
8
+
9
+ export const Input = forwardRef<HTMLInputElement, InputProps>(
10
+ ({ label, error, fullWidth = true, style, ...props }, ref) => {
11
+ return (
12
+ <div
13
+ style={{
14
+ display: "flex",
15
+ flexDirection: "column",
16
+ width: fullWidth ? "100%" : "auto",
17
+ }}
18
+ >
19
+ {label && (
20
+ <label
21
+ style={{
22
+ marginBottom: "var(--space-1)",
23
+ fontSize: "0.875rem",
24
+ fontWeight: 500,
25
+ color: "var(--text-secondary)",
26
+ }}
27
+ >
28
+ {label}
29
+ </label>
30
+ )}
31
+ <input
32
+ ref={ref}
33
+ style={{
34
+ width: "100%",
35
+ padding: "var(--space-2) var(--space-3)",
36
+ backgroundColor: "var(--bg-app)",
37
+ border: error
38
+ ? "1px solid var(--error)"
39
+ : "1px solid var(--border-subtle)",
40
+ borderRadius: "var(--radius-md)",
41
+ color: "var(--text-primary)",
42
+ fontSize: "1rem",
43
+ outline: "none",
44
+ transition: "border-color 0.2s",
45
+ ...style,
46
+ }}
47
+ onFocus={(e) => {
48
+ if (!error)
49
+ e.currentTarget.style.borderColor = "var(--border-focus)";
50
+ }}
51
+ onBlur={(e) => {
52
+ if (!error)
53
+ e.currentTarget.style.borderColor = "var(--border-subtle)";
54
+ }}
55
+ {...props}
56
+ />
57
+ {error && (
58
+ <span
59
+ style={{
60
+ color: "var(--error)",
61
+ fontSize: "0.8rem",
62
+ marginTop: "4px",
63
+ }}
64
+ >
65
+ {error}
66
+ </span>
67
+ )}
68
+ </div>
69
+ );
70
+ }
71
+ );
72
+
73
+ Input.displayName = "Input";
@@ -0,0 +1,53 @@
1
+ import { type ReactNode } from "react";
2
+ import { createPortal } from "react-dom";
3
+ import { Card } from "./Card";
4
+
5
+ interface ModalProps {
6
+ isOpen: boolean;
7
+ onClose: () => void;
8
+ title?: string;
9
+ children: ReactNode;
10
+ }
11
+
12
+ export const Modal = ({ isOpen, onClose, title, children }: ModalProps) => {
13
+ if (!isOpen) return null;
14
+
15
+ return createPortal(
16
+ <div
17
+ style={{
18
+ position: "fixed",
19
+ top: 0,
20
+ left: 0,
21
+ right: 0,
22
+ bottom: 0,
23
+ backgroundColor: "rgba(0,0,0,0.6)",
24
+ display: "flex",
25
+ alignItems: "center",
26
+ justifyContent: "center",
27
+ zIndex: 100,
28
+ backdropFilter: "blur(4px)",
29
+ }}
30
+ onClick={onClose}
31
+ >
32
+ <Card
33
+ style={{
34
+ width: "100%",
35
+ maxWidth: "480px",
36
+ // We override card hover behavior just in case, though it defaults false
37
+ transform: "none",
38
+ cursor: "default",
39
+ boxShadow: "var(--shadow-lg)",
40
+ }}
41
+ onClick={(e) => e.stopPropagation()} // Prevent closing when clicking inside
42
+ >
43
+ {title && (
44
+ <h3 style={{ marginBottom: "var(--space-4)", fontSize: "1.25rem" }}>
45
+ {title}
46
+ </h3>
47
+ )}
48
+ {children}
49
+ </Card>
50
+ </div>,
51
+ document.body
52
+ );
53
+ };
@@ -0,0 +1,68 @@
1
+ import { forwardRef, type ButtonHTMLAttributes } from "react";
2
+ import { cva, type VariantProps } from "class-variance-authority";
3
+ import { clsx, type ClassValue } from "clsx";
4
+ import { twMerge } from "tailwind-merge";
5
+
6
+ // Utility for class merging
7
+ function cn(...inputs: ClassValue[]) {
8
+ return twMerge(clsx(inputs));
9
+ }
10
+
11
+ const buttonVariants = cva(
12
+ "inline-flex items-center justify-center text-sm font-medium transition-colors focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-[var(--wadi-primary)] disabled:pointer-events-none disabled:opacity-50 font-mono-wadi uppercase tracking-wider",
13
+ {
14
+ variants: {
15
+ variant: {
16
+ default:
17
+ "bg-[var(--wadi-primary)] text-white shadow hover:bg-[var(--wadi-primary)]/90 hover:shadow-[0_0_15px_var(--wadi-primary-glow)]",
18
+ destructive:
19
+ "bg-[var(--wadi-alert)] text-white shadow-sm hover:bg-[var(--wadi-alert)]/90 hover:shadow-[0_0_15px_var(--wadi-alert-glow)]",
20
+ outline:
21
+ "border border-[var(--wadi-border)] bg-transparent shadow-sm hover:bg-[var(--wadi-surface)] hover:text-[var(--wadi-text)]",
22
+ ghost: "hover:bg-[var(--wadi-surface)] hover:text-[var(--wadi-text)]",
23
+ link: "text-[var(--wadi-primary)] underline-offset-4 hover:underline",
24
+ glass:
25
+ "wadi-glass hover:bg-[rgba(139,92,246,0.1)] text-[var(--wadi-primary)] border-[var(--wadi-primary)]/30",
26
+ },
27
+ size: {
28
+ default: "h-9 px-4 py-2",
29
+ sm: "h-8 px-3 text-xs",
30
+ lg: "h-10 px-8",
31
+ icon: "h-9 w-9",
32
+ },
33
+ radius: {
34
+ none: "rounded-none",
35
+ sm: "rounded-[2px]",
36
+ md: "rounded-md",
37
+ full: "rounded-full",
38
+ },
39
+ },
40
+ defaultVariants: {
41
+ variant: "default",
42
+ size: "default",
43
+ radius: "sm",
44
+ },
45
+ }
46
+ );
47
+
48
+ export interface ButtonProps
49
+ extends
50
+ ButtonHTMLAttributes<HTMLButtonElement>,
51
+ VariantProps<typeof buttonVariants> {
52
+ asChild?: boolean;
53
+ }
54
+
55
+ const Button = forwardRef<HTMLButtonElement, ButtonProps>(
56
+ ({ className, variant, size, radius, ...props }, ref) => {
57
+ return (
58
+ <button
59
+ className={cn(buttonVariants({ variant, size, radius, className }))}
60
+ ref={ref}
61
+ {...props}
62
+ />
63
+ );
64
+ }
65
+ );
66
+ Button.displayName = "Button";
67
+
68
+ export { Button };
@@ -0,0 +1,86 @@
1
+ import { type HTMLAttributes, forwardRef } from "react";
2
+ import { clsx, type ClassValue } from "clsx";
3
+ import { twMerge } from "tailwind-merge";
4
+
5
+ function cn(...inputs: ClassValue[]) {
6
+ return twMerge(clsx(inputs));
7
+ }
8
+
9
+ const Card = forwardRef<HTMLDivElement, HTMLAttributes<HTMLDivElement>>(
10
+ ({ className, ...props }, ref) => (
11
+ <div
12
+ ref={ref}
13
+ className={cn(
14
+ "rounded-sm border border-[var(--wadi-border)] bg-[var(--wadi-surface)]/50 text-[var(--wadi-text)] shadow backdrop-blur-sm",
15
+ className
16
+ )}
17
+ {...props}
18
+ />
19
+ )
20
+ );
21
+ Card.displayName = "Card";
22
+
23
+ const CardHeader = forwardRef<HTMLDivElement, HTMLAttributes<HTMLDivElement>>(
24
+ ({ className, ...props }, ref) => (
25
+ <div
26
+ ref={ref}
27
+ className={cn("flex flex-col space-y-1.5 p-6", className)}
28
+ {...props}
29
+ />
30
+ )
31
+ );
32
+ CardHeader.displayName = "CardHeader";
33
+
34
+ const CardTitle = forwardRef<
35
+ HTMLParagraphElement,
36
+ HTMLAttributes<HTMLHeadingElement>
37
+ >(({ className, ...props }, ref) => (
38
+ <h3
39
+ ref={ref}
40
+ className={cn(
41
+ "font-semibold leading-none tracking-tight font-mono-wadi uppercase text-[var(--wadi-primary)]",
42
+ className
43
+ )}
44
+ {...props}
45
+ />
46
+ ));
47
+ CardTitle.displayName = "CardTitle";
48
+
49
+ const CardDescription = forwardRef<
50
+ HTMLParagraphElement,
51
+ HTMLAttributes<HTMLParagraphElement>
52
+ >(({ className, ...props }, ref) => (
53
+ <p
54
+ ref={ref}
55
+ className={cn("text-sm text-[var(--wadi-text-muted)]", className)}
56
+ {...props}
57
+ />
58
+ ));
59
+ CardDescription.displayName = "CardDescription";
60
+
61
+ const CardContent = forwardRef<HTMLDivElement, HTMLAttributes<HTMLDivElement>>(
62
+ ({ className, ...props }, ref) => (
63
+ <div ref={ref} className={cn("p-6 pt-0", className)} {...props} />
64
+ )
65
+ );
66
+ CardContent.displayName = "CardContent";
67
+
68
+ const CardFooter = forwardRef<HTMLDivElement, HTMLAttributes<HTMLDivElement>>(
69
+ ({ className, ...props }, ref) => (
70
+ <div
71
+ ref={ref}
72
+ className={cn("flex items-center p-6 pt-0", className)}
73
+ {...props}
74
+ />
75
+ )
76
+ );
77
+ CardFooter.displayName = "CardFooter";
78
+
79
+ export {
80
+ Card,
81
+ CardHeader,
82
+ CardFooter,
83
+ CardTitle,
84
+ CardDescription,
85
+ CardContent,
86
+ };
@@ -0,0 +1,28 @@
1
+ import { type InputHTMLAttributes, forwardRef } from "react";
2
+ import { clsx, type ClassValue } from "clsx";
3
+ import { twMerge } from "tailwind-merge";
4
+
5
+ function cn(...inputs: ClassValue[]) {
6
+ return twMerge(clsx(inputs));
7
+ }
8
+
9
+ export type InputProps = InputHTMLAttributes<HTMLInputElement>;
10
+
11
+ const Input = forwardRef<HTMLInputElement, InputProps>(
12
+ ({ className, type, ...props }, ref) => {
13
+ return (
14
+ <input
15
+ type={type}
16
+ className={cn(
17
+ "flex h-12 w-full bg-transparent border-b border-[var(--wadi-border)] px-3 py-1 text-base shadow-sm transition-all file:border-0 file:bg-transparent file:text-sm file:font-medium placeholder:text-[var(--wadi-text-muted)] focus-visible:outline-none focus-visible:border-[var(--wadi-primary)] focus-visible:shadow-[0_1px_0_0_var(--wadi-primary)] disabled:cursor-not-allowed disabled:opacity-50 rounded-none font-sans",
18
+ className
19
+ )}
20
+ ref={ref}
21
+ {...props}
22
+ />
23
+ );
24
+ }
25
+ );
26
+ Input.displayName = "Input";
27
+
28
+ export { Input };