diff --git a/.github/ISSUE_TEMPLATE/bug.md b/.github/ISSUE_TEMPLATE/bug.md deleted file mode 100644 index e1006ea9..00000000 --- a/.github/ISSUE_TEMPLATE/bug.md +++ /dev/null @@ -1,25 +0,0 @@ ---- -name: Bug Report -about: Report a problem with the app -title: [BUG] ---- - -**Description** -Briefly describe the bug. - -**Steps to Reproduce** -1. Go to '...' -2. Click on '...' -3. Observe the issue. - -**Expected vs. Actual Behavior** -- **Expected:** What should happen? -- **Actual:** What happens instead? - -**Environment** -- **Platform:** (e.g., Windows, macOS, Linux, iOS, Android) -- **Browser:** (e.g., Chrome, Firefox, Safari) -- **Version:** (if applicable) - -**Additional Context** -Any screenshots, logs, or error messages? Add them here. diff --git a/.github/ISSUE_TEMPLATE/feature.md b/.github/ISSUE_TEMPLATE/feature.md deleted file mode 100644 index ae186514..00000000 --- a/.github/ISSUE_TEMPLATE/feature.md +++ /dev/null @@ -1,14 +0,0 @@ ---- -name: Feature Request -about: Suggest a new feature for the app -title: [FEATURE] ---- - -**Description** -What feature would you like to see? Describe it briefly. - -**Use Case** -Why is this feature important? How will it improve the app? - -**Additional Context** -Any mockups, screenshots, or references? Add them here. diff --git a/.github/ISSUE_TEMPLATE/general.md b/.github/ISSUE_TEMPLATE/general.md deleted file mode 100644 index 2f63439c..00000000 --- a/.github/ISSUE_TEMPLATE/general.md +++ /dev/null @@ -1,14 +0,0 @@ ---- -name: General Issue -about: Use this for issues that don't fit other templates -title: [GENERAL] ---- - -**Description** -What is the issue about? Brief and clear. - -**Details** -Add any relevant details or context here. - -**Additional Context** -Attach files, links, or screenshots if necessary. \ No newline at end of file diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md index 81ec79e1..a38b878d 100644 --- a/.github/PULL_REQUEST_TEMPLATE.md +++ b/.github/PULL_REQUEST_TEMPLATE.md @@ -5,6 +5,7 @@ What does this PR do? Summarize your changes. Link to any related issues (e.g., `Fixes #123`). **Changes Made** + - [ ] Key change #1 - [ ] Key change #2 - [ ] Key change #3 @@ -13,10 +14,11 @@ Link to any related issues (e.g., `Fixes #123`). How can reviewers test your changes? Include steps, commands, or screenshots. **Checklist** + - [ ] Code is well-documented. - [ ] Tests have been added or updated. - [ ] All checks pass (CI/CD, linting, etc.). - [ ] Changes have been reviewed and approved by peers. **Additional Context** -Any other information or screenshots? Add them here. \ No newline at end of file +Any other information or screenshots? Add them here. diff --git a/.github/workflows/develop.yml b/.github/workflows/develop.yml index ec39bb67..890d40e8 100644 --- a/.github/workflows/develop.yml +++ b/.github/workflows/develop.yml @@ -1,4 +1,4 @@ -name: Develop +ikoname: Develop on: push: branches: @@ -21,11 +21,11 @@ jobs: - name: Set up JDK 21 uses: actions/setup-java@v4 with: - java-version: '21' - distribution: 'corretto' + java-version: "21" + distribution: "corretto" server-id: github settings-path: ${{ github.workspace }} - cache: 'maven' + cache: "maven" - name: Cache Maven dependencies uses: actions/cache@v3 @@ -147,4 +147,4 @@ jobs: run: scp -o "StrictHostKeyChecking no" -A -r -J ${{secrets.BASTION_SSH_USER}}@${{secrets.BASTION_HOST}}:2222 $PWD/* ${{secrets.DEPLOYMENT_SSH_USER}}@${{secrets.DEPLOYMENT_HOST}}:/home/infra/billtracker/frontend_content - name: Update Backend - run: ssh -o "StrictHostKeyChecking no" -A -J ${{secrets.BASTION_SSH_USER}}@${{secrets.BASTION_HOST}}:2222 ${{secrets.DEPLOYMENT_SSH_USER}}@${{secrets.DEPLOYMENT_HOST}} "bash -c \"cd billtracker && echo "export BILLTRACKER_VERSION=${{ github.sha }}" >> version.env && source version.env && docker compose pull backend && docker compose up -d backend\"" \ No newline at end of file + run: ssh -o "StrictHostKeyChecking no" -A -J ${{secrets.BASTION_SSH_USER}}@${{secrets.BASTION_HOST}}:2222 ${{secrets.DEPLOYMENT_SSH_USER}}@${{secrets.DEPLOYMENT_HOST}} "bash -c \"cd billtracker && echo "export BILLTRACKER_VERSION=${{ github.sha }}" >> version.env && source version.env && docker compose pull backend && docker compose up -d backend\"" diff --git a/.github/workflows/production.yml b/.github/workflows/production.yml index afd99cf4..99748c46 100644 --- a/.github/workflows/production.yml +++ b/.github/workflows/production.yml @@ -21,11 +21,11 @@ jobs: - name: Set up JDK 21 uses: actions/setup-java@v4 with: - java-version: '21' - distribution: 'corretto' + java-version: "21" + distribution: "corretto" server-id: github settings-path: ${{ github.workspace }} - cache: 'maven' + cache: "maven" - name: Cache Maven dependencies uses: actions/cache@v3 @@ -147,4 +147,4 @@ jobs: run: scp -o "StrictHostKeyChecking no" -A -r -J ${{secrets.BASTION_SSH_USER}}@${{secrets.BASTION_HOST}}:2222 $PWD/* ${{secrets.DEPLOYMENT_SSH_USER}}@${{secrets.DEPLOYMENT_HOST}}:/home/infra/billtracker/frontend_content - name: Update Backend - run: ssh -o "StrictHostKeyChecking no" -A -J ${{secrets.BASTION_SSH_USER}}@${{secrets.BASTION_HOST}}:2222 ${{secrets.DEPLOYMENT_SSH_USER}}@${{secrets.DEPLOYMENT_HOST}} "bash -c \"cd billtracker && echo "export BILLTRACKER_VERSION=${{ github.ref_name }}" >> version.env && source version.env && docker compose pull backend && docker compose up -d backend\"" \ No newline at end of file + run: ssh -o "StrictHostKeyChecking no" -A -J ${{secrets.BASTION_SSH_USER}}@${{secrets.BASTION_HOST}}:2222 ${{secrets.DEPLOYMENT_SSH_USER}}@${{secrets.DEPLOYMENT_HOST}} "bash -c \"cd billtracker && echo "export BILLTRACKER_VERSION=${{ github.ref_name }}" >> version.env && source version.env && docker compose pull backend && docker compose up -d backend\"" diff --git a/.vscode/launch.json b/.vscode/launch.json index 941e31a1..b0fb55d3 100644 --- a/.vscode/launch.json +++ b/.vscode/launch.json @@ -1,19 +1,17 @@ { - // Use IntelliSense to learn about possible attributes. - // Hover to view descriptions of existing attributes. - // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 - "version": "0.2.0", - "configurations": [ - { - "preLaunchTask": "Tailwind Watch", - "type": "java", - "name": "BilltrackerApplication", - "request": "launch", - "mainClass": "com.kerosenelabs.billtracker.BilltrackerApplication", - "projectName": "billtracker", - "args": [ - "--spring.profiles.active=local" - ] - } - ] -} \ No newline at end of file + // Use IntelliSense to learn about possible attributes. + // Hover to view descriptions of existing attributes. + // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 + "version": "0.2.0", + "configurations": [ + { + "preLaunchTask": "Tailwind Watch", + "type": "java", + "name": "BilltrackerApplication", + "request": "launch", + "mainClass": "com.kerosenelabs.billtracker.BilltrackerApplication", + "projectName": "billtracker", + "args": ["--spring.profiles.active=local"] + } + ] +} diff --git a/.vscode/settings.json b/.vscode/settings.json index d53ecaf3..d232ff52 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -1,4 +1,4 @@ { - "java.compile.nullAnalysis.mode": "automatic", - "java.configuration.updateBuildConfiguration": "automatic" -} \ No newline at end of file + "java.compile.nullAnalysis.mode": "automatic", + "java.configuration.updateBuildConfiguration": "automatic" +} diff --git a/.vscode/tasks.json b/.vscode/tasks.json index 6eea3bbf..f51744e8 100644 --- a/.vscode/tasks.json +++ b/.vscode/tasks.json @@ -1,14 +1,14 @@ { - // See https://go.microsoft.com/fwlink/?LinkId=733558 - // for the documentation about the tasks.json format - "version": "2.0.0", - "tasks": [ - { - "isBackground": true, - "label": "Tailwind Watch", - "type": "shell", - "command": "cd src/main/frontend && npm run watch", - "problemMatcher": [], - } - ] -} \ No newline at end of file + // See https://go.microsoft.com/fwlink/?LinkId=733558 + // for the documentation about the tasks.json format + "version": "2.0.0", + "tasks": [ + { + "isBackground": true, + "label": "Tailwind Watch", + "type": "shell", + "command": "cd src/main/frontend && npm run watch", + "problemMatcher": [] + } + ] +} diff --git a/LICENSE.md b/LICENSE.md index 551b88f1..d1d47943 100644 --- a/LICENSE.md +++ b/LICENSE.md @@ -1,4 +1,3 @@ - Copyright 2024 Kerosene Labs LLC Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the “Software”), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: diff --git a/README.md b/README.md index cb78990a..437fb491 100644 --- a/README.md +++ b/README.md @@ -6,9 +6,9 @@ An open source, transparent, independently auditable personal expense and income 1. [Features](#features) 2. [Installation](#installation) -4. [Contributing](#contributing) -5. [License](#license) -6. [Contact](#contact) +3. [Contributing](#contributing) +4. [License](#license) +5. [Contact](#contact) ## Features @@ -37,4 +37,4 @@ Please see [LICENSE.md](LICENSE.md). ## Contact -Follow the proper channels on [our website](https://kerosenelabs.com). \ No newline at end of file +Follow the proper channels on [our website](https://kerosenelabs.com). diff --git a/compose.yml b/compose.yml index 31684823..0efe0935 100644 --- a/compose.yml +++ b/compose.yml @@ -7,4 +7,4 @@ services: volumes: - db_data:/var/lib/postgresql/data volumes: - db_data: \ No newline at end of file + db_data: diff --git a/pom.xml b/pom.xml index 097086f7..d42252f7 100644 --- a/pom.xml +++ b/pom.xml @@ -147,6 +147,7 @@ + ${project.basedir}/src/main/kotlin @@ -200,7 +201,7 @@ org.springframework.boot spring-boot-maven-plugin - com.kerosenelabs.billtracker.BilltrackerApplicationKt + com.kerosenelabs.billtracker.BillTrackerApplicationKt diff --git a/src/main/kotlin/com/kerosenelabs/billtracker/BilltrackerApplication.kt b/src/main/kotlin/com/kerosenelabs/billtracker/BillTrackerApplication.kt similarity index 89% rename from src/main/kotlin/com/kerosenelabs/billtracker/BilltrackerApplication.kt rename to src/main/kotlin/com/kerosenelabs/billtracker/BillTrackerApplication.kt index d2e7f272..a73f540e 100644 --- a/src/main/kotlin/com/kerosenelabs/billtracker/BilltrackerApplication.kt +++ b/src/main/kotlin/com/kerosenelabs/billtracker/BillTrackerApplication.kt @@ -15,8 +15,8 @@ import org.springframework.web.bind.annotation.CrossOrigin ) @CrossOrigin @SpringBootApplication -open class BilltrackerApplication +open class BillTrackerApplication fun main(args: Array) { - runApplication(*args) + runApplication(*args) } diff --git a/src/main/kotlin/com/kerosenelabs/billtracker/controller/ExpensesController.kt b/src/main/kotlin/com/kerosenelabs/billtracker/controller/ExpensesController.kt index 6246372f..0af56dfb 100644 --- a/src/main/kotlin/com/kerosenelabs/billtracker/controller/ExpensesController.kt +++ b/src/main/kotlin/com/kerosenelabs/billtracker/controller/ExpensesController.kt @@ -4,6 +4,7 @@ import com.kerosenelabs.billtracker.entity.UserEntity import com.kerosenelabs.billtracker.model.request.CreateOneOffExpenseRequest import com.kerosenelabs.billtracker.model.request.CreateRecurringExpenseCreatorRequest import com.kerosenelabs.billtracker.model.response.GetExpenseEventsResponse +import com.kerosenelabs.billtracker.model.response.GetRecurringExpenseEventCreatorsResponse import com.kerosenelabs.billtracker.service.ExpenseService import io.swagger.v3.oas.annotations.Parameter import io.swagger.v3.oas.annotations.tags.Tag @@ -18,7 +19,7 @@ import org.springframework.web.bind.annotation.RestController @RestController @Tag(name = "Expenses", description = "Personal expenses") class ExpensesController(private val expenseService: ExpenseService) { - @PostMapping("/expenses/oneOff") + @PostMapping("/expenses/oneOffs") @ResponseStatus(HttpStatus.NO_CONTENT) fun createOneOff( @Parameter(hidden = true) user: UserEntity, @@ -27,7 +28,7 @@ class ExpensesController(private val expenseService: ExpenseService) { expenseService.createOneOffExpense(request.amount, user, request.date, request.description) } - @PostMapping("/expenses/recurringCreator") + @PostMapping("/expenses/recurringCreators") @ResponseStatus(HttpStatus.NO_CONTENT) fun createRecurringExpenseCreator( @Parameter(hidden = true) user: UserEntity, @@ -36,7 +37,7 @@ class ExpensesController(private val expenseService: ExpenseService) { expenseService.createRecurringExpenseEventCreator( request.amount, user, - request.recursEveryDays, + request.recursEveryCalendarDay, request.description ) } @@ -51,4 +52,15 @@ class ExpensesController(private val expenseService: ExpenseService) { .toList() ) } + +// @GetMapping("/expenses/recurringCreators") +// @ResponseStatus(HttpStatus.OK) +// fun getExpenses(@Parameter(hidden = true) user: UserEntity): GetRecurringExpenseEventCreatorsResponse { +// return GetExpenseEventsResponse( +// expenseService.(user) +// .stream() +// .map { entity -> expenseService.mapExpenseEventEntityToExpenseEvent(entity) } +// .toList() +// ) +// } } diff --git a/src/main/kotlin/com/kerosenelabs/billtracker/entity/RecurringExpenseEventCreatorEntity.kt b/src/main/kotlin/com/kerosenelabs/billtracker/entity/RecurringExpenseEventCreatorEntity.kt index 0c30dbf7..fa35c02a 100644 --- a/src/main/kotlin/com/kerosenelabs/billtracker/entity/RecurringExpenseEventCreatorEntity.kt +++ b/src/main/kotlin/com/kerosenelabs/billtracker/entity/RecurringExpenseEventCreatorEntity.kt @@ -8,7 +8,7 @@ import java.util.UUID @Table(name = "recurring_expense_event_creator", schema = "public") class RecurringExpenseEventCreatorEntity( @Id @GeneratedValue(strategy = GenerationType.AUTO) var id: UUID? = null, - @Column(nullable = false) var recursEveryDays: Int = 0, + @Column(nullable = false) var recursEveryCalendarDay: Int = 0, @Column(nullable = false) var amount: BigDecimal = BigDecimal.ZERO, @ManyToOne diff --git a/src/main/kotlin/com/kerosenelabs/billtracker/model/expense/RecurringExpenseEventCreator.kt b/src/main/kotlin/com/kerosenelabs/billtracker/model/expense/RecurringExpenseEventCreator.kt new file mode 100644 index 00000000..8d2f99a6 --- /dev/null +++ b/src/main/kotlin/com/kerosenelabs/billtracker/model/expense/RecurringExpenseEventCreator.kt @@ -0,0 +1,11 @@ +package com.kerosenelabs.billtracker.model.expense + +import java.math.BigDecimal +import java.util.UUID + +data class RecurringExpenseEventCreator( + var id: UUID, + var recursEveryCalendarDay: Int, + var amount: BigDecimal, + var description: String, +) diff --git a/src/main/kotlin/com/kerosenelabs/billtracker/model/request/CreateRecurringExpenseCreatorRequest.kt b/src/main/kotlin/com/kerosenelabs/billtracker/model/request/CreateRecurringExpenseCreatorRequest.kt index d48b808d..049f0d70 100644 --- a/src/main/kotlin/com/kerosenelabs/billtracker/model/request/CreateRecurringExpenseCreatorRequest.kt +++ b/src/main/kotlin/com/kerosenelabs/billtracker/model/request/CreateRecurringExpenseCreatorRequest.kt @@ -7,7 +7,7 @@ import jakarta.validation.constraints.Positive import java.math.BigDecimal data class CreateRecurringExpenseCreatorRequest( - @field:Min(1) @field:Max(28) val recursEveryDays: Int, + @field:Min(1) @field:Max(28) val recursEveryCalendarDay: Int, @field:Positive val amount: BigDecimal, @field:NotBlank val description: String, ) diff --git a/src/main/kotlin/com/kerosenelabs/billtracker/model/response/GetRecurringExpenseEventCreatorsResponse.kt b/src/main/kotlin/com/kerosenelabs/billtracker/model/response/GetRecurringExpenseEventCreatorsResponse.kt new file mode 100644 index 00000000..72884096 --- /dev/null +++ b/src/main/kotlin/com/kerosenelabs/billtracker/model/response/GetRecurringExpenseEventCreatorsResponse.kt @@ -0,0 +1,7 @@ +package com.kerosenelabs.billtracker.model.response + +import com.kerosenelabs.billtracker.model.expense.RecurringExpenseEventCreator + +data class GetRecurringExpenseEventCreatorsResponse( + val recurringExpenseEventCreators: List +) \ No newline at end of file diff --git a/src/main/kotlin/com/kerosenelabs/billtracker/repository/ExpenseEventRepository.kt b/src/main/kotlin/com/kerosenelabs/billtracker/repository/ExpenseEventRepository.kt index 73ee4975..d00e9734 100644 --- a/src/main/kotlin/com/kerosenelabs/billtracker/repository/ExpenseEventRepository.kt +++ b/src/main/kotlin/com/kerosenelabs/billtracker/repository/ExpenseEventRepository.kt @@ -8,5 +8,5 @@ import java.util.* @Repository interface ExpenseEventRepository : JpaRepository { - fun findExpenseEventEntitiesByUser(user: UserEntity): List + fun findAllByUser(user: UserEntity): List } diff --git a/src/main/kotlin/com/kerosenelabs/billtracker/repository/RecurringExpenseEventCreatorRepository.kt b/src/main/kotlin/com/kerosenelabs/billtracker/repository/RecurringExpenseEventCreatorRepository.kt index 4c69bc68..7eca4fbf 100644 --- a/src/main/kotlin/com/kerosenelabs/billtracker/repository/RecurringExpenseEventCreatorRepository.kt +++ b/src/main/kotlin/com/kerosenelabs/billtracker/repository/RecurringExpenseEventCreatorRepository.kt @@ -1,8 +1,10 @@ package com.kerosenelabs.billtracker.repository import com.kerosenelabs.billtracker.entity.RecurringExpenseEventCreatorEntity +import com.kerosenelabs.billtracker.entity.UserEntity import org.springframework.data.jpa.repository.JpaRepository import java.util.* interface RecurringExpenseEventCreatorRepository : JpaRepository{ + fun findAllByUser(user: UserEntity): List } \ No newline at end of file diff --git a/src/main/kotlin/com/kerosenelabs/billtracker/service/ExpenseService.kt b/src/main/kotlin/com/kerosenelabs/billtracker/service/ExpenseService.kt index 5490e90a..6558a062 100644 --- a/src/main/kotlin/com/kerosenelabs/billtracker/service/ExpenseService.kt +++ b/src/main/kotlin/com/kerosenelabs/billtracker/service/ExpenseService.kt @@ -5,6 +5,7 @@ import com.kerosenelabs.billtracker.entity.RecurringExpenseEventCreatorEntity import com.kerosenelabs.billtracker.entity.UserEntity import com.kerosenelabs.billtracker.model.expense.ExpenseEvent import com.kerosenelabs.billtracker.model.expense.ExpenseEventType +import com.kerosenelabs.billtracker.model.expense.RecurringExpenseEventCreator import com.kerosenelabs.billtracker.repository.ExpenseEventRepository import com.kerosenelabs.billtracker.repository.RecurringExpenseEventCreatorRepository import org.hibernate.sql.ast.tree.expression.Every @@ -43,13 +44,13 @@ class ExpenseService( fun createRecurringExpenseEventCreator( amount: BigDecimal, user: UserEntity, - recursEveryDays: Int, + recursEveryCalendarDay: Int, description: String ): RecurringExpenseEventCreatorEntity { return RecurringExpenseEventCreatorEntity( amount = amount, user = user, - recursEveryDays = recursEveryDays, + recursEveryCalendarDay = recursEveryCalendarDay, description = description ) } @@ -59,7 +60,15 @@ class ExpenseService( * @see ExpenseEventEntity */ fun getExpenseEventEntitiesByUser(user: UserEntity): List { - return expenseEventRepository.findExpenseEventEntitiesByUser(user) + return expenseEventRepository.findAllByUser(user) + } + + /** + * Helper function to get all recurring expense event creators by a user. + * @see RecurringExpenseEventCreatorEntity + */ + fun getRecurringExpenseEventCreatorsByUser(user: UserEntity): List { + return recurringExpenseEventCreatorRepository.findAllByUser(user) } /** @@ -75,4 +84,15 @@ class ExpenseService( description = expenseEventEntity.description, ) } + + /** + * Map a RecurringExpenseEventCreatorEntity (aka an recurring expense event from the database) to a model + * suitable for consumption by the user. + */ +// fun mapRecurringExpenseEventCreatorEntityToRecurringExpenseEventCreator(recurringExpenseEventCreator: RecurringExpenseEventCreator): RecurringExpenseEventCreator { +// return RecurringExpenseEventCreator( +// id = recurringExpenseEventCreator.id!!, +//// recursEveryCalendarDays = recurringExpenseEventCreator, +// ) +// } } \ No newline at end of file diff --git a/src/main/resources/application.yaml b/src/main/resources/application.yaml index 21b421ff..b819397c 100644 --- a/src/main/resources/application.yaml +++ b/src/main/resources/application.yaml @@ -12,4 +12,4 @@ billtracker: userInfoEndpoint: https://www.googleapis.com/oauth2/v3/userinfo clientSecret: clientId: - redirectUri: \ No newline at end of file + redirectUri: diff --git a/src/main/svelte/src/app.css b/src/main/svelte/src/app.css index ce9e50af..2af22706 100644 --- a/src/main/svelte/src/app.css +++ b/src/main/svelte/src/app.css @@ -12,4 +12,4 @@ h2 { p.subtitle { @apply font-semibold text-neutral-400; -} +} \ No newline at end of file diff --git a/src/main/svelte/src/app.html b/src/main/svelte/src/app.html index 2f0089e0..552a4dea 100644 --- a/src/main/svelte/src/app.html +++ b/src/main/svelte/src/app.html @@ -3,13 +3,16 @@ - + %sveltekit.head% diff --git a/src/main/svelte/src/lib/components/Table.svelte b/src/main/svelte/src/lib/components/Table.svelte index 74114ba6..f9eb942f 100644 --- a/src/main/svelte/src/lib/components/Table.svelte +++ b/src/main/svelte/src/lib/components/Table.svelte @@ -5,27 +5,32 @@ export let rows: String[][] = [["Val 1", "Val 2", "Val 3"]]; -
- +
+
- - {#each headers as header} - - {/each} - - - - {#each rows as row} - - {#each row as cell} - + + {#each headers as header} + {/each} - {/each} + + + {#each rows as row} + + {#each row as cell} + + {/each} + + {/each}
{header}
{cell}
{header}
{cell}
\ No newline at end of file + diff --git a/src/main/svelte/src/lib/components/expenses/ExpenseEventTable.svelte b/src/main/svelte/src/lib/components/expenses/ExpenseEventTable.svelte index b9ec6223..b5427a40 100644 --- a/src/main/svelte/src/lib/components/expenses/ExpenseEventTable.svelte +++ b/src/main/svelte/src/lib/components/expenses/ExpenseEventTable.svelte @@ -6,6 +6,7 @@ import Spinner from "$lib/tk/Spinner.svelte"; import Button from "$lib/tk/Button.svelte"; import Table from "$lib/components/Table.svelte"; + import { goto } from "$app/navigation"; let expenses: ExpenseEvent[] | undefined = undefined; let expenseRows: String[][] = []; @@ -16,13 +17,18 @@ .then((response) => { expenses = response.expenseEvents; expenses.forEach((expense) => { - expenseRows.push(["$" + expense.amount.toFixed(2), expense.date.toDateString(), expense.description, expense.expenseEventType]) - }) + expenseRows.push([ + "$" + expense.amount.toFixed(2), + expense.date.toDateString(), + expense.description, + expense.expenseEventType, + ]); + }); }) .catch(async (error: ResponseError) => { addToToastQueue({ message: "Failed to get Expenses.", - type: ToastType.ERROR + type: ToastType.ERROR, }); }); }); @@ -30,6 +36,12 @@
+
@@ -43,9 +55,12 @@

