diff --git a/package.json b/package.json index ac9cfe1..d1aab9e 100644 --- a/package.json +++ b/package.json @@ -52,6 +52,7 @@ "@supabase/ssr": "^0.4.0", "@supabase/supabase-js": "^2.44.2", "chart.js": "^4.4.6", + "simple-datatables": "^9.2.1", "stripe": "^15.4.0", "ts-debounce": "^4.0.0", "winston": "^3.15.0" diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 88dfa8c..e1e057c 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -23,6 +23,9 @@ importers: chart.js: specifier: ^4.4.6 version: 4.4.6 + simple-datatables: + specifier: ^9.2.1 + version: 9.2.1 stripe: specifier: ^15.4.0 version: 15.12.0 @@ -1680,6 +1683,9 @@ packages: resolution: {integrity: sha512-t/Ygsytq+R995EJ5PZlD4Cu56sWa8InXySaViRzw9apusqsOO2bQP+SbYzAhR0pFKoB+43lYy8rWban9JSuXnA==} engines: {node: '>= 0.4'} + dayjs@1.11.13: + resolution: {integrity: sha512-oaMBel6gjolK862uaPQOVTA7q3TZhuSvuMQAAglQDOWYO9A91IrAOUJEyKVlqJlHE0vq5p5UXxzdPfMH/x6xNg==} + debug@4.3.7: resolution: {integrity: sha512-Er2nc/H7RrMXZBFCEim6TCmMk02Z8vLC2Rbi1KEBggpo0fS6l0S1nnapwmIi3yW/+GOJap1Krg4w0Hg80oCqgQ==} engines: {node: '>=6.0'} @@ -1741,6 +1747,9 @@ packages: didyoumean@1.2.2: resolution: {integrity: sha512-gxtyfqMg7GKyhQmb056K7M3xszy/myH8w+B4RT+QXBQsvAOdc3XymqDDPHx1BgPgsdAA5SIifona89YtRATDzw==} + diff-dom@5.1.4: + resolution: {integrity: sha512-TSEaVdVGictY1KHg7VpVw2nuM02YKC9C8/qBkGiCnkiAybVbu1zQTMj2/dnVLRO7Z62UsqzHGpXweiOj5/jaZg==} + dir-glob@3.0.1: resolution: {integrity: sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==} engines: {node: '>=8'} @@ -3003,6 +3012,9 @@ packages: simple-concat@1.0.1: resolution: {integrity: sha512-cSFtAPtRhljv69IK0hTVZQ+OfE9nePi/rtJmw5UjHeVyVroEqJXP1sFztKUy1qU+xvz3u/sfYJLa947b7nAN2Q==} + simple-datatables@9.2.1: + resolution: {integrity: sha512-R+KRyZ4GNQdqj5IoW08OYi9FHqCbndbw+MfdOJDnwOGs6me9+BhbNuj2QHZR/GXQ04TLra43Uj2/Lk1KcLiJRw==} + simple-get@4.0.1: resolution: {integrity: sha512-brv7p5WgH0jmQJr1ZDDfKDOSeWWg+OVypG99A/5vYGPqJ6pxiaHLy8nxtFjBA7oMa01ebA9gfh1uMCFqOuXxvA==} @@ -5353,6 +5365,8 @@ snapshots: es-errors: 1.3.0 is-data-view: 1.0.1 + dayjs@1.11.13: {} + debug@4.3.7: dependencies: ms: 2.1.3 @@ -5402,6 +5416,8 @@ snapshots: didyoumean@1.2.2: {} + diff-dom@5.1.4: {} + dir-glob@3.0.1: dependencies: path-type: 4.0.0 @@ -6715,6 +6731,11 @@ snapshots: simple-concat@1.0.1: {} + simple-datatables@9.2.1: + dependencies: + dayjs: 1.11.13 + diff-dom: 5.1.4 + simple-get@4.0.1: dependencies: decompress-response: 6.0.0 diff --git a/src/routes/(user)/credits/+page.server.ts b/src/routes/(user)/credits/+page.server.ts index 34df0b8..5cbc43e 100644 --- a/src/routes/(user)/credits/+page.server.ts +++ b/src/routes/(user)/credits/+page.server.ts @@ -17,9 +17,25 @@ export async function load({ locals: { safeGetSession } }) { const creditsRemaining = await getUserCredits(userId); const transactions = await getUserCreditTransactions(userId); + const monthlyAggregates = transactions.reduce((acc, transaction) => { + const date = new Date(transaction.created_at); + const month = `${date.getFullYear()}-${date.getMonth() + 1}`; + + if (!acc[month]) acc[month] = { credits_added: 0, credits_deducted: 0 }; + + if (transaction.credits_change > 0) { + acc[month].credits_added += transaction.credits_change; + } else { + acc[month].credits_deducted += transaction.credits_change; + } + + return acc; + }, {}); + return { creditsRemaining, - transactions + transactions, + monthlyAggregates }; } catch (error) { return { diff --git a/src/routes/(user)/credits/+page.svelte b/src/routes/(user)/credits/+page.svelte index 80444ed..1d3b8fd 100644 --- a/src/routes/(user)/credits/+page.svelte +++ b/src/routes/(user)/credits/+page.svelte @@ -1,59 +1,120 @@

Credit Dashboard

Credits Remaining: {creditsRemaining}

+
+ + +
+

Transaction History

- {#if noTransactions} + {#if transactions.length === 0}

No transactions found.

{:else} - +
@@ -88,4 +149,15 @@ table { margin-top: 1rem; } + button { + margin: 0 1rem; + padding: 0.5rem 1rem; + border: 1px solid #ccc; + border-radius: 0.5rem; + cursor: pointer; + } + button.font-bold { + font-weight: bold; + background-color: #f0f0f0; + }
Date