@pylonsync/create-pylon 0.3.343 → 0.3.345

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 (422) hide show
  1. package/bin/create-pylon.js +35 -0
  2. package/package.json +1 -1
  3. package/templates/agency/components/ui/badge.tsx +37 -0
  4. package/templates/agency/components/ui/dialog.tsx +110 -0
  5. package/templates/agency/components/ui/input.tsx +30 -0
  6. package/templates/agency/components/ui/label.tsx +21 -0
  7. package/templates/agency/components/ui/select.tsx +39 -0
  8. package/templates/agency/components/ui/table.tsx +124 -0
  9. package/templates/agency/components/ui/textarea.tsx +24 -0
  10. package/templates/agency/package.json +1 -0
  11. package/templates/ai-chat/components/ui/badge.tsx +37 -0
  12. package/templates/ai-chat/components/ui/button.tsx +56 -0
  13. package/templates/ai-chat/components/ui/card.tsx +90 -0
  14. package/templates/ai-chat/components/ui/dialog.tsx +110 -0
  15. package/templates/ai-chat/components/ui/input.tsx +30 -0
  16. package/templates/ai-chat/components/ui/label.tsx +21 -0
  17. package/templates/ai-chat/components/ui/select.tsx +39 -0
  18. package/templates/ai-chat/components/ui/table.tsx +124 -0
  19. package/templates/ai-chat/components/ui/textarea.tsx +24 -0
  20. package/templates/ai-chat/package.json +1 -0
  21. package/templates/ai-studio/components/ui/badge.tsx +37 -0
  22. package/templates/ai-studio/components/ui/button.tsx +56 -0
  23. package/templates/ai-studio/components/ui/card.tsx +90 -0
  24. package/templates/ai-studio/components/ui/dialog.tsx +110 -0
  25. package/templates/ai-studio/components/ui/input.tsx +30 -0
  26. package/templates/ai-studio/components/ui/label.tsx +21 -0
  27. package/templates/ai-studio/components/ui/select.tsx +39 -0
  28. package/templates/ai-studio/components/ui/table.tsx +124 -0
  29. package/templates/ai-studio/components/ui/textarea.tsx +24 -0
  30. package/templates/ai-studio/package.json +1 -0
  31. package/templates/barebones/components/ui/badge.tsx +37 -0
  32. package/templates/barebones/components/ui/dialog.tsx +110 -0
  33. package/templates/barebones/components/ui/input.tsx +30 -0
  34. package/templates/barebones/components/ui/label.tsx +21 -0
  35. package/templates/barebones/components/ui/select.tsx +39 -0
  36. package/templates/barebones/components/ui/table.tsx +124 -0
  37. package/templates/barebones/components/ui/textarea.tsx +24 -0
  38. package/templates/barebones/package.json +1 -0
  39. package/templates/chat/components/ui/badge.tsx +37 -0
  40. package/templates/chat/components/ui/dialog.tsx +110 -0
  41. package/templates/chat/components/ui/input.tsx +30 -0
  42. package/templates/chat/components/ui/label.tsx +21 -0
  43. package/templates/chat/components/ui/select.tsx +39 -0
  44. package/templates/chat/components/ui/table.tsx +124 -0
  45. package/templates/chat/components/ui/textarea.tsx +24 -0
  46. package/templates/chat/package.json +1 -0
  47. package/templates/consumer/components/ui/badge.tsx +37 -0
  48. package/templates/consumer/components/ui/dialog.tsx +110 -0
  49. package/templates/consumer/components/ui/input.tsx +30 -0
  50. package/templates/consumer/components/ui/label.tsx +21 -0
  51. package/templates/consumer/components/ui/select.tsx +39 -0
  52. package/templates/consumer/components/ui/table.tsx +124 -0
  53. package/templates/consumer/components/ui/textarea.tsx +24 -0
  54. package/templates/consumer/package.json +1 -0
  55. package/templates/creator/components/ui/badge.tsx +37 -0
  56. package/templates/creator/components/ui/dialog.tsx +110 -0
  57. package/templates/creator/components/ui/input.tsx +30 -0
  58. package/templates/creator/components/ui/label.tsx +21 -0
  59. package/templates/creator/components/ui/select.tsx +39 -0
  60. package/templates/creator/components/ui/table.tsx +124 -0
  61. package/templates/creator/components/ui/textarea.tsx +24 -0
  62. package/templates/creator/package.json +1 -0
  63. package/templates/crm/AGENTS.md +116 -0
  64. package/templates/crm/CLAUDE.md +7 -0
  65. package/templates/crm/README.md +96 -0
  66. package/templates/crm/app/companies/companies-view.tsx +129 -0
  67. package/templates/crm/app/companies/page.tsx +17 -0
  68. package/templates/crm/app/contacts/contacts-view.tsx +139 -0
  69. package/templates/crm/app/contacts/page.tsx +17 -0
  70. package/templates/crm/app/deals/[id]/deal-view.tsx +189 -0
  71. package/templates/crm/app/deals/[id]/page.tsx +23 -0
  72. package/templates/crm/app/error.tsx +43 -0
  73. package/templates/crm/app/globals.css +201 -0
  74. package/templates/crm/app/layout.tsx +31 -0
  75. package/templates/crm/app/login/auth-form.tsx +122 -0
  76. package/templates/crm/app/login/page.tsx +38 -0
  77. package/templates/crm/app/not-found.tsx +29 -0
  78. package/templates/crm/app/page.tsx +38 -0
  79. package/templates/crm/app/pipeline-view.tsx +99 -0
  80. package/templates/crm/app/robots.ts +12 -0
  81. package/templates/crm/app/sitemap.ts +27 -0
  82. package/templates/crm/app/workspace.tsx +231 -0
  83. package/templates/crm/app.ts +171 -0
  84. package/templates/crm/bunfig +4 -0
  85. package/templates/crm/components/activity-timeline.tsx +133 -0
  86. package/templates/crm/components/avatar.tsx +40 -0
  87. package/templates/crm/components/board-skeleton.tsx +44 -0
  88. package/templates/crm/components/command-palette.tsx +162 -0
  89. package/templates/crm/components/data-table.tsx +90 -0
  90. package/templates/crm/components/deal-card.tsx +91 -0
  91. package/templates/crm/components/deal-dialog.tsx +169 -0
  92. package/templates/crm/components/empty-state.tsx +43 -0
  93. package/templates/crm/components/kbd.tsx +23 -0
  94. package/templates/crm/components/metrics-bar.tsx +46 -0
  95. package/templates/crm/components/page-header.tsx +36 -0
  96. package/templates/crm/components/pipeline-board.tsx +105 -0
  97. package/templates/crm/components/record-dialog.tsx +126 -0
  98. package/templates/crm/components/sidebar.tsx +112 -0
  99. package/templates/crm/components/stage-badge.tsx +33 -0
  100. package/templates/crm/components/ui/badge.tsx +37 -0
  101. package/templates/crm/components/ui/button.tsx +56 -0
  102. package/templates/crm/components/ui/card.tsx +90 -0
  103. package/templates/crm/components/ui/dialog.tsx +110 -0
  104. package/templates/crm/components/ui/input.tsx +30 -0
  105. package/templates/crm/components/ui/label.tsx +21 -0
  106. package/templates/crm/components/ui/select.tsx +39 -0
  107. package/templates/crm/components/ui/table.tsx +124 -0
  108. package/templates/crm/components/ui/textarea.tsx +24 -0
  109. package/templates/crm/components.json +20 -0
  110. package/templates/crm/functions/createDeal.ts +59 -0
  111. package/templates/crm/functions/logActivity.ts +49 -0
  112. package/templates/crm/functions/moveDeal.ts +53 -0
  113. package/templates/crm/functions/seedWorkspace.ts +63 -0
  114. package/templates/crm/gitignore +10 -0
  115. package/templates/crm/lib/pipeline.ts +221 -0
  116. package/templates/crm/lib/search.ts +78 -0
  117. package/templates/crm/lib/seed.ts +130 -0
  118. package/templates/crm/lib/utils.ts +10 -0
  119. package/templates/crm/package.json +39 -0
  120. package/templates/crm/tests/components.test.tsx +245 -0
  121. package/templates/crm/tests/pipeline.test.ts +219 -0
  122. package/templates/crm/tests/search.test.ts +83 -0
  123. package/templates/crm/tests/setup.ts +5 -0
  124. package/templates/crm/tsconfig.json +33 -0
  125. package/templates/default/components/ui/badge.tsx +37 -0
  126. package/templates/default/components/ui/dialog.tsx +110 -0
  127. package/templates/default/components/ui/input.tsx +30 -0
  128. package/templates/default/components/ui/label.tsx +21 -0
  129. package/templates/default/components/ui/select.tsx +39 -0
  130. package/templates/default/components/ui/table.tsx +124 -0
  131. package/templates/default/components/ui/textarea.tsx +24 -0
  132. package/templates/default/package.json +1 -0
  133. package/templates/directory/components/ui/badge.tsx +37 -0
  134. package/templates/directory/components/ui/dialog.tsx +110 -0
  135. package/templates/directory/components/ui/input.tsx +30 -0
  136. package/templates/directory/components/ui/label.tsx +21 -0
  137. package/templates/directory/components/ui/select.tsx +39 -0
  138. package/templates/directory/components/ui/table.tsx +124 -0
  139. package/templates/directory/components/ui/textarea.tsx +24 -0
  140. package/templates/directory/package.json +1 -0
  141. package/templates/helpdesk/AGENTS.md +116 -0
  142. package/templates/helpdesk/CLAUDE.md +7 -0
  143. package/templates/helpdesk/README.md +90 -0
  144. package/templates/helpdesk/app/customers/customers-view.tsx +140 -0
  145. package/templates/helpdesk/app/customers/page.tsx +17 -0
  146. package/templates/helpdesk/app/error.tsx +43 -0
  147. package/templates/helpdesk/app/globals.css +201 -0
  148. package/templates/helpdesk/app/inbox-view.tsx +147 -0
  149. package/templates/helpdesk/app/layout.tsx +31 -0
  150. package/templates/helpdesk/app/login/auth-form.tsx +122 -0
  151. package/templates/helpdesk/app/login/page.tsx +38 -0
  152. package/templates/helpdesk/app/not-found.tsx +29 -0
  153. package/templates/helpdesk/app/page.tsx +38 -0
  154. package/templates/helpdesk/app/robots.ts +12 -0
  155. package/templates/helpdesk/app/sitemap.ts +27 -0
  156. package/templates/helpdesk/app/tickets/[id]/page.tsx +23 -0
  157. package/templates/helpdesk/app/tickets/[id]/ticket-view.tsx +164 -0
  158. package/templates/helpdesk/app/workspace.tsx +210 -0
  159. package/templates/helpdesk/app.ts +142 -0
  160. package/templates/helpdesk/bunfig +4 -0
  161. package/templates/helpdesk/components/avatar.tsx +40 -0
  162. package/templates/helpdesk/components/command-palette.tsx +162 -0
  163. package/templates/helpdesk/components/data-table.tsx +90 -0
  164. package/templates/helpdesk/components/empty-state.tsx +43 -0
  165. package/templates/helpdesk/components/kbd.tsx +23 -0
  166. package/templates/helpdesk/components/new-ticket-dialog.tsx +147 -0
  167. package/templates/helpdesk/components/page-header.tsx +36 -0
  168. package/templates/helpdesk/components/priority-badge.tsx +61 -0
  169. package/templates/helpdesk/components/record-dialog.tsx +126 -0
  170. package/templates/helpdesk/components/sidebar.tsx +111 -0
  171. package/templates/helpdesk/components/sla-indicator.tsx +47 -0
  172. package/templates/helpdesk/components/thread.tsx +143 -0
  173. package/templates/helpdesk/components/ticket-list.tsx +78 -0
  174. package/templates/helpdesk/components/ui/badge.tsx +37 -0
  175. package/templates/helpdesk/components/ui/button.tsx +56 -0
  176. package/templates/helpdesk/components/ui/card.tsx +90 -0
  177. package/templates/helpdesk/components/ui/dialog.tsx +110 -0
  178. package/templates/helpdesk/components/ui/input.tsx +30 -0
  179. package/templates/helpdesk/components/ui/label.tsx +21 -0
  180. package/templates/helpdesk/components/ui/select.tsx +39 -0
  181. package/templates/helpdesk/components/ui/table.tsx +124 -0
  182. package/templates/helpdesk/components/ui/textarea.tsx +24 -0
  183. package/templates/helpdesk/components.json +20 -0
  184. package/templates/helpdesk/functions/createTicket.ts +62 -0
  185. package/templates/helpdesk/functions/replyToTicket.ts +55 -0
  186. package/templates/helpdesk/functions/seedWorkspace.ts +52 -0
  187. package/templates/helpdesk/functions/setTicketState.ts +58 -0
  188. package/templates/helpdesk/gitignore +10 -0
  189. package/templates/helpdesk/lib/format.ts +53 -0
  190. package/templates/helpdesk/lib/search.ts +78 -0
  191. package/templates/helpdesk/lib/seed.ts +185 -0
  192. package/templates/helpdesk/lib/tickets.ts +184 -0
  193. package/templates/helpdesk/lib/utils.ts +10 -0
  194. package/templates/helpdesk/package.json +39 -0
  195. package/templates/helpdesk/tests/components.test.tsx +202 -0
  196. package/templates/helpdesk/tests/search.test.ts +83 -0
  197. package/templates/helpdesk/tests/setup.ts +5 -0
  198. package/templates/helpdesk/tests/tickets.test.ts +215 -0
  199. package/templates/helpdesk/tsconfig.json +33 -0
  200. package/templates/inventory/AGENTS.md +116 -0
  201. package/templates/inventory/CLAUDE.md +7 -0
  202. package/templates/inventory/README.md +103 -0
  203. package/templates/inventory/app/error.tsx +43 -0
  204. package/templates/inventory/app/globals.css +201 -0
  205. package/templates/inventory/app/layout.tsx +31 -0
  206. package/templates/inventory/app/login/auth-form.tsx +122 -0
  207. package/templates/inventory/app/login/page.tsx +38 -0
  208. package/templates/inventory/app/movements/movements-view.tsx +103 -0
  209. package/templates/inventory/app/movements/page.tsx +17 -0
  210. package/templates/inventory/app/not-found.tsx +29 -0
  211. package/templates/inventory/app/page.tsx +34 -0
  212. package/templates/inventory/app/products/[id]/page.tsx +23 -0
  213. package/templates/inventory/app/products/[id]/product-view.tsx +178 -0
  214. package/templates/inventory/app/products-view.tsx +213 -0
  215. package/templates/inventory/app/robots.ts +12 -0
  216. package/templates/inventory/app/sitemap.ts +27 -0
  217. package/templates/inventory/app/workspace.tsx +172 -0
  218. package/templates/inventory/app.ts +154 -0
  219. package/templates/inventory/bunfig +4 -0
  220. package/templates/inventory/components/avatar.tsx +40 -0
  221. package/templates/inventory/components/command-palette.tsx +162 -0
  222. package/templates/inventory/components/data-table.tsx +90 -0
  223. package/templates/inventory/components/empty-state.tsx +43 -0
  224. package/templates/inventory/components/kbd.tsx +23 -0
  225. package/templates/inventory/components/movement-dialog.tsx +182 -0
  226. package/templates/inventory/components/page-header.tsx +36 -0
  227. package/templates/inventory/components/record-dialog.tsx +126 -0
  228. package/templates/inventory/components/sidebar.tsx +111 -0
  229. package/templates/inventory/components/stock-level.tsx +47 -0
  230. package/templates/inventory/components/summary-bar.tsx +56 -0
  231. package/templates/inventory/components/ui/badge.tsx +37 -0
  232. package/templates/inventory/components/ui/button.tsx +56 -0
  233. package/templates/inventory/components/ui/card.tsx +90 -0
  234. package/templates/inventory/components/ui/dialog.tsx +110 -0
  235. package/templates/inventory/components/ui/input.tsx +30 -0
  236. package/templates/inventory/components/ui/label.tsx +21 -0
  237. package/templates/inventory/components/ui/select.tsx +39 -0
  238. package/templates/inventory/components/ui/table.tsx +124 -0
  239. package/templates/inventory/components/ui/textarea.tsx +24 -0
  240. package/templates/inventory/components.json +20 -0
  241. package/templates/inventory/functions/recordMovement.ts +72 -0
  242. package/templates/inventory/functions/seedWorkspace.ts +40 -0
  243. package/templates/inventory/gitignore +10 -0
  244. package/templates/inventory/lib/format.ts +53 -0
  245. package/templates/inventory/lib/search.ts +78 -0
  246. package/templates/inventory/lib/seed.ts +102 -0
  247. package/templates/inventory/lib/stock.ts +207 -0
  248. package/templates/inventory/lib/utils.ts +10 -0
  249. package/templates/inventory/package.json +39 -0
  250. package/templates/inventory/tests/components.test.tsx +155 -0
  251. package/templates/inventory/tests/search.test.ts +83 -0
  252. package/templates/inventory/tests/setup.ts +5 -0
  253. package/templates/inventory/tests/stock.test.ts +255 -0
  254. package/templates/inventory/tsconfig.json +33 -0
  255. package/templates/invoices/AGENTS.md +116 -0
  256. package/templates/invoices/CLAUDE.md +7 -0
  257. package/templates/invoices/README.md +99 -0
  258. package/templates/invoices/app/clients/clients-view.tsx +130 -0
  259. package/templates/invoices/app/clients/page.tsx +17 -0
  260. package/templates/invoices/app/error.tsx +43 -0
  261. package/templates/invoices/app/globals.css +201 -0
  262. package/templates/invoices/app/invoices/[id]/invoice-view.tsx +253 -0
  263. package/templates/invoices/app/invoices/[id]/page.tsx +23 -0
  264. package/templates/invoices/app/invoices-view.tsx +183 -0
  265. package/templates/invoices/app/layout.tsx +31 -0
  266. package/templates/invoices/app/login/auth-form.tsx +122 -0
  267. package/templates/invoices/app/login/page.tsx +38 -0
  268. package/templates/invoices/app/not-found.tsx +29 -0
  269. package/templates/invoices/app/page.tsx +36 -0
  270. package/templates/invoices/app/robots.ts +12 -0
  271. package/templates/invoices/app/sitemap.ts +27 -0
  272. package/templates/invoices/app/workspace.tsx +174 -0
  273. package/templates/invoices/app.ts +169 -0
  274. package/templates/invoices/bunfig +4 -0
  275. package/templates/invoices/components/avatar.tsx +40 -0
  276. package/templates/invoices/components/command-palette.tsx +162 -0
  277. package/templates/invoices/components/data-table.tsx +90 -0
  278. package/templates/invoices/components/empty-state.tsx +43 -0
  279. package/templates/invoices/components/kbd.tsx +23 -0
  280. package/templates/invoices/components/line-items.tsx +172 -0
  281. package/templates/invoices/components/page-header.tsx +36 -0
  282. package/templates/invoices/components/payment-dialog.tsx +132 -0
  283. package/templates/invoices/components/record-dialog.tsx +126 -0
  284. package/templates/invoices/components/sidebar.tsx +111 -0
  285. package/templates/invoices/components/status-badge.tsx +35 -0
  286. package/templates/invoices/components/summary-bar.tsx +65 -0
  287. package/templates/invoices/components/totals-panel.tsx +70 -0
  288. package/templates/invoices/components/ui/badge.tsx +37 -0
  289. package/templates/invoices/components/ui/button.tsx +56 -0
  290. package/templates/invoices/components/ui/card.tsx +90 -0
  291. package/templates/invoices/components/ui/dialog.tsx +110 -0
  292. package/templates/invoices/components/ui/input.tsx +30 -0
  293. package/templates/invoices/components/ui/label.tsx +21 -0
  294. package/templates/invoices/components/ui/select.tsx +39 -0
  295. package/templates/invoices/components/ui/table.tsx +124 -0
  296. package/templates/invoices/components/ui/textarea.tsx +24 -0
  297. package/templates/invoices/components.json +20 -0
  298. package/templates/invoices/functions/createInvoice.ts +49 -0
  299. package/templates/invoices/functions/recordPayment.ts +72 -0
  300. package/templates/invoices/functions/seedWorkspace.ts +57 -0
  301. package/templates/invoices/functions/setInvoiceStatus.ts +35 -0
  302. package/templates/invoices/gitignore +10 -0
  303. package/templates/invoices/lib/billing.ts +259 -0
  304. package/templates/invoices/lib/format.ts +53 -0
  305. package/templates/invoices/lib/search.ts +78 -0
  306. package/templates/invoices/lib/seed.ts +190 -0
  307. package/templates/invoices/lib/utils.ts +10 -0
  308. package/templates/invoices/package.json +39 -0
  309. package/templates/invoices/tests/billing.test.ts +283 -0
  310. package/templates/invoices/tests/components.test.tsx +172 -0
  311. package/templates/invoices/tests/search.test.ts +83 -0
  312. package/templates/invoices/tests/setup.ts +5 -0
  313. package/templates/invoices/tsconfig.json +33 -0
  314. package/templates/local-service/components/ui/badge.tsx +37 -0
  315. package/templates/local-service/components/ui/dialog.tsx +110 -0
  316. package/templates/local-service/components/ui/input.tsx +30 -0
  317. package/templates/local-service/components/ui/label.tsx +21 -0
  318. package/templates/local-service/components/ui/select.tsx +39 -0
  319. package/templates/local-service/components/ui/table.tsx +124 -0
  320. package/templates/local-service/components/ui/textarea.tsx +24 -0
  321. package/templates/local-service/package.json +1 -0
  322. package/templates/marketplace/components/ui/badge.tsx +37 -0
  323. package/templates/marketplace/components/ui/button.tsx +56 -0
  324. package/templates/marketplace/components/ui/card.tsx +90 -0
  325. package/templates/marketplace/components/ui/dialog.tsx +110 -0
  326. package/templates/marketplace/components/ui/input.tsx +30 -0
  327. package/templates/marketplace/components/ui/label.tsx +21 -0
  328. package/templates/marketplace/components/ui/select.tsx +39 -0
  329. package/templates/marketplace/components/ui/table.tsx +124 -0
  330. package/templates/marketplace/components/ui/textarea.tsx +24 -0
  331. package/templates/marketplace/lib/utils.ts +10 -0
  332. package/templates/marketplace/package.json +1 -0
  333. package/templates/projects/AGENTS.md +116 -0
  334. package/templates/projects/CLAUDE.md +7 -0
  335. package/templates/projects/README.md +96 -0
  336. package/templates/projects/app/clients/clients-view.tsx +126 -0
  337. package/templates/projects/app/clients/page.tsx +17 -0
  338. package/templates/projects/app/error.tsx +43 -0
  339. package/templates/projects/app/globals.css +201 -0
  340. package/templates/projects/app/layout.tsx +31 -0
  341. package/templates/projects/app/login/auth-form.tsx +122 -0
  342. package/templates/projects/app/login/page.tsx +38 -0
  343. package/templates/projects/app/not-found.tsx +29 -0
  344. package/templates/projects/app/page.tsx +30 -0
  345. package/templates/projects/app/projects/[id]/page.tsx +23 -0
  346. package/templates/projects/app/projects/[id]/project-view.tsx +179 -0
  347. package/templates/projects/app/projects-view.tsx +181 -0
  348. package/templates/projects/app/robots.ts +12 -0
  349. package/templates/projects/app/sitemap.ts +27 -0
  350. package/templates/projects/app/workspace.tsx +190 -0
  351. package/templates/projects/app.ts +186 -0
  352. package/templates/projects/bunfig +4 -0
  353. package/templates/projects/components/avatar.tsx +40 -0
  354. package/templates/projects/components/board-skeleton.tsx +37 -0
  355. package/templates/projects/components/budget-bar.tsx +61 -0
  356. package/templates/projects/components/command-palette.tsx +162 -0
  357. package/templates/projects/components/data-table.tsx +90 -0
  358. package/templates/projects/components/empty-state.tsx +43 -0
  359. package/templates/projects/components/kbd.tsx +23 -0
  360. package/templates/projects/components/page-header.tsx +36 -0
  361. package/templates/projects/components/record-dialog.tsx +126 -0
  362. package/templates/projects/components/sidebar.tsx +111 -0
  363. package/templates/projects/components/task-board.tsx +109 -0
  364. package/templates/projects/components/task-card.tsx +77 -0
  365. package/templates/projects/components/time-dialog.tsx +114 -0
  366. package/templates/projects/components/ui/badge.tsx +37 -0
  367. package/templates/projects/components/ui/button.tsx +56 -0
  368. package/templates/projects/components/ui/card.tsx +90 -0
  369. package/templates/projects/components/ui/dialog.tsx +110 -0
  370. package/templates/projects/components/ui/input.tsx +30 -0
  371. package/templates/projects/components/ui/label.tsx +21 -0
  372. package/templates/projects/components/ui/select.tsx +39 -0
  373. package/templates/projects/components/ui/table.tsx +124 -0
  374. package/templates/projects/components/ui/textarea.tsx +24 -0
  375. package/templates/projects/components.json +20 -0
  376. package/templates/projects/functions/logTime.ts +49 -0
  377. package/templates/projects/functions/moveTask.ts +40 -0
  378. package/templates/projects/functions/seedWorkspace.ts +59 -0
  379. package/templates/projects/gitignore +10 -0
  380. package/templates/projects/lib/format.ts +53 -0
  381. package/templates/projects/lib/search.ts +78 -0
  382. package/templates/projects/lib/seed.ts +140 -0
  383. package/templates/projects/lib/utils.ts +10 -0
  384. package/templates/projects/lib/work.ts +233 -0
  385. package/templates/projects/package.json +39 -0
  386. package/templates/projects/tests/components.test.tsx +200 -0
  387. package/templates/projects/tests/search.test.ts +83 -0
  388. package/templates/projects/tests/setup.ts +5 -0
  389. package/templates/projects/tests/work.test.ts +238 -0
  390. package/templates/projects/tsconfig.json +33 -0
  391. package/templates/restaurant/components/ui/badge.tsx +37 -0
  392. package/templates/restaurant/components/ui/dialog.tsx +110 -0
  393. package/templates/restaurant/components/ui/input.tsx +30 -0
  394. package/templates/restaurant/components/ui/label.tsx +21 -0
  395. package/templates/restaurant/components/ui/select.tsx +39 -0
  396. package/templates/restaurant/components/ui/table.tsx +124 -0
  397. package/templates/restaurant/components/ui/textarea.tsx +24 -0
  398. package/templates/restaurant/package.json +1 -0
  399. package/templates/shop/components/ui/badge.tsx +37 -0
  400. package/templates/shop/components/ui/dialog.tsx +110 -0
  401. package/templates/shop/components/ui/input.tsx +30 -0
  402. package/templates/shop/components/ui/label.tsx +21 -0
  403. package/templates/shop/components/ui/select.tsx +39 -0
  404. package/templates/shop/components/ui/table.tsx +124 -0
  405. package/templates/shop/components/ui/textarea.tsx +24 -0
  406. package/templates/shop/package.json +1 -0
  407. package/templates/todo/components/ui/badge.tsx +37 -0
  408. package/templates/todo/components/ui/dialog.tsx +110 -0
  409. package/templates/todo/components/ui/input.tsx +30 -0
  410. package/templates/todo/components/ui/label.tsx +21 -0
  411. package/templates/todo/components/ui/select.tsx +39 -0
  412. package/templates/todo/components/ui/table.tsx +124 -0
  413. package/templates/todo/components/ui/textarea.tsx +24 -0
  414. package/templates/todo/package.json +1 -0
  415. package/templates/waitlist/components/ui/badge.tsx +37 -0
  416. package/templates/waitlist/components/ui/dialog.tsx +110 -0
  417. package/templates/waitlist/components/ui/input.tsx +30 -0
  418. package/templates/waitlist/components/ui/label.tsx +21 -0
  419. package/templates/waitlist/components/ui/select.tsx +39 -0
  420. package/templates/waitlist/components/ui/table.tsx +124 -0
  421. package/templates/waitlist/components/ui/textarea.tsx +24 -0
  422. package/templates/waitlist/package.json +1 -0
