Try to implement autocomplete for payees

This commit is contained in:
Jan Bader 2022-02-01 21:08:37 +00:00
parent b6628dd8cb
commit 46d727c650
5 changed files with 84 additions and 5 deletions

View File

@ -60,6 +60,28 @@ func getDate(c *gin.Context) (time.Time, error) {
return getFirstOfMonth(year, month, time.Now().Location()), nil
}
func (h *Handler) autocompletePayee(c *gin.Context) {
budgetID := c.Param("budgetid")
budgetUUID, err := uuid.Parse(budgetID)
if err != nil {
c.AbortWithError(http.StatusBadRequest, fmt.Errorf("budgetid missing from URL"))
return
}
query := c.Request.URL.Query().Get("s")
searchParams := postgres.SearchPayeesParams{
BudgetID: budgetUUID,
Search: query + "%",
}
payees, err := h.Service.SearchPayees(c.Request.Context(), searchParams)
if err != nil {
c.AbortWithError(http.StatusInternalServerError, err)
return
}
c.JSON(http.StatusOK, payees)
}
func (h *Handler) budgeting(c *gin.Context) {
budgetID := c.Param("budgetid")
budgetUUID, err := uuid.Parse(budgetID)

View File

@ -66,6 +66,7 @@ func (h *Handler) Serve() {
authenticated.GET("/account/:accountid/transactions", h.transactionsForAccount)
authenticated.GET("/admin/clear-database", h.clearDatabase)
authenticated.GET("/budget/:budgetid", h.budgeting)
authenticated.GET("/budget/:budgetid/autocomplete/payees", h.autocompletePayee)
authenticated.DELETE("/budget/:budgetid", h.deleteBudget)
authenticated.POST("/budget/:budgetid/import/ynab", h.importYNAB)
authenticated.POST("/budget/:budgetid/settings/clear", h.clearBudget)

View File

@ -56,3 +56,37 @@ func (q *Queries) GetPayees(ctx context.Context, budgetID uuid.UUID) ([]Payee, e
}
return items, nil
}
const searchPayees = `-- name: SearchPayees :many
SELECT payees.id, payees.budget_id, payees.name FROM payees
WHERE payees.budget_id = $1
AND payees.name LIKE $2
`
type SearchPayeesParams struct {
BudgetID uuid.UUID
Search string
}
func (q *Queries) SearchPayees(ctx context.Context, arg SearchPayeesParams) ([]Payee, error) {
rows, err := q.db.QueryContext(ctx, searchPayees, arg.BudgetID, arg.Search)
if err != nil {
return nil, err
}
defer rows.Close()
var items []Payee
for rows.Next() {
var i Payee
if err := rows.Scan(&i.ID, &i.BudgetID, &i.Name); err != nil {
return nil, err
}
items = append(items, i)
}
if err := rows.Close(); err != nil {
return nil, err
}
if err := rows.Err(); err != nil {
return nil, err
}
return items, nil
}

View File

@ -7,4 +7,10 @@ RETURNING *;
-- name: GetPayees :many
SELECT payees.* FROM payees
WHERE payees.budget_id = $1
ORDER BY name;
ORDER BY name;
-- name: SearchPayees :many
SELECT payees.* FROM payees
WHERE payees.budget_id = @budget_id
AND payees.name LIKE @search;
--ORDER BY levenshtein(payees.name, $2);

View File

@ -6,12 +6,27 @@ export default defineComponent({
return {
TransactionDate: new Date().toISOString().substring(0, 10),
Payee: "",
SearchPayees: null,
Category: "",
Memo: "",
Amount: 0
}
},
props: ["budgetid", "accountid"],
watch: {
SearchPayees() {
GetPayees(this.$data.SearchPayees);
}
},
methods: {
saveTransaction(e : MouseEvent) {
e.preventDefault();
},
GetPayees() {
fetch("/api/v1/budget/" + this.$store.getters.CurrentBudget.ID + "/autocomplete/payees?s=" + this.$data.SearchPayees, {
headers: this.$store.getters.AuthHeaders
}) .then(x=>x.json())
.then(x => console.log(x));
}
}
})
@ -32,16 +47,17 @@ export default defineComponent({
<input type="date" v-model="TransactionDate" />
</td>
<td style="max-width: 150px;">
<input type="text" v-model="Payee" />
<!--<v-autocomplete v-model="Payee" :loading="PayeesLoading" :search-input.sync="SearchPayees" label="Select payee" />-->
<input @change="GetPayees" v-model="SearchPayees" />
</td>
<td style="max-width: 200px;">
<input type="text" />
<input type="text" v-model="Category" />
</td>
<td>
<input type="text" />
<input type="text" v-model="Memo" />
</td>
<td style="width: 80px;">
<input type="number" />
<input type="currency" v-model="Amount" />
</td>
<td style="width: 20px;">
<input type="submit" @click="saveTransaction" value="ι" />