jat-feedback 2.0.1 → 3.0.1

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.
package/package.json CHANGED
@@ -1,13 +1,14 @@
1
1
  {
2
2
  "name": "jat-feedback",
3
- "version": "2.0.1",
3
+ "version": "3.0.1",
4
4
  "description": "Embeddable feedback widget for bug reports and feature requests. Captures screenshots, console logs, and user context as a web component.",
5
5
  "type": "module",
6
6
  "main": "dist/jat-feedback.js",
7
7
  "module": "dist/jat-feedback.mjs",
8
8
  "files": [
9
9
  "dist",
10
- "supabase"
10
+ "supabase",
11
+ "routes"
11
12
  ],
12
13
  "scripts": {
13
14
  "dev": "vite build --watch",
@@ -0,0 +1,45 @@
1
+ # Route Templates
2
+
3
+ Drop-in SvelteKit route templates for customer-facing task management UI.
4
+
5
+ ## /tasks — Task List & Detail
6
+
7
+ A customer-facing page that reads from the `project_tasks` Supabase table. Shows tasks with filtering, detail drawer, and comment thread.
8
+
9
+ ### Prerequisites
10
+
11
+ - jat-feedback v3.0.0+ with `3.0.0_rename_to_project_tasks.sql` migration applied
12
+ - SvelteKit app with Supabase SSR auth (parent layout provides `data.supabase`)
13
+ - DaisyUI + Tailwind CSS v4
14
+
15
+ ### Installation
16
+
17
+ Copy the route into your SvelteKit app:
18
+
19
+ ```bash
20
+ cp -r node_modules/jat-feedback/routes/tasks/ src/routes/(admin)/account/tasks/
21
+ ```
22
+
23
+ Adjust the destination path to match your route structure. The route must be nested under a layout that:
24
+ 1. Creates a Supabase browser client and passes it as `data.supabase`
25
+ 2. Handles auth redirects (the page has a fallback redirect to `/login`)
26
+ 3. Passes `data.user` with at least an `email` field
27
+
28
+ ### Features
29
+
30
+ - **Server-side loading** from `project_tasks` via Supabase RLS
31
+ - **URL-based filters** for status, type, and priority
32
+ - **Task detail drawer** with full description, metadata, and labels
33
+ - **Comment thread** with real-time submission (Ctrl+Enter shortcut)
34
+ - **Mobile responsive** — table on desktop, cards on mobile
35
+ - **Status badges** with color coding
36
+ - **Screenshot display** from feedback-captured images
37
+
38
+ ### Customization
39
+
40
+ The route uses standard DaisyUI classes and inherits your theme. Common customizations:
41
+
42
+ - **Change redirect path**: Edit the `redirect(303, "/login")` in `+page.server.ts`
43
+ - **Add more statuses**: Edit `statusOptions` array in `+page.svelte`
44
+ - **Customize columns**: Modify the table `<thead>` and `<tbody>` cells
45
+ - **Restrict by source**: Add `.eq("source", "feedback")` to the server query
@@ -0,0 +1,55 @@
1
+ import { redirect } from "@sveltejs/kit"
2
+ import type { PageServerLoad } from "./$types"
3
+
4
+ export const load: PageServerLoad = async ({
5
+ locals: { supabase, safeGetSession },
6
+ url,
7
+ }) => {
8
+ const { user } = await safeGetSession()
9
+ if (!user) {
10
+ redirect(303, "/login")
11
+ }
12
+
13
+ // Read filters from URL search params
14
+ const status = url.searchParams.get("status") || ""
15
+ const issueType = url.searchParams.get("type") || ""
16
+ const priority = url.searchParams.get("priority") || ""
17
+
18
+ // Build query — RLS ensures users only see their own tasks
19
+ let query = supabase
20
+ .from("project_tasks")
21
+ .select("*, project_tasks_comments(count)")
22
+ .order("created_at", { ascending: false })
23
+
24
+ if (status) {
25
+ query = query.eq("status", status)
26
+ }
27
+ if (issueType) {
28
+ query = query.eq("issue_type", issueType)
29
+ }
30
+ if (priority) {
31
+ query = query.eq("priority", priority)
32
+ }
33
+
34
+ // Fetch tasks and team members in parallel
35
+ // NOTE: Customize the role filter for your project's profile roles
36
+ const [tasksResult, teamResult] = await Promise.all([
37
+ query.limit(100),
38
+ supabase
39
+ .from("profiles")
40
+ .select("id, full_name, role")
41
+ .not("full_name", "is", null)
42
+ .order("full_name"),
43
+ ])
44
+
45
+ if (tasksResult.error) {
46
+ console.error("Failed to load tasks:", tasksResult.error.message)
47
+ }
48
+
49
+ return {
50
+ tasks: tasksResult.data ?? [],
51
+ teamMembers: teamResult.data ?? [],
52
+ filters: { status, issueType, priority },
53
+ user,
54
+ }
55
+ }