@@ -0,0 +1,43 @@
1
+ import React from "react";
2
+ import { type ErrorBoundaryProps } from "@pylonsync/react";
3
+ import { Button } from "@/components/ui/button";
4
+
5
+ // `app/error.tsx` → the error boundary for this segment. It catches a throw
6
+ // in any page/layout below it and renders at HTTP 500. It's HYDRATED, so
7
+ // this is a real interactive client component: `reset()` re-attempts the
8
+ // route, and useState/onClick work. The thrown error reaches the client as
9
+ // `{ message, digest }` only — the stack stays in the dev overlay
10
+ // (PYLON_DEV_MODE) and the server logs, never in the page.
11
+ export default function Error({ error, reset }: ErrorBoundaryProps) {
12
+ const [tries, setTries] = React.useState(0);
13
+ return (
14
+ <div className="space-y-6">
15
+ <section>
16
+ <h1 className="text-2xl font-semibold tracking-tight">
17
+ Something went wrong
18
+ </h1>
19
+ <p className="mt-2 text-muted-foreground">{error.message}</p>
20
+ {error.digest ? (
21
+ <p className="mt-1 text-xs text-muted-foreground/70">
22
+ Reference: <code>{error.digest}</code>
23
+ </p>
24
+ ) : null}
25
+ </section>
26
+ <div className="flex items-center gap-3">
27
+ <Button
28
+ onClick={() => {
29
+ setTries((n) => n + 1);
30
+ reset();
31
+ }}
32
+ >
33
+ Try again
34
+ </Button>
35
+ {tries > 0 ? (
36
+ <span className="text-sm text-muted-foreground">
37
+ Retried {tries} {tries === 1 ? "time" : "times"}
38
+ </span>
39
+ ) : null}
40
+ </div>
41
+ </div>
42
+ );
43
+ }
@@ -0,0 +1,201 @@
1
+ @import "tailwindcss";
2
+ @import "tw-animate-css";
3
+
4
+ @source "../app/**/*.{tsx,ts,jsx,js}";
5
+ @source "../components/**/*.{tsx,ts,jsx,js}";
6
+
7
+ @custom-variant dark (&:where(.dark, .dark *));
8
+
9
+ /* ---------------------------------------------------------------------------
10
+ Design tokens.
11
+
12
+ Tuned for a dense internal tool rather than a marketing page: a near-neutral
13
+ surface ramp, hairline borders instead of shadows, and one accent used
14
+ sparingly so status colour still means something. Dark is the primary theme —
15
+ `app/layout.tsx` sets `class="dark"` — and light is a real, tested
16
+ alternative, not an afterthought.
17
+
18
+ These are the same variable names shadcn/ui generates against, so
19
+ `npx shadcn@latest add <component>` drops in already themed.
20
+ --------------------------------------------------------------------------- */
21
+ :root {
22
+ --radius: 0.5rem;
23
+
24
+ --background: oklch(1 0 0);
25
+ --foreground: oklch(0.21 0.006 285.9);
26
+ --card: oklch(1 0 0);
27
+ --card-foreground: var(--foreground);
28
+ --popover: oklch(1 0 0);
29
+ --popover-foreground: var(--foreground);
30
+
31
+ --primary: oklch(0.55 0.204 274.5);
32
+ --primary-foreground: oklch(1 0 0);
33
+ --secondary: oklch(0.968 0.002 286.4);
34
+ --secondary-foreground: oklch(0.27 0.006 286);
35
+ --muted: oklch(0.972 0.002 286.4);
36
+ --muted-foreground: oklch(0.53 0.013 286);
37
+ --accent: oklch(0.96 0.003 286.4);
38
+ --accent-foreground: oklch(0.27 0.006 286);
39
+ --destructive: oklch(0.58 0.216 27.3);
40
+
41
+ --border: oklch(0.918 0.004 286.3);
42
+ --input: oklch(0.918 0.004 286.3);
43
+ --ring: oklch(0.55 0.204 274.5);
44
+
45
+ /* Surfaces above the page: sidebar, popovers, hover rows. */
46
+ --surface-1: oklch(0.985 0.001 286.4);
47
+ --surface-2: oklch(0.968 0.002 286.4);
48
+
49
+ /* Pipeline + status. Muted on purpose — a board of saturated chips is
50
+ unreadable, and the eye should land on the one that's actually urgent. */
51
+ --stage-lead: oklch(0.62 0.03 264);
52
+ --stage-qualified: oklch(0.6 0.13 240);
53
+ --stage-proposal: oklch(0.68 0.15 78);
54
+ --stage-won: oklch(0.6 0.15 155);
55
+ --stage-lost: oklch(0.6 0.11 25);
56
+ }
57
+
58
+ .dark {
59
+ --background: oklch(0.165 0.004 285.9);
60
+ --foreground: oklch(0.93 0.002 286.3);
61
+ --card: oklch(0.196 0.005 285.9);
62
+ --card-foreground: var(--foreground);
63
+ --popover: oklch(0.216 0.006 285.9);
64
+ --popover-foreground: var(--foreground);
65
+
66
+ --primary: oklch(0.62 0.19 274.5);
67
+ --primary-foreground: oklch(1 0 0);
68
+ --secondary: oklch(0.25 0.006 286);
69
+ --secondary-foreground: oklch(0.93 0.002 286.3);
70
+ --muted: oklch(0.25 0.006 286);
71
+ --muted-foreground: oklch(0.65 0.012 286);
72
+ --accent: oklch(0.26 0.006 286);
73
+ --accent-foreground: oklch(0.93 0.002 286.3);
74
+ --destructive: oklch(0.65 0.19 25);
75
+
76
+ --border: oklch(1 0 0 / 9%);
77
+ --input: oklch(1 0 0 / 12%);
78
+ --ring: oklch(0.62 0.19 274.5);
79
+
80
+ --surface-1: oklch(0.186 0.004 285.9);
81
+ --surface-2: oklch(0.216 0.006 285.9);
82
+
83
+ --stage-lead: oklch(0.68 0.03 264);
84
+ --stage-qualified: oklch(0.68 0.13 240);
85
+ --stage-proposal: oklch(0.75 0.14 78);
86
+ --stage-won: oklch(0.7 0.15 155);
87
+ --stage-lost: oklch(0.68 0.14 25);
88
+ }
89
+
90
+ @theme inline {
91
+ --radius-sm: calc(var(--radius) - 3px);
92
+ --radius-md: calc(var(--radius) - 1px);
93
+ --radius-lg: var(--radius);
94
+ --radius-xl: calc(var(--radius) + 4px);
95
+
96
+ --color-background: var(--background);
97
+ --color-foreground: var(--foreground);
98
+ --color-card: var(--card);
99
+ --color-card-foreground: var(--card-foreground);
100
+ --color-popover: var(--popover);
101
+ --color-popover-foreground: var(--popover-foreground);
102
+ --color-primary: var(--primary);
103
+ --color-primary-foreground: var(--primary-foreground);
104
+ --color-secondary: var(--secondary);
105
+ --color-secondary-foreground: var(--secondary-foreground);
106
+ --color-muted: var(--muted);
107
+ --color-muted-foreground: var(--muted-foreground);
108
+ --color-accent: var(--accent);
109
+ --color-accent-foreground: var(--accent-foreground);
110
+ --color-destructive: var(--destructive);
111
+ --color-border: var(--border);
112
+ --color-input: var(--input);
113
+ --color-ring: var(--ring);
114
+
115
+ --color-surface-1: var(--surface-1);
116
+ --color-surface-2: var(--surface-2);
117
+
118
+ --color-stage-lead: var(--stage-lead);
119
+ --color-stage-qualified: var(--stage-qualified);
120
+ --color-stage-proposal: var(--stage-proposal);
121
+ --color-stage-won: var(--stage-won);
122
+ --color-stage-lost: var(--stage-lost);
123
+ }
124
+
125
+ @layer base {
126
+ *,
127
+ ::after,
128
+ ::before,
129
+ ::backdrop,
130
+ ::file-selector-button {
131
+ border-color: var(--color-border, currentColor);
132
+ outline-color: var(--color-ring);
133
+ }
134
+
135
+ html {
136
+ /* An internal tool is a fixed shell with scrolling panes, not a scrolling
137
+ document — this keeps the sidebar and header from drifting. */
138
+ height: 100%;
139
+ -webkit-tap-highlight-color: transparent;
140
+ }
141
+
142
+ body {
143
+ height: 100%;
144
+ background-color: var(--color-background);
145
+ color: var(--color-foreground);
146
+ /* 13px is the density these screens are designed at; the slight negative
147
+ tracking is what keeps Inter from looking loose at that size. */
148
+ font-size: 13px;
149
+ line-height: 1.5;
150
+ letter-spacing: -0.006em;
151
+ -webkit-font-smoothing: antialiased;
152
+ text-rendering: optimizeLegibility;
153
+ }
154
+
155
+ button {
156
+ cursor: pointer;
157
+ }
158
+
159
+ /* Numbers that sit in columns must not jitter as they change. */
160
+ .tabular,
161
+ table {
162
+ font-variant-numeric: tabular-nums;
163
+ }
164
+
165
+ /* Thin, self-effacing scrollbars — the board has several at once. */
166
+ * {
167
+ scrollbar-width: thin;
168
+ scrollbar-color: color-mix(in oklab, var(--color-foreground) 18%, transparent)
169
+ transparent;
170
+ }
171
+ ::-webkit-scrollbar {
172
+ width: 10px;
173
+ height: 10px;
174
+ }
175
+ ::-webkit-scrollbar-thumb {
176
+ background-color: color-mix(in oklab, var(--color-foreground) 16%, transparent);
177
+ border: 3px solid transparent;
178
+ background-clip: content-box;
179
+ border-radius: 999px;
180
+ }
181
+ ::-webkit-scrollbar-thumb:hover {
182
+ background-color: color-mix(in oklab, var(--color-foreground) 28%, transparent);
183
+ }
184
+ ::-webkit-scrollbar-corner {
185
+ background: transparent;
186
+ }
187
+
188
+ /* Only show focus rings for keyboard users; a mouse click shouldn't ring. */
189
+ :focus-visible {
190
+ outline: 2px solid var(--color-ring);
191
+ outline-offset: 1px;
192
+ }
193
+ }
194
+
195
+ @layer components {
196
+ /* A hairline that reads at 1px on any DPR without the doubling you get from
197
+ a plain border on retina. */
198
+ .hairline {
199
+ box-shadow: inset 0 -1px 0 0 var(--color-border);
200
+ }
201
+ }
@@ -0,0 +1,253 @@
1
+ "use client";
2
+
3
+ import React, { useState } from "react";
4
+ import { Link, callFn, db, useRouter } from "@pylonsync/react";
5
+ import { ArrowLeft, Trash2 } from "lucide-react";
6
+ import { Button } from "@/components/ui/button";
7
+ import { Select } from "@/components/ui/select";
8
+ import { PageHeader } from "@/components/page-header";
9
+ import { EmptyState } from "@/components/empty-state";
10
+ import { StatusBadge } from "@/components/status-badge";
11
+ import { LineItems } from "@/components/line-items";
12
+ import { TotalsPanel } from "@/components/totals-panel";
13
+ import { PaymentDialog } from "@/components/payment-dialog";
14
+ import { relativeTime } from "@/lib/format";
15
+ import { STATUSES, displayStatus, money, totals } from "@/lib/billing";
16
+ import { Workspace } from "../../workspace";
17
+
18
+ export function InvoiceView({
19
+ email,
20
+ invoiceId,
21
+ }: {
22
+ email: string;
23
+ invoiceId: string;
24
+ }) {
25
+ const router = useRouter();
26
+ const [payOpen, setPayOpen] = useState(false);
27
+
28
+ return (
29
+ <Workspace email={email} pathname="/">
30
+ {(data) => {
31
+ const invoice = data.invoices.find((i) => i.id === invoiceId);
32
+
33
+ if (!invoice) {
34
+ return (
35
+ <>
36
+ <PageHeader title="Invoice" />
37
+ <EmptyState
38
+ title={data.loading ? "Loading…" : "Invoice not found"}
39
+ description={
40
+ data.loading ? undefined : "It may have been deleted, or the link is wrong."
41
+ }
42
+ action={
43
+ data.loading ? undefined : (
44
+ <Button size="sm" variant="secondary" asChild>
45
+ <Link href="/">Back to invoices</Link>
46
+ </Button>
47
+ )
48
+ }
49
+ />
50
+ </>
51
+ );
52
+ }
53
+
54
+ const t = totals(invoice, data.items, data.payments);
55
+ const shown = displayStatus(invoice, t.balanceCents);
56
+ const client = data.clients.find((c) => c.id === invoice.clientId);
57
+ const lines = data.items.filter((item) => item.invoiceId === invoice.id);
58
+ const paid = data.payments
59
+ .filter((payment) => payment.invoiceId === invoice.id)
60
+ .sort((a, b) => (b.paidAt ?? "").localeCompare(a.paidAt ?? ""));
61
+ // A sent invoice is a document someone is paying against; editing its
62
+ // lines after the fact desyncs it from the copy in their inbox.
63
+ const editable = invoice.status === "draft";
64
+
65
+ return (
66
+ <>
67
+ <PageHeader title={invoice.number}>
68
+ <StatusBadge status={shown} />
69
+ <div className="w-28">
70
+ <Select
71
+ aria-label="Status"
72
+ value={invoice.status}
73
+ className="h-7 text-[12px]"
74
+ onChange={(event) =>
75
+ void callFn("setInvoiceStatus", {
76
+ invoiceId: invoice.id,
77
+ status: event.target.value,
78
+ })
79
+ }
80
+ >
81
+ {STATUSES.map((s) => (
82
+ <option key={s.id} value={s.id}>
83
+ {s.label}
84
+ </option>
85
+ ))}
86
+ </Select>
87
+ </div>
88
+ {t.balanceCents > 0 && invoice.status !== "void" ? (
89
+ <Button size="sm" onClick={() => setPayOpen(true)}>
90
+ Record payment
91
+ </Button>
92
+ ) : null}
93
+ {editable ? (
94
+ <Button
95
+ size="sm"
96
+ variant="ghost"
97
+ onClick={async () => {
98
+ await db.delete("Invoice", invoice.id);
99
+ router.push("/");
100
+ }}
101
+ className="text-muted-foreground hover:text-destructive"
102
+ >
103
+ <Trash2 />
104
+ </Button>
105
+ ) : null}
106
+ </PageHeader>
107
+
108
+ <div className="min-h-0 flex-1 overflow-y-auto">
109
+ <div className="mx-auto flex max-w-3xl flex-col gap-6 px-6 py-6">
110
+ <Link
111
+ href="/"
112
+ className="inline-flex w-fit items-center gap-1.5 text-[12px] text-muted-foreground transition-colors hover:text-foreground"
113
+ >
114
+ <ArrowLeft className="size-3.5" />
115
+ Invoices
116
+ </Link>
117
+
118
+ <dl className="grid grid-cols-2 gap-x-6 gap-y-4 rounded-lg border border-border bg-card p-4 sm:grid-cols-4">
119
+ <Field label="Client">
120
+ <Select
121
+ aria-label="Client"
122
+ value={invoice.clientId ?? ""}
123
+ className="h-7 text-[12px]"
124
+ onChange={(event) =>
125
+ void db.update("Invoice", invoice.id, {
126
+ clientId: event.target.value || null,
127
+ })
128
+ }
129
+ >
130
+ <option value="">—</option>
131
+ {data.clients.map((c) => (
132
+ <option key={c.id} value={c.id}>
133
+ {c.name}
134
+ </option>
135
+ ))}
136
+ </Select>
137
+ </Field>
138
+ <Field label="Issued">
139
+ {invoice.issueDate
140
+ ? new Date(invoice.issueDate).toLocaleDateString("en-US", {
141
+ month: "short",
142
+ day: "numeric",
143
+ year: "numeric",
144
+ })
145
+ : "—"}
146
+ </Field>
147
+ <Field label="Due">
148
+ {invoice.dueDate
149
+ ? new Date(invoice.dueDate).toLocaleDateString("en-US", {
150
+ month: "short",
151
+ day: "numeric",
152
+ year: "numeric",
153
+ })
154
+ : "—"}
155
+ </Field>
156
+ <Field label="Balance">
157
+ <span
158
+ className={
159
+ "tabular font-medium" +
160
+ (t.balanceCents > 0 ? " text-destructive" : "")
161
+ }
162
+ >
163
+ {money(t.balanceCents)}
164
+ </span>
165
+ </Field>
166
+ </dl>
167
+
168
+ {client?.address ? (
169
+ <div className="text-[12px] text-muted-foreground">
170
+ <p className="mb-1 font-medium text-foreground">Billed to</p>
171
+ <p className="whitespace-pre-wrap">{client.address}</p>
172
+ </div>
173
+ ) : null}
174
+
175
+ <LineItems
176
+ items={lines}
177
+ editable={editable}
178
+ onAdd={async (draft) => {
179
+ await db.insert("LineItem", {
180
+ ...draft,
181
+ invoiceId: invoice.id,
182
+ position: lines.length,
183
+ });
184
+ }}
185
+ onRemove={async (id) => {
186
+ await db.delete("LineItem", id);
187
+ }}
188
+ />
189
+
190
+ <TotalsPanel totals={t} taxRateBps={invoice.taxRateBps} />
191
+
192
+ {paid.length > 0 ? (
193
+ <section>
194
+ <h2 className="mb-2 text-[13px] font-semibold">Payments</h2>
195
+ <ul className="space-y-1.5">
196
+ {paid.map((payment) => (
197
+ <li
198
+ key={payment.id}
199
+ className="flex items-center gap-3 rounded-md border border-border bg-card px-3 py-2 text-[12px]"
200
+ >
201
+ <span className="tabular font-medium">
202
+ {money(payment.amountCents)}
203
+ </span>
204
+ <span className="text-muted-foreground capitalize">
205
+ {payment.method ?? "other"}
206
+ </span>
207
+ {payment.reference ? (
208
+ <span className="truncate text-muted-foreground">
209
+ {payment.reference}
210
+ </span>
211
+ ) : null}
212
+ <time
213
+ className="ml-auto text-muted-foreground"
214
+ dateTime={payment.paidAt ?? undefined}
215
+ >
216
+ {relativeTime(payment.paidAt)}
217
+ </time>
218
+ </li>
219
+ ))}
220
+ </ul>
221
+ </section>
222
+ ) : null}
223
+ </div>
224
+ </div>
225
+
226
+ <PaymentDialog
227
+ open={payOpen}
228
+ balanceCents={t.balanceCents}
229
+ onOpenChange={setPayOpen}
230
+ onRecord={(amountCents, method, reference) =>
231
+ callFn("recordPayment", {
232
+ invoiceId: invoice.id,
233
+ amountCents,
234
+ method,
235
+ ...(reference ? { reference } : {}),
236
+ })
237
+ }
238
+ />
239
+ </>
240
+ );
241
+ }}
242
+ </Workspace>
243
+ );
244
+ }
245
+
246
+ function Field({ label, children }: { label: string; children: React.ReactNode }) {
247
+ return (
248
+ <div className="min-w-0">
249
+ <dt className="text-[11px] text-muted-foreground">{label}</dt>
250
+ <dd className="mt-1 truncate text-[13px]">{children}</dd>
251
+ </div>
252
+ );
253
+ }
@@ -0,0 +1,23 @@
1
+ import React, { use } from "react";
2
+ import type { Metadata, PageProps } from "@pylonsync/react";
3
+ import { InvoiceView } from "./invoice-view";
4
+
5
+ export const metadata: Metadata = {
6
+ title: "Invoice",
7
+ robots: "noindex",
8
+ };
9
+
10
+ /** `app/invoices/[id]/page.tsx` -> `/invoices/:id`. */
11
+ export default function InvoicePage({
12
+ auth,
13
+ response,
14
+ params,
15
+ serverData,
16
+ }: PageProps<{ id: string }>) {
17
+ if (!auth.user_id || auth.user_id.startsWith("guest_")) {
18
+ response.redirect("/login");
19
+ return null;
20
+ }
21
+ const me = use(serverData.get<{ email?: string }>("User", auth.user_id));
22
+ return <InvoiceView email={me?.email ?? ""} invoiceId={params.id} />;
23
+ }