diff --git a/datafetcher/handlers/accounts.go b/datafetcher/handlers/accounts.go index 6b8b884..0418aba 100644 --- a/datafetcher/handlers/accounts.go +++ b/datafetcher/handlers/accounts.go @@ -6,6 +6,7 @@ import ( "log" "net/http" + "github.com/a-h/templ" "github.com/esteanes/expense-manager/datafetcher/templates" "github.com/esteanes/expense-manager/datafetcher/upclient" ) @@ -17,27 +18,72 @@ type AccountHandler struct { func NewAccountHandler(log *log.Logger, upclient *upclient.APIClient, auth context.Context) *AccountHandler { handler := &AccountHandler{} handler.BaseHandler = &BaseHandler{ - Uri: "/accounts", - Log: log, - UpClient: upclient, - UpAuth: auth, - Handler: handler, // Set the Handler interface to the specific handler + Uri: "/accounts", + Log: log, + UpClient: upclient, + UpAuth: auth, + Handler: handler, // Set the Handler interface to the specific handler + MaxPageSize: int32(100), } return handler } func (h *AccountHandler) Post(w http.ResponseWriter, r *http.Request) {} func (h *AccountHandler) Get(w http.ResponseWriter, r *http.Request) { - pageSize := int32(30) filterOwnershipType := upclient.OwnershipTypeEnum("INDIVIDUAL") - resp, r2, err := h.UpClient.AccountsAPI.AccountsGet(h.UpAuth).PageSize(pageSize).FilterOwnershipType(filterOwnershipType).Execute() - h.Log.Println(resp) + accountChannel := make(chan upclient.AccountResource, 10) + clonedChannels := Clone(accountChannel, 2) + accountChannel1 := <-clonedChannels + accountChannel2 := <-clonedChannels + go h.GetAccounts(accountChannel, filterOwnershipType) + + templ.Handler(templates.Accounts(accountChannel1, accountChannel2), templ.WithStreaming()).ServeHTTP(w, r) +} + +func (h *AccountHandler) GetAccounts(accountChannel chan upclient.AccountResource, ownershipType upclient.OwnershipTypeEnum) { + defer close(accountChannel) + resp, r2, err := h.UpClient.AccountsAPI.AccountsGet(h.UpAuth).PageSize(h.MaxPageSize).FilterOwnershipType(ownershipType).Execute() if err != nil { - fmt.Fprintf(w, "Error when calling `AccountsAPI.AccountsGet``: %v\n", err) - fmt.Fprintf(w, "Full HTTP response: %v\n", r2) + h.Log.Println(fmt.Sprintf("Error when calling `AccountsAPI.AccountsGet`: %s\n", err)) + h.Log.Println(fmt.Sprintf("Full HTTP response: %v\n", r2)) h.Log.Println("Unable to get account information") } - // fmt.Fprintf(w, "Response from `AccountsAPI.AccountsGet`: %v\n", resp) - templates.Accounts(resp.Data).Render(r.Context(), w) + for _, account := range resp.Data { + accountChannel <- account + } +} +func Clone[T any](inCh chan T, size int) <-chan <-chan T { + // The channel of channels to return at the end of this function call + ret := make(chan (<-chan T), size) + + // This slice keeps track of all the output channels this function will be creating below. + outChs := make([]chan T, size) + + // Create channels, keep track of them in the slice and send them on the return channel + for i := 0; i < size; i++ { + // The buffer size of the newly created channel is the same as the input channel + outChs[i] = make(chan T, cap(inCh)) + ret <- outChs[i] + } + + // Start a goroutine to manage receiving message from the input channels and sending out to the output channels + // Close the output channels if the input channel has been closed. + go func() { + for { + msg, more := <-inCh + if more { + for _, ch := range outChs { + ch <- msg + } + } else { + for _, ch := range outChs { + close(ch) + } + return + } + } + }() + + return ret } diff --git a/datafetcher/handlers/basehandler.go b/datafetcher/handlers/basehandler.go index 70c2a52..bc8ce54 100644 --- a/datafetcher/handlers/basehandler.go +++ b/datafetcher/handlers/basehandler.go @@ -2,6 +2,7 @@ package handlers import ( "context" + "fmt" "log" "net/http" @@ -14,14 +15,16 @@ type Handler interface { } type BaseHandler struct { - Uri string - Log *log.Logger - UpClient *upclient.APIClient - UpAuth context.Context - Handler Handler // Embed the Handler interface + Uri string + Log *log.Logger + UpClient *upclient.APIClient + UpAuth context.Context + Handler Handler // Embed the Handler interface + MaxPageSize int32 } func (h *BaseHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) { + h.Log.Println(fmt.Sprintf("%s %s params: %s", r.Method, h.Uri, r.URL.Query())) switch r.Method { case http.MethodPost: h.Handler.Post(w, r) diff --git a/datafetcher/handlers/transactions.go b/datafetcher/handlers/transactions.go index f7e0deb..66141fc 100644 --- a/datafetcher/handlers/transactions.go +++ b/datafetcher/handlers/transactions.go @@ -5,37 +5,95 @@ import ( "fmt" "log" "net/http" + "net/url" + "strconv" + "github.com/a-h/templ" "github.com/esteanes/expense-manager/datafetcher/templates" - "github.com/esteanes/expense-manager/datafetcher/upclient" ) type TransactionsHandler struct { *BaseHandler + *AccountHandler } -func NewTransactionHandler(log *log.Logger, upclient *upclient.APIClient, auth context.Context) *TransactionsHandler { +func NewTransactionHandler(log *log.Logger, upclient *upclient.APIClient, auth context.Context, accountHandler *AccountHandler) *TransactionsHandler { handler := &TransactionsHandler{} handler.BaseHandler = &BaseHandler{ - Uri: "/transactions", - Log: log, - UpClient: upclient, - UpAuth: auth, - Handler: handler, // Set the Handler interface to the specific handler + Uri: "/transactions", + Log: log, + UpClient: upclient, + UpAuth: auth, + Handler: handler, // Set the Handler interface to the specific handler + MaxPageSize: int32(100), } + handler.AccountHandler = accountHandler return handler } func (h *TransactionsHandler) Post(w http.ResponseWriter, r *http.Request) {} func (h *TransactionsHandler) Get(w http.ResponseWriter, r *http.Request) { - pageSize := int32(30) // int32 | The number of records to return in each page. (optional) - resp, r2, err := h.UpClient.TransactionsAPI.TransactionsGet(h.UpAuth).PageSize(pageSize).Execute() + queryParams := r.URL.Query() + numTransactions, err := strconv.ParseInt(queryParams.Get("numTransactions"), 10, 32) if err != nil { - fmt.Fprintf(w, "Error when calling `TransactionsAPI.TransactionsGet``: %v\n", err) - fmt.Fprintf(w, "Full HTTP response: %v\n", r2.Body) - h.Log.Println(r2.Body) + numTransactions = int64(10) + } + accountId := queryParams.Get("accountId") + transactionsChannel := make(chan upclient.TransactionResource, numTransactions) + go h.getTransactions(transactionsChannel, int32(numTransactions), accountId) + accountsChannel := make(chan upclient.AccountResource) + go h.AccountHandler.GetAccounts(accountsChannel, upclient.OwnershipTypeEnum("INDIVIDUAL")) + templ.Handler(templates.Transactions(transactionsChannel, accountsChannel), templ.WithStreaming()).ServeHTTP(w, r) + +} +func (h *TransactionsHandler) getTransactions(transactionsChannel chan upclient.TransactionResource, numTransactions int32, accountId string) { + defer close(transactionsChannel) + getRequest := h.UpClient.TransactionsAPI.AccountsAccountIdTransactionsGet(h.UpAuth, accountId).PageSize(h.MaxPageSize) + var pageAfter *string + pageAfter = nil + countTransactions := int32(0) + for countTransactions < numTransactions { + if pageAfter != nil { + pageKeyParsed, _ := ExtractPageAfter(*pageAfter) + getRequest = getRequest.PageAfter(pageKeyParsed) + h.Log.Println(fmt.Sprintf("setting pageAfter to %s", pageKeyParsed)) + } + h.Log.Println(fmt.Sprintf("request struct is %+v", getRequest)) + resp, r2, err := getRequest.Execute() + if err != nil { + h.Log.Println(fmt.Sprintf("Error when calling `TransactionsAPI.TransactionsGet``: %s\n", err)) + h.Log.Println(fmt.Sprintf("Full HTTP response: %s\n", r2.Body)) + h.Log.Println(r2.Body) + return + } + // h.Log.Println(fmt.Sprintf("resp object is %#v", resp)) + pageAfter = resp.Links.Next.Get() + h.Log.Println(fmt.Sprintf("pageAfter is %p", pageAfter)) + if pageAfter != nil { + h.Log.Println(fmt.Sprintf("page after link is: %s", *pageAfter)) + } + for _, transaction := range resp.Data { + if countTransactions < numTransactions { + transactionsChannel <- transaction + countTransactions++ + } + } } - // response from `TransactionsGet`: ListTransactionsResponse - templates.Transactions(resp.Data).Render(r.Context(), w) +} + +func ExtractPageAfter(inputURL string) (string, error) { + // Parse the URL + parsedURL, err := url.Parse(inputURL) + if err != nil { + return "", err + } + + // Extract the query parameters + queryParams := parsedURL.Query() + + // Get the value of "page[before]" + pageAfter := queryParams.Get("page[after]") + + return pageAfter, nil } diff --git a/datafetcher/server.go b/datafetcher/server.go index 975aadf..80457ac 100644 --- a/datafetcher/server.go +++ b/datafetcher/server.go @@ -86,7 +86,7 @@ func HandleRequests(upBankToken string, log *log.Logger) { // Creating individual handlers accountHandler := handlers.NewAccountHandler(log, apiClient, auth) - transactionsHandler := handlers.NewTransactionHandler(log, apiClient, auth) + transactionsHandler := handlers.NewTransactionHandler(log, apiClient, auth, accountHandler) transactionsCsvHandler := handlers.NewTransactionCsvHandler(log, apiClient, auth) mux := http.NewServeMux() mux.HandleFunc(accountHandler.Uri, accountHandler.ServeHTTP) diff --git a/datafetcher/templates/accounts.templ b/datafetcher/templates/accounts.templ index 4d33a8f..4bb44ee 100644 --- a/datafetcher/templates/accounts.templ +++ b/datafetcher/templates/accounts.templ @@ -5,7 +5,36 @@ import ( "strings" ) -templ Accounts(accounts []upclient.AccountResource) { +templ AccountDetails(accounts <-chan upclient.AccountResource) { +
Account Type: { strings.ToTitle(string(account.Attributes.AccountType)) }
+Balance: { account.Attributes.Balance.CurrencyCode } { account.Attributes.Balance.Value }
+Created At: { account.Attributes.CreatedAt.String() }
+Id: { account.Id }
+Account Type: { strings.ToTitle(string(account.Attributes.AccountType)) }
-Balance: { account.Attributes.Balance.CurrencyCode } { account.Attributes.Balance.Value }
-Created At: { account.Attributes.CreatedAt.String() }
-Account Type: ") - if templ_7745c5c3_Err != nil { - return templ_7745c5c3_Err - } - var templ_7745c5c3_Var3 string - templ_7745c5c3_Var3, templ_7745c5c3_Err = templ.JoinStringErrs(strings.ToTitle(string(account.Attributes.AccountType))) - if templ_7745c5c3_Err != nil { - return templ.Error{Err: templ_7745c5c3_Err, FileName: `datafetcher/templates/accounts.templ`, Line: 22, Col: 80} - } - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var3)) - if templ_7745c5c3_Err != nil { - return templ_7745c5c3_Err - } - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("
Balance: ") - if templ_7745c5c3_Err != nil { - return templ_7745c5c3_Err - } - var templ_7745c5c3_Var4 string - templ_7745c5c3_Var4, templ_7745c5c3_Err = templ.JoinStringErrs(account.Attributes.Balance.CurrencyCode) - if templ_7745c5c3_Err != nil { - return templ.Error{Err: templ_7745c5c3_Err, FileName: `datafetcher/templates/accounts.templ`, Line: 23, Col: 59} - } - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var4)) - if templ_7745c5c3_Err != nil { - return templ_7745c5c3_Err - } - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(" ") - if templ_7745c5c3_Err != nil { - return templ_7745c5c3_Err - } - var templ_7745c5c3_Var5 string - templ_7745c5c3_Var5, templ_7745c5c3_Err = templ.JoinStringErrs(account.Attributes.Balance.Value) - if templ_7745c5c3_Err != nil { - return templ.Error{Err: templ_7745c5c3_Err, FileName: `datafetcher/templates/accounts.templ`, Line: 23, Col: 96} - } - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var5)) - if templ_7745c5c3_Err != nil { + for account := range accounts { + templ_7745c5c3_Var2 := templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) { + templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context + templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templruntime.GetBuffer(templ_7745c5c3_W) + if !templ_7745c5c3_IsBuffer { + defer func() { + templ_7745c5c3_BufErr := templruntime.ReleaseBuffer(templ_7745c5c3_Buffer) + if templ_7745c5c3_Err == nil { + templ_7745c5c3_Err = templ_7745c5c3_BufErr + } + }() + } + ctx = templ.InitializeContext(ctx) + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("
Account Type: ") + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + var templ_7745c5c3_Var4 string + templ_7745c5c3_Var4, templ_7745c5c3_Err = templ.JoinStringErrs(strings.ToTitle(string(account.Attributes.AccountType))) + if templ_7745c5c3_Err != nil { + return templ.Error{Err: templ_7745c5c3_Err, FileName: `datafetcher/templates/accounts.templ`, Line: 15, Col: 79} + } + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var4)) + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("
Balance: ") + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + var templ_7745c5c3_Var5 string + templ_7745c5c3_Var5, templ_7745c5c3_Err = templ.JoinStringErrs(account.Attributes.Balance.CurrencyCode) + if templ_7745c5c3_Err != nil { + return templ.Error{Err: templ_7745c5c3_Err, FileName: `datafetcher/templates/accounts.templ`, Line: 16, Col: 58} + } + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var5)) + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(" ") + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + var templ_7745c5c3_Var6 string + templ_7745c5c3_Var6, templ_7745c5c3_Err = templ.JoinStringErrs(account.Attributes.Balance.Value) + if templ_7745c5c3_Err != nil { + return templ.Error{Err: templ_7745c5c3_Err, FileName: `datafetcher/templates/accounts.templ`, Line: 16, Col: 95} + } + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var6)) + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("
Created At: ") + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + var templ_7745c5c3_Var7 string + templ_7745c5c3_Var7, templ_7745c5c3_Err = templ.JoinStringErrs(account.Attributes.CreatedAt.String()) + if templ_7745c5c3_Err != nil { + return templ.Error{Err: templ_7745c5c3_Err, FileName: `datafetcher/templates/accounts.templ`, Line: 17, Col: 59} + } + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var7)) + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("
Id: ") + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + var templ_7745c5c3_Var8 string + templ_7745c5c3_Var8, templ_7745c5c3_Err = templ.JoinStringErrs(account.Id) + if templ_7745c5c3_Err != nil { + return templ.Error{Err: templ_7745c5c3_Err, FileName: `datafetcher/templates/accounts.templ`, Line: 18, Col: 24} + } + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var8)) + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("
Created At: ") + }) + templ_7745c5c3_Err = templ.Flush().Render(templ.WithChildren(ctx, templ_7745c5c3_Var2), templ_7745c5c3_Buffer) if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } - var templ_7745c5c3_Var6 string - templ_7745c5c3_Var6, templ_7745c5c3_Err = templ.JoinStringErrs(account.Attributes.CreatedAt.String()) - if templ_7745c5c3_Err != nil { - return templ.Error{Err: templ_7745c5c3_Err, FileName: `datafetcher/templates/accounts.templ`, Line: 24, Col: 60} - } - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var6)) - if templ_7745c5c3_Err != nil { + } + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("") + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + return templ_7745c5c3_Err + }) +} + +func AccountButtons(accounts <-chan upclient.AccountResource) templ.Component { + return templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) { + templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context + templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templruntime.GetBuffer(templ_7745c5c3_W) + if !templ_7745c5c3_IsBuffer { + defer func() { + templ_7745c5c3_BufErr := templruntime.ReleaseBuffer(templ_7745c5c3_Buffer) + if templ_7745c5c3_Err == nil { + templ_7745c5c3_Err = templ_7745c5c3_BufErr + } + }() + } + ctx = templ.InitializeContext(ctx) + templ_7745c5c3_Var9 := templ.GetChildren(ctx) + if templ_7745c5c3_Var9 == nil { + templ_7745c5c3_Var9 = templ.NopComponent + } + ctx = templ.ClearChildren(ctx) + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("
Transaction Amount | +Description | +Status | +Time | +Message | +Category | +Purchase Method | +Card Number | +
---|---|---|---|---|---|---|---|
{ transaction.Attributes.Amount.Value } | +{ transaction.Attributes.Description } | +{ string(transaction.Attributes.Status) } | +{ transaction.Attributes.CreatedAt.String() } | +{ getMessage(transaction) } | +{ getCategory(transaction) } | +{ getCardPurchase(transaction) } | +{ getCardPurchaseNumber(transaction) } | +
Transaction Amount | -Description | -Status | -Time | -Message | -Purchase Method | -Card Number | -
---|---|---|---|---|---|---|
{ transaction.Attributes.Amount.Value } | -{ transaction.Attributes.Description } | -{ string(transaction.Attributes.Status) } | -{ transaction.Attributes.CreatedAt.String() } | -{ getMessage(transaction) } | -{ getCardPurchase(transaction) } | -{ getCardPurchaseNumber(transaction) } | -
Transaction Amount | Description | Status | Time | Message | Purchase Method | Card Number |
---|
Transaction Amount | Description | Status | Time | Message | Category | Purchase Method | Card Number |
---|---|---|---|---|---|---|---|
") - if templ_7745c5c3_Err != nil { - return templ_7745c5c3_Err - } - var templ_7745c5c3_Var2 string - templ_7745c5c3_Var2, templ_7745c5c3_Err = templ.JoinStringErrs(transaction.Attributes.Amount.Value) - if templ_7745c5c3_Err != nil { - return templ.Error{Err: templ_7745c5c3_Err, FileName: `datafetcher/templates/transactions.templ`, Line: 72, Col: 48} - } - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var2)) - if templ_7745c5c3_Err != nil { - return templ_7745c5c3_Err - } - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(" | ") - if templ_7745c5c3_Err != nil { - return templ_7745c5c3_Err - } - var templ_7745c5c3_Var3 string - templ_7745c5c3_Var3, templ_7745c5c3_Err = templ.JoinStringErrs(transaction.Attributes.Description) - if templ_7745c5c3_Err != nil { - return templ.Error{Err: templ_7745c5c3_Err, FileName: `datafetcher/templates/transactions.templ`, Line: 73, Col: 47} - } - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var3)) - if templ_7745c5c3_Err != nil { - return templ_7745c5c3_Err - } - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(" | ") - if templ_7745c5c3_Err != nil { - return templ_7745c5c3_Err - } - var templ_7745c5c3_Var4 string - templ_7745c5c3_Var4, templ_7745c5c3_Err = templ.JoinStringErrs(string(transaction.Attributes.Status)) - if templ_7745c5c3_Err != nil { - return templ.Error{Err: templ_7745c5c3_Err, FileName: `datafetcher/templates/transactions.templ`, Line: 74, Col: 50} - } - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var4)) - if templ_7745c5c3_Err != nil { - return templ_7745c5c3_Err - } - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(" | ") - if templ_7745c5c3_Err != nil { - return templ_7745c5c3_Err - } - var templ_7745c5c3_Var5 string - templ_7745c5c3_Var5, templ_7745c5c3_Err = templ.JoinStringErrs(transaction.Attributes.CreatedAt.String()) - if templ_7745c5c3_Err != nil { - return templ.Error{Err: templ_7745c5c3_Err, FileName: `datafetcher/templates/transactions.templ`, Line: 75, Col: 54} - } - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var5)) - if templ_7745c5c3_Err != nil { - return templ_7745c5c3_Err - } - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(" | ") - if templ_7745c5c3_Err != nil { - return templ_7745c5c3_Err - } - var templ_7745c5c3_Var6 string - templ_7745c5c3_Var6, templ_7745c5c3_Err = templ.JoinStringErrs(getMessage(transaction)) - if templ_7745c5c3_Err != nil { - return templ.Error{Err: templ_7745c5c3_Err, FileName: `datafetcher/templates/transactions.templ`, Line: 76, Col: 36} - } - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var6)) - if templ_7745c5c3_Err != nil { - return templ_7745c5c3_Err - } - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(" | ") - if templ_7745c5c3_Err != nil { - return templ_7745c5c3_Err - } - var templ_7745c5c3_Var7 string - templ_7745c5c3_Var7, templ_7745c5c3_Err = templ.JoinStringErrs(getCardPurchase(transaction)) - if templ_7745c5c3_Err != nil { - return templ.Error{Err: templ_7745c5c3_Err, FileName: `datafetcher/templates/transactions.templ`, Line: 77, Col: 41} - } - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var7)) - if templ_7745c5c3_Err != nil { - return templ_7745c5c3_Err - } - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(" | ") - if templ_7745c5c3_Err != nil { - return templ_7745c5c3_Err - } - var templ_7745c5c3_Var8 string - templ_7745c5c3_Var8, templ_7745c5c3_Err = templ.JoinStringErrs(getCardPurchaseNumber(transaction)) - if templ_7745c5c3_Err != nil { - return templ.Error{Err: templ_7745c5c3_Err, FileName: `datafetcher/templates/transactions.templ`, Line: 78, Col: 47} - } - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var8)) - if templ_7745c5c3_Err != nil { + for transaction := range transactions { + templ_7745c5c3_Var2 := templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) { + templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context + templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templruntime.GetBuffer(templ_7745c5c3_W) + if !templ_7745c5c3_IsBuffer { + defer func() { + templ_7745c5c3_BufErr := templruntime.ReleaseBuffer(templ_7745c5c3_Buffer) + if templ_7745c5c3_Err == nil { + templ_7745c5c3_Err = templ_7745c5c3_BufErr + } + }() + } + ctx = templ.InitializeContext(ctx) + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(" | |
") + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + var templ_7745c5c3_Var3 string + templ_7745c5c3_Var3, templ_7745c5c3_Err = templ.JoinStringErrs(transaction.Attributes.Amount.Value) + if templ_7745c5c3_Err != nil { + return templ.Error{Err: templ_7745c5c3_Err, FileName: `datafetcher/templates/transactions.templ`, Line: 61, Col: 47} + } + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var3)) + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(" | ") + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + var templ_7745c5c3_Var4 string + templ_7745c5c3_Var4, templ_7745c5c3_Err = templ.JoinStringErrs(transaction.Attributes.Description) + if templ_7745c5c3_Err != nil { + return templ.Error{Err: templ_7745c5c3_Err, FileName: `datafetcher/templates/transactions.templ`, Line: 62, Col: 46} + } + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var4)) + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(" | ") + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + var templ_7745c5c3_Var5 string + templ_7745c5c3_Var5, templ_7745c5c3_Err = templ.JoinStringErrs(string(transaction.Attributes.Status)) + if templ_7745c5c3_Err != nil { + return templ.Error{Err: templ_7745c5c3_Err, FileName: `datafetcher/templates/transactions.templ`, Line: 63, Col: 49} + } + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var5)) + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(" | ") + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + var templ_7745c5c3_Var6 string + templ_7745c5c3_Var6, templ_7745c5c3_Err = templ.JoinStringErrs(transaction.Attributes.CreatedAt.String()) + if templ_7745c5c3_Err != nil { + return templ.Error{Err: templ_7745c5c3_Err, FileName: `datafetcher/templates/transactions.templ`, Line: 64, Col: 53} + } + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var6)) + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(" | ") + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + var templ_7745c5c3_Var7 string + templ_7745c5c3_Var7, templ_7745c5c3_Err = templ.JoinStringErrs(getMessage(transaction)) + if templ_7745c5c3_Err != nil { + return templ.Error{Err: templ_7745c5c3_Err, FileName: `datafetcher/templates/transactions.templ`, Line: 65, Col: 35} + } + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var7)) + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(" | ") + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + var templ_7745c5c3_Var8 string + templ_7745c5c3_Var8, templ_7745c5c3_Err = templ.JoinStringErrs(getCategory(transaction)) + if templ_7745c5c3_Err != nil { + return templ.Error{Err: templ_7745c5c3_Err, FileName: `datafetcher/templates/transactions.templ`, Line: 66, Col: 36} + } + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var8)) + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(" | ") + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + var templ_7745c5c3_Var9 string + templ_7745c5c3_Var9, templ_7745c5c3_Err = templ.JoinStringErrs(getCardPurchase(transaction)) + if templ_7745c5c3_Err != nil { + return templ.Error{Err: templ_7745c5c3_Err, FileName: `datafetcher/templates/transactions.templ`, Line: 67, Col: 40} + } + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var9)) + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(" | ") + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + var templ_7745c5c3_Var10 string + templ_7745c5c3_Var10, templ_7745c5c3_Err = templ.JoinStringErrs(getCardPurchaseNumber(transaction)) + if templ_7745c5c3_Err != nil { + return templ.Error{Err: templ_7745c5c3_Err, FileName: `datafetcher/templates/transactions.templ`, Line: 68, Col: 46} + } + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var10)) + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(" |