🦗...crickets

-

There's no expenses here.

+

There's nothing here.

{:else} -
+
{/if} diff --git a/src/main/svelte/src/lib/components/expenses/RecurringExpenseCreator.svelte b/src/main/svelte/src/lib/components/expenses/RecurringExpenseCreator.svelte new file mode 100644 index 00000000..b74a8394 --- /dev/null +++ b/src/main/svelte/src/lib/components/expenses/RecurringExpenseCreator.svelte @@ -0,0 +1,58 @@ + + + +
+
+ + + +
+ +
+
diff --git a/src/main/svelte/src/lib/components/expenses/RecurringExpenseEventCreatorTable.svelte b/src/main/svelte/src/lib/components/expenses/RecurringExpenseEventCreatorTable.svelte index e9d357d2..23c74214 100644 --- a/src/main/svelte/src/lib/components/expenses/RecurringExpenseEventCreatorTable.svelte +++ b/src/main/svelte/src/lib/components/expenses/RecurringExpenseEventCreatorTable.svelte @@ -6,6 +6,7 @@ import Spinner from "$lib/tk/Spinner.svelte"; import Button from "$lib/tk/Button.svelte"; import Table from "$lib/components/Table.svelte"; + import { goto } from "$app/navigation"; let expenses: ExpenseEvent[] | undefined = undefined; let expenseRows: String[][] = []; @@ -16,13 +17,18 @@ .then((response) => { expenses = response.expenseEvents; expenses.forEach((expense) => { - expenseRows.push(["$" + expense.amount.toFixed(2), expense.date.toDateString(), expense.description, expense.expenseEventType]) - }) + expenseRows.push([ + "$" + expense.amount.toFixed(2), + expense.date.toDateString(), + expense.description, + expense.expenseEventType, + ]); + }); }) .catch(async (error: ResponseError) => { addToToastQueue({ message: "Failed to get Expenses.", - type: ToastType.ERROR + type: ToastType.ERROR, }); }); }); @@ -30,8 +36,12 @@
- - +
{#if expenses === undefined} @@ -43,9 +53,12 @@

🦗...crickets

-

There's no expenses here.

+

There's nothing here.

{:else} -
+
{/if} diff --git a/src/main/svelte/src/lib/eureka/input/EDateInput.svelte b/src/main/svelte/src/lib/eureka/input/EDateInput.svelte new file mode 100644 index 00000000..e69de29b diff --git a/src/main/svelte/src/lib/eureka/input/ENumberInput.svelte b/src/main/svelte/src/lib/eureka/input/ENumberInput.svelte new file mode 100644 index 00000000..e69de29b diff --git a/src/main/svelte/src/lib/eureka/input/ETextInput.svelte b/src/main/svelte/src/lib/eureka/input/ETextInput.svelte new file mode 100644 index 00000000..e69de29b diff --git a/src/main/svelte/src/lib/sdk/.openapi-generator/FILES b/src/main/svelte/src/lib/sdk/.openapi-generator/FILES index 17498345..0427f02a 100644 --- a/src/main/svelte/src/lib/sdk/.openapi-generator/FILES +++ b/src/main/svelte/src/lib/sdk/.openapi-generator/FILES @@ -4,6 +4,7 @@ apis/SettingsApi.ts apis/index.ts index.ts models/CreateOneOffExpenseRequest.ts +models/CreateRecurringExpenseCreatorRequest.ts models/ExpenseEvent.ts models/GetExpenseEventsResponse.ts models/GetIntroductorySettingsResponse.ts diff --git a/src/main/svelte/src/lib/sdk/apis/ExpensesApi.ts b/src/main/svelte/src/lib/sdk/apis/ExpensesApi.ts index ca9884d0..09ca85fd 100644 --- a/src/main/svelte/src/lib/sdk/apis/ExpensesApi.ts +++ b/src/main/svelte/src/lib/sdk/apis/ExpensesApi.ts @@ -16,11 +16,14 @@ import * as runtime from '../runtime'; import type { CreateOneOffExpenseRequest, + CreateRecurringExpenseCreatorRequest, GetExpenseEventsResponse, } from '../models/index'; import { CreateOneOffExpenseRequestFromJSON, CreateOneOffExpenseRequestToJSON, + CreateRecurringExpenseCreatorRequestFromJSON, + CreateRecurringExpenseCreatorRequestToJSON, GetExpenseEventsResponseFromJSON, GetExpenseEventsResponseToJSON, } from '../models/index'; @@ -29,6 +32,10 @@ export interface CreateOneOffRequest { createOneOffExpenseRequest: CreateOneOffExpenseRequest; } +export interface CreateRecurringExpenseCreatorOperationRequest { + createRecurringExpenseCreatorRequest: CreateRecurringExpenseCreatorRequest; +} + /** * */ @@ -75,6 +82,47 @@ export class ExpensesApi extends runtime.BaseAPI { await this.createOneOffRaw(requestParameters, initOverrides); } + /** + */ + async createRecurringExpenseCreatorRaw(requestParameters: CreateRecurringExpenseCreatorOperationRequest, initOverrides?: RequestInit | runtime.InitOverrideFunction): Promise> { + if (requestParameters['createRecurringExpenseCreatorRequest'] == null) { + throw new runtime.RequiredError( + 'createRecurringExpenseCreatorRequest', + 'Required parameter "createRecurringExpenseCreatorRequest" was null or undefined when calling createRecurringExpenseCreator().' + ); + } + + const queryParameters: any = {}; + + const headerParameters: runtime.HTTPHeaders = {}; + + headerParameters['Content-Type'] = 'application/json'; + + if (this.configuration && this.configuration.accessToken) { + const token = this.configuration.accessToken; + const tokenString = await token("bearerAuth", []); + + if (tokenString) { + headerParameters["Authorization"] = `Bearer ${tokenString}`; + } + } + const response = await this.request({ + path: `/expenses/recurringCreator`, + method: 'POST', + headers: headerParameters, + query: queryParameters, + body: CreateRecurringExpenseCreatorRequestToJSON(requestParameters['createRecurringExpenseCreatorRequest']), + }, initOverrides); + + return new runtime.VoidApiResponse(response); + } + + /** + */ + async createRecurringExpenseCreator(requestParameters: CreateRecurringExpenseCreatorOperationRequest, initOverrides?: RequestInit | runtime.InitOverrideFunction): Promise { + await this.createRecurringExpenseCreatorRaw(requestParameters, initOverrides); + } + /** */ async getExpensesRaw(initOverrides?: RequestInit | runtime.InitOverrideFunction): Promise> { diff --git a/src/main/svelte/src/lib/sdk/models/index.ts b/src/main/svelte/src/lib/sdk/models/index.ts index 738ce1cd..cccd6091 100644 --- a/src/main/svelte/src/lib/sdk/models/index.ts +++ b/src/main/svelte/src/lib/sdk/models/index.ts @@ -1,6 +1,7 @@ /* tslint:disable */ /* eslint-disable */ export * from './CreateOneOffExpenseRequest'; +export * from './CreateRecurringExpenseCreatorRequest'; export * from './ExpenseEvent'; export * from './GetExpenseEventsResponse'; export * from './GetIntroductorySettingsResponse'; diff --git a/src/main/svelte/src/lib/tk/LineEdit.svelte b/src/main/svelte/src/lib/tk/LineEdit.svelte index 3ab3f85a..2bca5f0c 100644 --- a/src/main/svelte/src/lib/tk/LineEdit.svelte +++ b/src/main/svelte/src/lib/tk/LineEdit.svelte @@ -2,7 +2,22 @@ export let id: string; export let label: string; export let type: InputTypes; - export let value: string | Date | number; + export let value: string | Date | number | undefined = undefined; + export let min: number | null = null; + export let max: number | null = null; + export let title: string | null = null; + + function isWithinBounds(): boolean { + if (value === undefined) { + return true; + } else if (typeof value === "number") { + if (value < min! || value > max!) { + return false; + } + } + return true; + } + type InputTypes = | "button" | "checkbox" @@ -26,36 +41,37 @@ | "time" | "url" | "week"; +
{label}
diff --git a/src/main/svelte/src/routes/app/expenses/+page.svelte b/src/main/svelte/src/routes/app/expenses/+page.svelte index 7bd17ac4..9492389f 100644 --- a/src/main/svelte/src/routes/app/expenses/+page.svelte +++ b/src/main/svelte/src/routes/app/expenses/+page.svelte @@ -10,24 +10,20 @@ + -
- - +
+
- - + +
+ +
- - - \ No newline at end of file diff --git a/src/main/svelte/src/routes/app/expenses/createRecurringCreator/+page.svelte b/src/main/svelte/src/routes/app/expenses/createRecurringCreator/+page.svelte new file mode 100644 index 00000000..45d602bd --- /dev/null +++ b/src/main/svelte/src/routes/app/expenses/createRecurringCreator/+page.svelte @@ -0,0 +1,5 @@ + + + \ No newline at end of file