app is now using historical exchange rates for transactions

This commit is contained in:
Matthias Hinrichs
2025-07-05 03:44:53 +02:00
parent a96bbe4d2a
commit aef9342cc5
11 changed files with 926 additions and 237 deletions
+180 -16
View File
@@ -18,7 +18,7 @@ func calculateTotalInvested(activities []model.Activity) float64 {
return total
}
// calculateTotalInvestedInBaseCurrency calculates total invested converted to portfolio base currency
// calculateTotalInvestedInBaseCurrency calculates total invested converted to portfolio base currency using historical rates
func calculateTotalInvestedInBaseCurrency(activities []model.Activity, baseCurrency string) float64 {
var total float64 = 0
for _, activity := range activities {
@@ -28,10 +28,17 @@ func calculateTotalInvestedInBaseCurrency(activities []model.Activity, baseCurre
if activity.Currency == baseCurrency {
total += activityTotal
} else {
convertedTotal, err := util.ConvertCurrency(activityTotal, activity.Currency, baseCurrency)
// Use historical exchange rate for the transaction date
convertedTotal, err := util.ConvertCurrencyHistorical(activityTotal, activity.Currency, baseCurrency, activity.Date)
if err != nil {
// If conversion fails, add original amount (fallback)
total += activityTotal
// If historical conversion fails, try current rate as fallback
fallbackTotal, fallbackErr := util.ConvertCurrency(activityTotal, activity.Currency, baseCurrency)
if fallbackErr != nil {
// If all conversions fail, add original amount (last resort)
total += activityTotal
} else {
total += fallbackTotal
}
} else {
total += convertedTotal
}
@@ -55,13 +62,13 @@ func getLastBuyDate(activities []model.Activity) string {
return lastBuy.Format("02.01.2006")
}
// convertActivityPrice converts activity price to portfolio base currency if different
// convertActivityPrice converts activity price to portfolio base currency using historical rate
func convertActivityPrice(activity model.Activity, portfolioBaseCurrency string) (float64, string, error) {
if activity.Currency == portfolioBaseCurrency {
return activity.Price, "", nil // No conversion needed
}
convertedPrice, err := util.ConvertCurrency(activity.Price, activity.Currency, portfolioBaseCurrency)
convertedPrice, err := util.ConvertCurrencyHistorical(activity.Price, activity.Currency, portfolioBaseCurrency, activity.Date)
if err != nil {
return 0, "", err
}
@@ -69,13 +76,13 @@ func convertActivityPrice(activity model.Activity, portfolioBaseCurrency string)
return convertedPrice, portfolioBaseCurrency, nil
}
// formatActivityPrice formats activity price with conversion if needed
// formatActivityPrice formats activity price with conversion if needed using historical rates
func formatActivityPrice(activity model.Activity, portfolioBaseCurrency string) string {
if activity.Currency == portfolioBaseCurrency {
return fmt.Sprintf("%.2f %s", activity.Price, activity.Currency)
}
convertedPrice, err := util.ConvertCurrency(activity.Price, activity.Currency, portfolioBaseCurrency)
convertedPrice, err := util.ConvertCurrencyHistorical(activity.Price, activity.Currency, portfolioBaseCurrency, activity.Date)
if err != nil {
return fmt.Sprintf("%.2f %s (conv. error)", activity.Price, activity.Currency)
}
@@ -83,7 +90,7 @@ func formatActivityPrice(activity model.Activity, portfolioBaseCurrency string)
return fmt.Sprintf("%.2f %s (~%.2f %s)", activity.Price, activity.Currency, convertedPrice, portfolioBaseCurrency)
}
// formatActivityTotal formats activity total with conversion if needed
// formatActivityTotal formats activity total with conversion if needed using historical rates
func formatActivityTotal(activity model.Activity, portfolioBaseCurrency string) string {
total := activity.Amount * activity.Price
@@ -91,7 +98,7 @@ func formatActivityTotal(activity model.Activity, portfolioBaseCurrency string)
return fmt.Sprintf("%.2f %s", total, activity.Currency)
}
convertedTotal, err := util.ConvertCurrency(total, activity.Currency, portfolioBaseCurrency)
convertedTotal, err := util.ConvertCurrencyHistorical(total, activity.Currency, portfolioBaseCurrency, activity.Date)
if err != nil {
return fmt.Sprintf("%.2f %s (conv. error)", total, activity.Currency)
}
@@ -99,28 +106,38 @@ func formatActivityTotal(activity model.Activity, portfolioBaseCurrency string)
return fmt.Sprintf("%.2f %s (~%.2f %s)", total, activity.Currency, convertedTotal, portfolioBaseCurrency)
}
// getConvertedPrice returns the converted price or original if conversion fails
// getConvertedPrice returns the converted price using historical exchange rate or original if conversion fails
func getConvertedPrice(activity model.Activity, portfolioBaseCurrency string) string {
if activity.Currency == portfolioBaseCurrency {
return ""
}
convertedPrice, err := util.ConvertCurrency(activity.Price, activity.Currency, portfolioBaseCurrency)
// Use historical exchange rate for the transaction date
convertedPrice, isHistorical, err := util.GetExchangeRateWithFallback(activity.Currency, portfolioBaseCurrency, activity.Date)
if err != nil {
return "Conv. Error"
}
return fmt.Sprintf("%.2f %s", convertedPrice, portfolioBaseCurrency)
finalPrice := activity.Price * convertedPrice
// Add indicator if fallback (current) rate was used instead of historical
if !isHistorical {
return fmt.Sprintf("%.2f %s*", finalPrice, portfolioBaseCurrency)
}
return fmt.Sprintf("%.2f %s", finalPrice, portfolioBaseCurrency)
}
// getConvertedTotal returns the converted total or original if conversion fails
// getConvertedTotal returns the converted total using historical exchange rate or original if conversion fails
func getConvertedTotal(activity model.Activity, portfolioBaseCurrency string) string {
if activity.Currency == portfolioBaseCurrency {
return ""
}
total := activity.Amount * activity.Price
convertedTotal, err := util.ConvertCurrency(total, activity.Currency, portfolioBaseCurrency)
// Use historical exchange rate for the transaction date
convertedTotal, err := util.ConvertCurrencyHistorical(total, activity.Currency, portfolioBaseCurrency, activity.Date)
if err != nil {
return "Conv. Error"
}
@@ -128,15 +145,47 @@ func getConvertedTotal(activity model.Activity, portfolioBaseCurrency string) st
return fmt.Sprintf("%.2f %s", convertedTotal, portfolioBaseCurrency)
}
// formatTotalInvestedWithConversion formats total invested with currency info
// getConvertedTotalWithFallbackInfo returns the converted total with information about rate source
func getConvertedTotalWithFallbackInfo(activity model.Activity, portfolioBaseCurrency string) string {
if activity.Currency == portfolioBaseCurrency {
return ""
}
total := activity.Amount * activity.Price
// Use historical exchange rate with fallback information
rate, isHistorical, err := util.GetExchangeRateWithFallback(activity.Currency, portfolioBaseCurrency, activity.Date)
if err != nil {
return "Conv. Error"
}
convertedTotal := total * rate
// Add indicator if fallback (current) rate was used instead of historical
if !isHistorical {
return fmt.Sprintf("%.2f %s*", convertedTotal, portfolioBaseCurrency)
}
return fmt.Sprintf("%.2f %s", convertedTotal, portfolioBaseCurrency)
}
// formatTotalInvestedWithConversion formats total invested with currency info and conversion indicators
func formatTotalInvestedWithConversion(activities []model.Activity, baseCurrency string) string {
convertedTotal := calculateTotalInvestedInBaseCurrency(activities, baseCurrency)
// Check if any activities have different currencies
hasDifferentCurrencies := false
hasHistoricalConversions := false
for _, activity := range activities {
if activity.Type == model.Buy && activity.Currency != baseCurrency {
hasDifferentCurrencies = true
// Check if we can get historical rate for this transaction
_, isHistorical, err := util.GetExchangeRateWithFallback(activity.Currency, baseCurrency, activity.Date)
if err == nil && isHistorical {
hasHistoricalConversions = true
}
break
}
}
@@ -145,5 +194,120 @@ func formatTotalInvestedWithConversion(activities []model.Activity, baseCurrency
return fmt.Sprintf("%.2f %s", convertedTotal, baseCurrency)
}
if hasHistoricalConversions {
return fmt.Sprintf("%.2f %s (historical rates)", convertedTotal, baseCurrency)
}
return fmt.Sprintf("%.2f %s (converted)", convertedTotal, baseCurrency)
}
// calculateTotalInvestedByDate calculates total invested up to a specific date
func calculateTotalInvestedByDate(activities []model.Activity, baseCurrency string, endDate time.Time) float64 {
var total float64 = 0
for _, activity := range activities {
if activity.Type == model.Buy && activity.Date.Before(endDate.AddDate(0, 0, 1)) { // Include transactions on endDate
activityTotal := activity.Amount * activity.Price
if activity.Currency == baseCurrency {
total += activityTotal
} else {
// Use historical exchange rate for the transaction date
convertedTotal, err := util.ConvertCurrencyHistorical(activityTotal, activity.Currency, baseCurrency, activity.Date)
if err != nil {
// If historical conversion fails, try current rate as fallback
fallbackTotal, fallbackErr := util.ConvertCurrency(activityTotal, activity.Currency, baseCurrency)
if fallbackErr != nil {
// If all conversions fail, add original amount (last resort)
total += activityTotal
} else {
total += fallbackTotal
}
} else {
total += convertedTotal
}
}
}
}
return total
}
// getConversionInfo returns information about currency conversions used in the portfolio
func getConversionInfo(activities []model.Activity, baseCurrency string) map[string]interface{} {
info := map[string]interface{}{
"hasDifferentCurrencies": false,
"historicalConversions": 0,
"fallbackConversions": 0,
"errorConversions": 0,
"currencies": make(map[string]int),
}
currencies := make(map[string]int)
historicalCount := 0
fallbackCount := 0
errorCount := 0
for _, activity := range activities {
if activity.Type == model.Buy {
currencies[activity.Currency]++
if activity.Currency != baseCurrency {
info["hasDifferentCurrencies"] = true
// Check conversion status
_, isHistorical, err := util.GetExchangeRateWithFallback(activity.Currency, baseCurrency, activity.Date)
if err != nil {
errorCount++
} else if isHistorical {
historicalCount++
} else {
fallbackCount++
}
}
}
}
info["historicalConversions"] = historicalCount
info["fallbackConversions"] = fallbackCount
info["errorConversions"] = errorCount
info["currencies"] = currencies
return info
}
// formatCurrencyWithConversionNote formats currency amount with appropriate conversion notes
func formatCurrencyWithConversionNote(amount float64, fromCurrency, toCurrency string, transactionDate time.Time) string {
if fromCurrency == toCurrency {
return util.FormatCurrencyWithSymbol(amount, toCurrency)
}
rate, isHistorical, err := util.GetExchangeRateWithFallback(fromCurrency, toCurrency, transactionDate)
if err != nil {
return fmt.Sprintf("%.2f %s (conv. error)", amount, fromCurrency)
}
convertedAmount := amount * rate
if isHistorical {
return fmt.Sprintf("%.2f %s (historical rate)", convertedAmount, toCurrency)
}
return fmt.Sprintf("%.2f %s (current rate)", convertedAmount, toCurrency)
}
// getActivityConversionStatus returns the conversion status for a specific activity
func getActivityConversionStatus(activity model.Activity, portfolioBaseCurrency string) string {
if activity.Currency == portfolioBaseCurrency {
return "same_currency"
}
_, isHistorical, err := util.GetExchangeRateWithFallback(activity.Currency, portfolioBaseCurrency, activity.Date)
if err != nil {
return "error"
}
if isHistorical {
return "historical"
}
return "fallback"
}
@@ -128,7 +128,7 @@ templ PortfolioDetailContent(portfolio model.Portfolio) {
<td>{ fmt.Sprintf("%.2f %s", activity.Amount * activity.Price, activity.Currency) }</td>
<td>
if activity.Currency != portfolio.BaseCurrency {
{ getConvertedTotal(activity, portfolio.BaseCurrency) }
{ getConvertedTotalWithFallbackInfo(activity, portfolio.BaseCurrency) }
} else {
<span class="text-muted">-</span>
}
@@ -194,10 +194,10 @@ templ PortfolioDetailContent(portfolio model.Portfolio) {
</svg>
</div>
<div class="flex-fill">
<div class="font-weight-medium">Währungsumrechnung</div>
<div class="font-weight-medium">Historische Währungsumrechnung</div>
<div class="text-muted small">
Transaktionen in anderen Währungen werden automatisch in { portfolio.BaseCurrency } umgerechnet.
Wechselkurse werden stündlich aktualisiert.
Transaktionen werden mit den historischen Wechselkursen vom Transaktionsdatum in { portfolio.BaseCurrency } umgerechnet.
Bei nicht verfügbaren historischen Kursen werden aktuelle Kurse verwendet (markiert mit *).
</div>
</div>
</div>
@@ -408,6 +408,9 @@ templ PortfolioSummary(activities []model.Activity, currency string) {
<div class="h2 mb-0">
{ formatTotalInvestedWithConversion(activities, currency) }
</div>
<div class="text-muted small">
* = Aktueller Kurs verwendet (historischer Kurs nicht verfügbar)
</div>
</div>
<div class="mb-3">
<div class="text-muted">Letzter Kauf</div>
@@ -1,6 +1,6 @@
// Code generated by templ - DO NOT EDIT.
// templ: version: v0.2.778
// templ: version: v0.3.906
package templates
//lint:file-ignore SA4006 This context is only used if a nested component is present.
@@ -35,33 +35,33 @@ func PortfolioDetailContent(portfolio model.Portfolio) templ.Component {
templ_7745c5c3_Var1 = templ.NopComponent
}
ctx = templ.ClearChildren(ctx)
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("<div class=\"container-fluid mt-4\"><div class=\"page-header\"><div class=\"row g-2 align-items-center\"><div class=\"col\"><h2 class=\"page-title\">")
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 1, "<div class=\"container-fluid mt-4\"><div class=\"page-header\"><div class=\"row g-2 align-items-center\"><div class=\"col\"><h2 class=\"page-title\">")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
var templ_7745c5c3_Var2 string
templ_7745c5c3_Var2, templ_7745c5c3_Err = templ.JoinStringErrs(portfolio.Name)
if templ_7745c5c3_Err != nil {
return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/web/templates/portfolio-detail.templ`, Line: 14, Col: 44}
return templ.Error{Err: templ_7745c5c3_Err, FileName: `portfolio-detail.templ`, Line: 14, Col: 44}
}
_, 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(" (")
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 2, " (")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
var templ_7745c5c3_Var3 string
templ_7745c5c3_Var3, templ_7745c5c3_Err = templ.JoinStringErrs(portfolio.BaseCurrency)
if templ_7745c5c3_Err != nil {
return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/web/templates/portfolio-detail.templ`, Line: 14, Col: 72}
return templ.Error{Err: templ_7745c5c3_Err, FileName: `portfolio-detail.templ`, Line: 14, Col: 72}
}
_, 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(")</h2><div class=\"page-subtitle\">")
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 3, ")</h2><div class=\"page-subtitle\">")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
@@ -69,175 +69,179 @@ func PortfolioDetailContent(portfolio model.Portfolio) templ.Component {
var templ_7745c5c3_Var4 string
templ_7745c5c3_Var4, templ_7745c5c3_Err = templ.JoinStringErrs(portfolio.Description)
if templ_7745c5c3_Err != nil {
return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/web/templates/portfolio-detail.templ`, Line: 17, Col: 30}
return templ.Error{Err: templ_7745c5c3_Err, FileName: `portfolio-detail.templ`, Line: 17, Col: 30}
}
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var4))
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
} else {
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("Erstellt am ")
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 4, "Erstellt am ")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
var templ_7745c5c3_Var5 string
templ_7745c5c3_Var5, templ_7745c5c3_Err = templ.JoinStringErrs(portfolio.CreatedAt.Format("02.01.2006"))
if templ_7745c5c3_Err != nil {
return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/web/templates/portfolio-detail.templ`, Line: 19, Col: 61}
return templ.Error{Err: templ_7745c5c3_Err, FileName: `portfolio-detail.templ`, Line: 19, Col: 61}
}
_, 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("</div></div><div class=\"col-auto ms-auto d-print-none\"><div class=\"btn-list\"><button type=\"button\" class=\"btn btn-primary\" data-bs-toggle=\"modal\" data-bs-target=\"#addTransactionModal\"><svg xmlns=\"http://www.w3.org/2000/svg\" class=\"icon\" width=\"24\" height=\"24\" viewBox=\"0 0 24 24\" stroke-width=\"2\" stroke=\"currentColor\" fill=\"none\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><path stroke=\"none\" d=\"M0 0h24v24H0z\" fill=\"none\"></path> <path d=\"M12 5l0 14\"></path> <path d=\"M5 12l14 0\"></path></svg> Transaktion hinzufügen</button></div></div></div></div><div class=\"row\"><!-- Portfolio Overview --><div class=\"col-md-8\"><div class=\"card\"><div class=\"card-header\"><h3 class=\"card-title\">Positionen</h3></div><div class=\"card-body\"><div class=\"table-responsive\"><table class=\"table table-vcenter\"><thead><tr><th>Wertpapier</th><th>Anzahl</th><th>Ø Einkaufspreis</th><th>Aktueller Wert</th><th>+/- Gesamt</th><th></th></tr></thead> <tbody>")
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 5, "</div></div><div class=\"col-auto ms-auto d-print-none\"><div class=\"btn-list\"><button type=\"button\" class=\"btn btn-primary\" data-bs-toggle=\"modal\" data-bs-target=\"#addTransactionModal\"><svg xmlns=\"http://www.w3.org/2000/svg\" class=\"icon\" width=\"24\" height=\"24\" viewBox=\"0 0 24 24\" stroke-width=\"2\" stroke=\"currentColor\" fill=\"none\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><path stroke=\"none\" d=\"M0 0h24v24H0z\" fill=\"none\"></path> <path d=\"M12 5l0 14\"></path> <path d=\"M5 12l14 0\"></path></svg> Transaktion hinzufügen</button></div></div></div></div><div class=\"row\"><!-- Portfolio Overview --><div class=\"col-md-8\"><div class=\"card\"><div class=\"card-header\"><h3 class=\"card-title\">Positionen</h3></div><div class=\"card-body\"><div class=\"table-responsive\"><table class=\"table table-vcenter\"><thead><tr><th>Wertpapier</th><th>Anzahl</th><th>Ø Einkaufspreis</th><th>Aktueller Wert</th><th>+/- Gesamt</th><th></th></tr></thead> <tbody>")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
if len(portfolio.Activities) > 0 {
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("<tr><td colspan=\"6\" class=\"text-center text-muted py-4\">Position calculation will be implemented here</td></tr>")
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 6, "<tr><td colspan=\"6\" class=\"text-center text-muted py-4\">Position calculation will be implemented here</td></tr>")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
} else {
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("<tr><td colspan=\"6\" class=\"text-center text-muted py-4\">Keine Positionen vorhanden. Fügen Sie Ihre erste Transaktion hinzu.</td></tr>")
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 7, "<tr><td colspan=\"6\" class=\"text-center text-muted py-4\">Keine Positionen vorhanden. Fügen Sie Ihre erste Transaktion hinzu.</td></tr>")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
}
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("</tbody></table></div></div></div><!-- Recent Activities --><div class=\"card mt-4\"><div class=\"card-header\"><h3 class=\"card-title\">Letzte Transaktionen</h3></div><div class=\"card-body\"><div class=\"table-responsive\"><table class=\"table table-sm\"><thead><tr><th>Datum</th><th>Typ</th><th>Wertpapier</th><th>Anzahl</th><th>Preis</th><th>Preis (")
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 8, "</tbody></table></div></div></div><!-- Recent Activities --><div class=\"card mt-4\"><div class=\"card-header\"><h3 class=\"card-title\">Letzte Transaktionen</h3></div><div class=\"card-body\"><div class=\"table-responsive\"><table class=\"table table-sm\"><thead><tr><th>Datum</th><th>Typ</th><th>Wertpapier</th><th>Anzahl</th><th>Preis</th><th>Preis (")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
var templ_7745c5c3_Var6 string
templ_7745c5c3_Var6, templ_7745c5c3_Err = templ.JoinStringErrs(portfolio.BaseCurrency)
if templ_7745c5c3_Err != nil {
return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/web/templates/portfolio-detail.templ`, Line: 91, Col: 45}
return templ.Error{Err: templ_7745c5c3_Err, FileName: `portfolio-detail.templ`, Line: 91, Col: 45}
}
_, 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(")</th><th>Gesamt</th><th>Gesamt (")
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 9, ")</th><th>Gesamt</th><th>Gesamt (")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
var templ_7745c5c3_Var7 string
templ_7745c5c3_Var7, templ_7745c5c3_Err = templ.JoinStringErrs(portfolio.BaseCurrency)
if templ_7745c5c3_Err != nil {
return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/web/templates/portfolio-detail.templ`, Line: 93, Col: 46}
return templ.Error{Err: templ_7745c5c3_Err, FileName: `portfolio-detail.templ`, Line: 93, Col: 46}
}
_, 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(")</th><th></th></tr></thead> <tbody>")
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 10, ")</th><th></th></tr></thead> <tbody>")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
if len(portfolio.Activities) > 0 {
for i, activity := range portfolio.Activities {
if i < 10 {
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("<tr><td>")
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 11, "<tr><td>")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
var templ_7745c5c3_Var8 string
templ_7745c5c3_Var8, templ_7745c5c3_Err = templ.JoinStringErrs(activity.Date.Format("02.01.2006"))
if templ_7745c5c3_Err != nil {
return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/web/templates/portfolio-detail.templ`, Line: 102, Col: 53}
return templ.Error{Err: templ_7745c5c3_Err, FileName: `portfolio-detail.templ`, Line: 102, Col: 53}
}
_, 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("</td><td>")
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 12, "</td><td>")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
if activity.Type == "BUY" {
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("<span class=\"badge bg-green\">Kauf</span>")
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 13, "<span class=\"badge bg-green\">Kauf</span>")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
} else if activity.Type == "SELL" {
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("<span class=\"badge bg-red\">Verkauf</span>")
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 14, "<span class=\"badge bg-red\">Verkauf</span>")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
} else if activity.Type == "DIVIDEND" {
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("<span class=\"badge bg-blue\">Dividende</span>")
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 15, "<span class=\"badge bg-blue\">Dividende</span>")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
} else {
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("<span class=\"badge bg-secondary\">")
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 16, "<span class=\"badge bg-secondary\">")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
var templ_7745c5c3_Var9 string
templ_7745c5c3_Var9, templ_7745c5c3_Err = templ.JoinStringErrs(string(activity.Type))
if templ_7745c5c3_Err != nil {
return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/web/templates/portfolio-detail.templ`, Line: 111, Col: 71}
return templ.Error{Err: templ_7745c5c3_Err, FileName: `portfolio-detail.templ`, Line: 111, Col: 71}
}
_, 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("</span>")
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 17, "</span>")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
}
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("</td><td><a href=\"")
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 18, "</td><td><a href=\"")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
var templ_7745c5c3_Var10 templ.SafeURL = templ.URL("/details?stock=" + activity.Stock)
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(string(templ_7745c5c3_Var10)))
var templ_7745c5c3_Var10 templ.SafeURL
templ_7745c5c3_Var10, templ_7745c5c3_Err = templ.JoinURLErrs(templ.URL("/details?stock=" + activity.Stock))
if templ_7745c5c3_Err != nil {
return templ.Error{Err: templ_7745c5c3_Err, FileName: `portfolio-detail.templ`, Line: 115, Col: 69}
}
_, 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("\" class=\"text-decoration-none\">")
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 19, "\" class=\"text-decoration-none\">")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
var templ_7745c5c3_Var11 string
templ_7745c5c3_Var11, templ_7745c5c3_Err = templ.JoinStringErrs(activity.Stock)
if templ_7745c5c3_Err != nil {
return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/web/templates/portfolio-detail.templ`, Line: 116, Col: 31}
return templ.Error{Err: templ_7745c5c3_Err, FileName: `portfolio-detail.templ`, Line: 116, Col: 31}
}
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var11))
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("</a></td><td>")
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 20, "</a></td><td>")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
var templ_7745c5c3_Var12 string
templ_7745c5c3_Var12, templ_7745c5c3_Err = templ.JoinStringErrs(fmt.Sprintf("%.3f", activity.Amount))
if templ_7745c5c3_Err != nil {
return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/web/templates/portfolio-detail.templ`, Line: 119, Col: 55}
return templ.Error{Err: templ_7745c5c3_Err, FileName: `portfolio-detail.templ`, Line: 119, Col: 55}
}
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var12))
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("</td><td>")
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 21, "</td><td>")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
var templ_7745c5c3_Var13 string
templ_7745c5c3_Var13, templ_7745c5c3_Err = templ.JoinStringErrs(fmt.Sprintf("%.2f %s", activity.Price, activity.Currency))
if templ_7745c5c3_Err != nil {
return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/web/templates/portfolio-detail.templ`, Line: 120, Col: 76}
return templ.Error{Err: templ_7745c5c3_Err, FileName: `portfolio-detail.templ`, Line: 120, Col: 76}
}
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var13))
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("</td><td>")
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 22, "</td><td>")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
@@ -245,233 +249,233 @@ func PortfolioDetailContent(portfolio model.Portfolio) templ.Component {
var templ_7745c5c3_Var14 string
templ_7745c5c3_Var14, templ_7745c5c3_Err = templ.JoinStringErrs(getConvertedPrice(activity, portfolio.BaseCurrency))
if templ_7745c5c3_Err != nil {
return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/web/templates/portfolio-detail.templ`, Line: 123, Col: 68}
return templ.Error{Err: templ_7745c5c3_Err, FileName: `portfolio-detail.templ`, Line: 123, Col: 68}
}
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var14))
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
} else {
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("<span class=\"text-muted\">-</span>")
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 23, "<span class=\"text-muted\">-</span>")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
}
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("</td><td>")
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 24, "</td><td>")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
var templ_7745c5c3_Var15 string
templ_7745c5c3_Var15, templ_7745c5c3_Err = templ.JoinStringErrs(fmt.Sprintf("%.2f %s", activity.Amount*activity.Price, activity.Currency))
if templ_7745c5c3_Err != nil {
return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/web/templates/portfolio-detail.templ`, Line: 128, Col: 94}
return templ.Error{Err: templ_7745c5c3_Err, FileName: `portfolio-detail.templ`, Line: 128, Col: 94}
}
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var15))
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("</td><td>")
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 25, "</td><td>")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
if activity.Currency != portfolio.BaseCurrency {
var templ_7745c5c3_Var16 string
templ_7745c5c3_Var16, templ_7745c5c3_Err = templ.JoinStringErrs(getConvertedTotal(activity, portfolio.BaseCurrency))
templ_7745c5c3_Var16, templ_7745c5c3_Err = templ.JoinStringErrs(getConvertedTotalWithFallbackInfo(activity, portfolio.BaseCurrency))
if templ_7745c5c3_Err != nil {
return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/web/templates/portfolio-detail.templ`, Line: 131, Col: 68}
return templ.Error{Err: templ_7745c5c3_Err, FileName: `portfolio-detail.templ`, Line: 131, Col: 84}
}
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var16))
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
} else {
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("<span class=\"text-muted\">-</span>")
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 26, "<span class=\"text-muted\">-</span>")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
}
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("</td><td><div class=\"btn-list flex-nowrap\"><button class=\"btn btn-sm btn-outline-primary\" data-bs-toggle=\"modal\" data-bs-target=\"#editTransactionModal\" data-activity-id=\"")
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 27, "</td><td><div class=\"btn-list flex-nowrap\"><button class=\"btn btn-sm btn-outline-primary\" data-bs-toggle=\"modal\" data-bs-target=\"#editTransactionModal\" data-activity-id=\"")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
var templ_7745c5c3_Var17 string
templ_7745c5c3_Var17, templ_7745c5c3_Err = templ.JoinStringErrs(fmt.Sprintf("%d", activity.ID))
if templ_7745c5c3_Err != nil {
return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/web/templates/portfolio-detail.templ`, Line: 142, Col: 65}
return templ.Error{Err: templ_7745c5c3_Err, FileName: `portfolio-detail.templ`, Line: 142, Col: 65}
}
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var17))
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("\" data-activity-type=\"")
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 28, "\" data-activity-type=\"")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
var templ_7745c5c3_Var18 string
templ_7745c5c3_Var18, templ_7745c5c3_Err = templ.JoinStringErrs(string(activity.Type))
if templ_7745c5c3_Err != nil {
return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/web/templates/portfolio-detail.templ`, Line: 143, Col: 58}
return templ.Error{Err: templ_7745c5c3_Err, FileName: `portfolio-detail.templ`, Line: 143, Col: 58}
}
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var18))
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("\" data-activity-stock=\"")
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 29, "\" data-activity-stock=\"")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
var templ_7745c5c3_Var19 string
templ_7745c5c3_Var19, templ_7745c5c3_Err = templ.JoinStringErrs(activity.Stock)
if templ_7745c5c3_Err != nil {
return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/web/templates/portfolio-detail.templ`, Line: 144, Col: 52}
return templ.Error{Err: templ_7745c5c3_Err, FileName: `portfolio-detail.templ`, Line: 144, Col: 52}
}
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var19))
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("\" data-activity-amount=\"")
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 30, "\" data-activity-amount=\"")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
var templ_7745c5c3_Var20 string
templ_7745c5c3_Var20, templ_7745c5c3_Err = templ.JoinStringErrs(fmt.Sprintf("%.3f", activity.Amount))
if templ_7745c5c3_Err != nil {
return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/web/templates/portfolio-detail.templ`, Line: 145, Col: 75}
return templ.Error{Err: templ_7745c5c3_Err, FileName: `portfolio-detail.templ`, Line: 145, Col: 75}
}
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var20))
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("\" data-activity-price=\"")
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 31, "\" data-activity-price=\"")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
var templ_7745c5c3_Var21 string
templ_7745c5c3_Var21, templ_7745c5c3_Err = templ.JoinStringErrs(fmt.Sprintf("%.2f", activity.Price))
if templ_7745c5c3_Err != nil {
return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/web/templates/portfolio-detail.templ`, Line: 146, Col: 73}
return templ.Error{Err: templ_7745c5c3_Err, FileName: `portfolio-detail.templ`, Line: 146, Col: 73}
}
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var21))
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("\" data-activity-date=\"")
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 32, "\" data-activity-date=\"")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
var templ_7745c5c3_Var22 string
templ_7745c5c3_Var22, templ_7745c5c3_Err = templ.JoinStringErrs(activity.Date.Format("2006-01-02"))
if templ_7745c5c3_Err != nil {
return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/web/templates/portfolio-detail.templ`, Line: 147, Col: 71}
return templ.Error{Err: templ_7745c5c3_Err, FileName: `portfolio-detail.templ`, Line: 147, Col: 71}
}
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var22))
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("\" data-activity-note=\"")
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 33, "\" data-activity-note=\"")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
var templ_7745c5c3_Var23 string
templ_7745c5c3_Var23, templ_7745c5c3_Err = templ.JoinStringErrs(activity.Note)
if templ_7745c5c3_Err != nil {
return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/web/templates/portfolio-detail.templ`, Line: 148, Col: 50}
return templ.Error{Err: templ_7745c5c3_Err, FileName: `portfolio-detail.templ`, Line: 148, Col: 50}
}
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var23))
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("\">Bearbeiten</button> <button class=\"btn btn-sm btn-outline-danger\" data-bs-toggle=\"modal\" data-bs-target=\"#deleteTransactionModal\" data-activity-id=\"")
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 34, "\">Bearbeiten</button> <button class=\"btn btn-sm btn-outline-danger\" data-bs-toggle=\"modal\" data-bs-target=\"#deleteTransactionModal\" data-activity-id=\"")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
var templ_7745c5c3_Var24 string
templ_7745c5c3_Var24, templ_7745c5c3_Err = templ.JoinStringErrs(fmt.Sprintf("%d", activity.ID))
if templ_7745c5c3_Err != nil {
return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/web/templates/portfolio-detail.templ`, Line: 156, Col: 65}
return templ.Error{Err: templ_7745c5c3_Err, FileName: `portfolio-detail.templ`, Line: 156, Col: 65}
}
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var24))
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("\" data-activity-stock=\"")
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 35, "\" data-activity-stock=\"")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
var templ_7745c5c3_Var25 string
templ_7745c5c3_Var25, templ_7745c5c3_Err = templ.JoinStringErrs(activity.Stock)
if templ_7745c5c3_Err != nil {
return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/web/templates/portfolio-detail.templ`, Line: 157, Col: 52}
return templ.Error{Err: templ_7745c5c3_Err, FileName: `portfolio-detail.templ`, Line: 157, Col: 52}
}
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var25))
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("\" data-activity-type=\"")
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 36, "\" data-activity-type=\"")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
var templ_7745c5c3_Var26 string
templ_7745c5c3_Var26, templ_7745c5c3_Err = templ.JoinStringErrs(string(activity.Type))
if templ_7745c5c3_Err != nil {
return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/web/templates/portfolio-detail.templ`, Line: 158, Col: 58}
return templ.Error{Err: templ_7745c5c3_Err, FileName: `portfolio-detail.templ`, Line: 158, Col: 58}
}
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var26))
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("\" data-activity-amount=\"")
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 37, "\" data-activity-amount=\"")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
var templ_7745c5c3_Var27 string
templ_7745c5c3_Var27, templ_7745c5c3_Err = templ.JoinStringErrs(fmt.Sprintf("%.3f", activity.Amount))
if templ_7745c5c3_Err != nil {
return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/web/templates/portfolio-detail.templ`, Line: 159, Col: 75}
return templ.Error{Err: templ_7745c5c3_Err, FileName: `portfolio-detail.templ`, Line: 159, Col: 75}
}
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var27))
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("\" data-activity-date=\"")
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 38, "\" data-activity-date=\"")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
var templ_7745c5c3_Var28 string
templ_7745c5c3_Var28, templ_7745c5c3_Err = templ.JoinStringErrs(activity.Date.Format("02.01.2006"))
if templ_7745c5c3_Err != nil {
return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/web/templates/portfolio-detail.templ`, Line: 160, Col: 71}
return templ.Error{Err: templ_7745c5c3_Err, FileName: `portfolio-detail.templ`, Line: 160, Col: 71}
}
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var28))
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("\">Löschen</button></div></td></tr>")
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 39, "\">Löschen</button></div></td></tr>")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
}
}
} else {
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("<tr><td colspan=\"9\" class=\"text-center text-muted py-3\">Keine Transaktionen vorhanden</td></tr>")
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 40, "<tr><td colspan=\"9\" class=\"text-center text-muted py-3\">Keine Transaktionen vorhanden</td></tr>")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
}
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("</tbody></table></div></div></div></div><!-- Portfolio Summary --><div class=\"col-md-4\"><!-- Currency Conversion Info --><div class=\"card mb-3\"><div class=\"card-body\"><div class=\"d-flex align-items-center\"><div class=\"me-3\"><svg xmlns=\"http://www.w3.org/2000/svg\" class=\"icon text-blue\" width=\"24\" height=\"24\" viewBox=\"0 0 24 24\" stroke-width=\"2\" stroke=\"currentColor\" fill=\"none\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><path stroke=\"none\" d=\"M0 0h24v24H0z\" fill=\"none\"></path> <circle cx=\"12\" cy=\"12\" r=\"9\"></circle> <path d=\"M12 8h.01\"></path> <path d=\"M11 12h1v4h1\"></path></svg></div><div class=\"flex-fill\"><div class=\"font-weight-medium\">Währungsumrechnung</div><div class=\"text-muted small\">Transaktionen in anderen Währungen werden automatisch in ")
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 41, "</tbody></table></div></div></div></div><!-- Portfolio Summary --><div class=\"col-md-4\"><!-- Currency Conversion Info --><div class=\"card mb-3\"><div class=\"card-body\"><div class=\"d-flex align-items-center\"><div class=\"me-3\"><svg xmlns=\"http://www.w3.org/2000/svg\" class=\"icon text-blue\" width=\"24\" height=\"24\" viewBox=\"0 0 24 24\" stroke-width=\"2\" stroke=\"currentColor\" fill=\"none\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><path stroke=\"none\" d=\"M0 0h24v24H0z\" fill=\"none\"></path> <circle cx=\"12\" cy=\"12\" r=\"9\"></circle> <path d=\"M12 8h.01\"></path> <path d=\"M11 12h1v4h1\"></path></svg></div><div class=\"flex-fill\"><div class=\"font-weight-medium\">Historische Währungsumrechnung</div><div class=\"text-muted small\">Transaktionen werden mit den historischen Wechselkursen vom Transaktionsdatum in ")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
var templ_7745c5c3_Var29 string
templ_7745c5c3_Var29, templ_7745c5c3_Err = templ.JoinStringErrs(portfolio.BaseCurrency)
if templ_7745c5c3_Err != nil {
return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/web/templates/portfolio-detail.templ`, Line: 199, Col: 91}
return templ.Error{Err: templ_7745c5c3_Err, FileName: `portfolio-detail.templ`, Line: 199, Col: 114}
}
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var29))
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(" umgerechnet. Wechselkurse werden stündlich aktualisiert.</div></div></div></div></div><div class=\"card\"><div class=\"card-header\"><h3 class=\"card-title\">Portfolio-Zusammenfassung</h3></div><div class=\"card-body\">")
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 42, " umgerechnet. Bei nicht verfügbaren historischen Kursen werden aktuelle Kurse verwendet (markiert mit *).</div></div></div></div></div><div class=\"card\"><div class=\"card-header\"><h3 class=\"card-title\">Portfolio-Zusammenfassung</h3></div><div class=\"card-body\">")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
@@ -479,76 +483,76 @@ func PortfolioDetailContent(portfolio model.Portfolio) templ.Component {
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("</div></div><div class=\"card mt-3\"><div class=\"card-header\"><h3 class=\"card-title\">Allokation</h3></div><div class=\"card-body\"><div id=\"allocationChart\"></div><p class=\"text-muted text-center\">Allokations-Chart wird hier implementiert</p></div></div></div></div></div><!-- Add Transaction Modal --><div class=\"modal modal-blur fade\" id=\"addTransactionModal\" tabindex=\"-1\" aria-labelledby=\"addTransactionModalLabel\" aria-hidden=\"true\"><div class=\"modal-dialog\"><div class=\"modal-content\"><div class=\"modal-header\"><h5 class=\"modal-title\" id=\"addTransactionModalLabel\">Transaktion hinzufügen</h5><button type=\"button\" class=\"btn-close\" data-bs-dismiss=\"modal\" aria-label=\"Schließen\"></button></div><form method=\"post\" action=\"/portfolio/transaction\"><input type=\"hidden\" name=\"portfolio_id\" value=\"")
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 43, "</div></div><div class=\"card mt-3\"><div class=\"card-header\"><h3 class=\"card-title\">Allokation</h3></div><div class=\"card-body\"><div id=\"allocationChart\"></div><p class=\"text-muted text-center\">Allokations-Chart wird hier implementiert</p></div></div></div></div></div><!-- Add Transaction Modal --><div class=\"modal modal-blur fade\" id=\"addTransactionModal\" tabindex=\"-1\" aria-labelledby=\"addTransactionModalLabel\" aria-hidden=\"true\"><div class=\"modal-dialog\"><div class=\"modal-content\"><div class=\"modal-header\"><h5 class=\"modal-title\" id=\"addTransactionModalLabel\">Transaktion hinzufügen</h5><button type=\"button\" class=\"btn-close\" data-bs-dismiss=\"modal\" aria-label=\"Schließen\"></button></div><form method=\"post\" action=\"/portfolio/transaction\"><input type=\"hidden\" name=\"portfolio_id\" value=\"")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
var templ_7745c5c3_Var30 string
templ_7745c5c3_Var30, templ_7745c5c3_Err = templ.JoinStringErrs(fmt.Sprintf("%d", portfolio.ID))
if templ_7745c5c3_Err != nil {
return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/web/templates/portfolio-detail.templ`, Line: 235, Col: 85}
return templ.Error{Err: templ_7745c5c3_Err, FileName: `portfolio-detail.templ`, Line: 235, Col: 85}
}
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var30))
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("\"><div class=\"modal-body\"><div class=\"mb-3\"><label for=\"transaction-type\" class=\"form-label\">Typ</label> <select class=\"form-select\" id=\"transaction-type\" name=\"type\" required><option value=\"\">Wählen Sie einen Typ</option> <option value=\"BUY\">Kauf</option> <option value=\"SELL\">Verkauf</option> <option value=\"DIVIDEND\">Dividende</option></select></div><div class=\"mb-3\"><label for=\"transaction-stock\" class=\"form-label\">Wertpapier</label> <input type=\"text\" class=\"form-control\" id=\"transaction-stock\" name=\"stock\" placeholder=\"z.B. AAPL\" required></div><div class=\"mb-3\"><label for=\"transaction-amount\" class=\"form-label\">Anzahl</label> <input type=\"number\" class=\"form-control\" id=\"transaction-amount\" name=\"amount\" step=\"0.001\" min=\"0\" required></div><div class=\"mb-3\"><label for=\"transaction-price\" class=\"form-label\">Preis</label><div class=\"input-group\"><input type=\"number\" class=\"form-control\" id=\"transaction-price\" name=\"price\" step=\"0.01\" min=\"0\" required> <span class=\"input-group-text\">")
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 44, "\"><div class=\"modal-body\"><div class=\"mb-3\"><label for=\"transaction-type\" class=\"form-label\">Typ</label> <select class=\"form-select\" id=\"transaction-type\" name=\"type\" required><option value=\"\">Wählen Sie einen Typ</option> <option value=\"BUY\">Kauf</option> <option value=\"SELL\">Verkauf</option> <option value=\"DIVIDEND\">Dividende</option></select></div><div class=\"mb-3\"><label for=\"transaction-stock\" class=\"form-label\">Wertpapier</label> <input type=\"text\" class=\"form-control\" id=\"transaction-stock\" name=\"stock\" placeholder=\"z.B. AAPL\" required></div><div class=\"mb-3\"><label for=\"transaction-amount\" class=\"form-label\">Anzahl</label> <input type=\"number\" class=\"form-control\" id=\"transaction-amount\" name=\"amount\" step=\"0.001\" min=\"0\" required></div><div class=\"mb-3\"><label for=\"transaction-price\" class=\"form-label\">Preis</label><div class=\"input-group\"><input type=\"number\" class=\"form-control\" id=\"transaction-price\" name=\"price\" step=\"0.01\" min=\"0\" required> <span class=\"input-group-text\">")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
var templ_7745c5c3_Var31 string
templ_7745c5c3_Var31, templ_7745c5c3_Err = templ.JoinStringErrs(portfolio.BaseCurrency)
if templ_7745c5c3_Err != nil {
return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/web/templates/portfolio-detail.templ`, Line: 258, Col: 63}
return templ.Error{Err: templ_7745c5c3_Err, FileName: `portfolio-detail.templ`, Line: 258, Col: 63}
}
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var31))
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("</span></div></div><div class=\"mb-3\"><label for=\"transaction-date\" class=\"form-label\">Datum</label> <input type=\"date\" class=\"form-control\" id=\"transaction-date\" name=\"date\" required></div><div class=\"mb-3\"><label for=\"transaction-note\" class=\"form-label\">Notiz (optional)</label> <textarea class=\"form-control\" id=\"transaction-note\" name=\"note\" rows=\"2\"></textarea></div></div><div class=\"modal-footer\"><button type=\"button\" class=\"btn btn-secondary\" data-bs-dismiss=\"modal\">Abbrechen</button> <button type=\"submit\" class=\"btn btn-primary\">Speichern</button></div></form></div></div></div><!-- Edit Transaction Modal --><div class=\"modal modal-blur fade\" id=\"editTransactionModal\" tabindex=\"-1\" aria-labelledby=\"editTransactionModalLabel\" aria-hidden=\"true\"><div class=\"modal-dialog\"><div class=\"modal-content\"><div class=\"modal-header\"><h5 class=\"modal-title\" id=\"editTransactionModalLabel\">Transaktion bearbeiten</h5><button type=\"button\" class=\"btn-close\" data-bs-dismiss=\"modal\" aria-label=\"Schließen\"></button></div><form method=\"post\" action=\"/portfolio/transaction/edit\"><input type=\"hidden\" name=\"activity_id\" id=\"edit-activity-id\"> <input type=\"hidden\" name=\"portfolio_id\" value=\"")
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 45, "</span></div></div><div class=\"mb-3\"><label for=\"transaction-date\" class=\"form-label\">Datum</label> <input type=\"date\" class=\"form-control\" id=\"transaction-date\" name=\"date\" required></div><div class=\"mb-3\"><label for=\"transaction-note\" class=\"form-label\">Notiz (optional)</label> <textarea class=\"form-control\" id=\"transaction-note\" name=\"note\" rows=\"2\"></textarea></div></div><div class=\"modal-footer\"><button type=\"button\" class=\"btn btn-secondary\" data-bs-dismiss=\"modal\">Abbrechen</button> <button type=\"submit\" class=\"btn btn-primary\">Speichern</button></div></form></div></div></div><!-- Edit Transaction Modal --><div class=\"modal modal-blur fade\" id=\"editTransactionModal\" tabindex=\"-1\" aria-labelledby=\"editTransactionModalLabel\" aria-hidden=\"true\"><div class=\"modal-dialog\"><div class=\"modal-content\"><div class=\"modal-header\"><h5 class=\"modal-title\" id=\"editTransactionModalLabel\">Transaktion bearbeiten</h5><button type=\"button\" class=\"btn-close\" data-bs-dismiss=\"modal\" aria-label=\"Schließen\"></button></div><form method=\"post\" action=\"/portfolio/transaction/edit\"><input type=\"hidden\" name=\"activity_id\" id=\"edit-activity-id\"> <input type=\"hidden\" name=\"portfolio_id\" value=\"")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
var templ_7745c5c3_Var32 string
templ_7745c5c3_Var32, templ_7745c5c3_Err = templ.JoinStringErrs(fmt.Sprintf("%d", portfolio.ID))
if templ_7745c5c3_Err != nil {
return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/web/templates/portfolio-detail.templ`, Line: 288, Col: 85}
return templ.Error{Err: templ_7745c5c3_Err, FileName: `portfolio-detail.templ`, Line: 288, Col: 85}
}
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var32))
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("\"><div class=\"modal-body\"><div class=\"mb-3\"><label for=\"edit-transaction-type\" class=\"form-label\">Typ</label> <select class=\"form-select\" id=\"edit-transaction-type\" name=\"type\" required><option value=\"\">Wählen Sie einen Typ</option> <option value=\"BUY\">Kauf</option> <option value=\"SELL\">Verkauf</option> <option value=\"DIVIDEND\">Dividende</option></select></div><div class=\"mb-3\"><label for=\"edit-transaction-stock\" class=\"form-label\">Wertpapier</label> <input type=\"text\" class=\"form-control\" id=\"edit-transaction-stock\" name=\"stock\" placeholder=\"z.B. AAPL\" required></div><div class=\"mb-3\"><label for=\"edit-transaction-amount\" class=\"form-label\">Anzahl</label> <input type=\"number\" class=\"form-control\" id=\"edit-transaction-amount\" name=\"amount\" step=\"0.001\" min=\"0\" required></div><div class=\"mb-3\"><label for=\"edit-transaction-price\" class=\"form-label\">Preis</label><div class=\"input-group\"><input type=\"number\" class=\"form-control\" id=\"edit-transaction-price\" name=\"price\" step=\"0.01\" min=\"0\" required> <span class=\"input-group-text\">")
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 46, "\"><div class=\"modal-body\"><div class=\"mb-3\"><label for=\"edit-transaction-type\" class=\"form-label\">Typ</label> <select class=\"form-select\" id=\"edit-transaction-type\" name=\"type\" required><option value=\"\">Wählen Sie einen Typ</option> <option value=\"BUY\">Kauf</option> <option value=\"SELL\">Verkauf</option> <option value=\"DIVIDEND\">Dividende</option></select></div><div class=\"mb-3\"><label for=\"edit-transaction-stock\" class=\"form-label\">Wertpapier</label> <input type=\"text\" class=\"form-control\" id=\"edit-transaction-stock\" name=\"stock\" placeholder=\"z.B. AAPL\" required></div><div class=\"mb-3\"><label for=\"edit-transaction-amount\" class=\"form-label\">Anzahl</label> <input type=\"number\" class=\"form-control\" id=\"edit-transaction-amount\" name=\"amount\" step=\"0.001\" min=\"0\" required></div><div class=\"mb-3\"><label for=\"edit-transaction-price\" class=\"form-label\">Preis</label><div class=\"input-group\"><input type=\"number\" class=\"form-control\" id=\"edit-transaction-price\" name=\"price\" step=\"0.01\" min=\"0\" required> <span class=\"input-group-text\">")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
var templ_7745c5c3_Var33 string
templ_7745c5c3_Var33, templ_7745c5c3_Err = templ.JoinStringErrs(portfolio.BaseCurrency)
if templ_7745c5c3_Err != nil {
return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/web/templates/portfolio-detail.templ`, Line: 311, Col: 63}
return templ.Error{Err: templ_7745c5c3_Err, FileName: `portfolio-detail.templ`, Line: 311, Col: 63}
}
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var33))
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("</span></div></div><div class=\"mb-3\"><label for=\"edit-transaction-date\" class=\"form-label\">Datum</label> <input type=\"date\" class=\"form-control\" id=\"edit-transaction-date\" name=\"date\" required></div><div class=\"mb-3\"><label for=\"edit-transaction-note\" class=\"form-label\">Notiz (optional)</label> <textarea class=\"form-control\" id=\"edit-transaction-note\" name=\"note\" rows=\"2\"></textarea></div></div><div class=\"modal-footer\"><button type=\"button\" class=\"btn btn-secondary\" data-bs-dismiss=\"modal\">Abbrechen</button> <button type=\"submit\" class=\"btn btn-primary\">Speichern</button></div></form></div></div></div><!-- Delete Transaction Modal --><div class=\"modal modal-blur fade\" id=\"deleteTransactionModal\" tabindex=\"-1\" aria-labelledby=\"deleteTransactionModalLabel\" aria-hidden=\"true\"><div class=\"modal-dialog modal-sm\"><div class=\"modal-content\"><div class=\"modal-header\"><h5 class=\"modal-title\" id=\"deleteTransactionModalLabel\">Transaktion löschen</h5><button type=\"button\" class=\"btn-close\" data-bs-dismiss=\"modal\" aria-label=\"Schließen\"></button></div><div class=\"modal-body\"><p>Möchten Sie diese Transaktion wirklich löschen?</p><div class=\"text-muted\" id=\"delete-transaction-details\"><small>Diese Aktion kann nicht rückgängig gemacht werden.</small></div></div><div class=\"modal-footer\"><button type=\"button\" class=\"btn btn-secondary\" data-bs-dismiss=\"modal\">Abbrechen</button><form method=\"post\" action=\"/portfolio/transaction/delete\" style=\"display: inline;\"><input type=\"hidden\" name=\"activity_id\" id=\"delete-activity-id\"> <input type=\"hidden\" name=\"portfolio_id\" value=\"")
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 47, "</span></div></div><div class=\"mb-3\"><label for=\"edit-transaction-date\" class=\"form-label\">Datum</label> <input type=\"date\" class=\"form-control\" id=\"edit-transaction-date\" name=\"date\" required></div><div class=\"mb-3\"><label for=\"edit-transaction-note\" class=\"form-label\">Notiz (optional)</label> <textarea class=\"form-control\" id=\"edit-transaction-note\" name=\"note\" rows=\"2\"></textarea></div></div><div class=\"modal-footer\"><button type=\"button\" class=\"btn btn-secondary\" data-bs-dismiss=\"modal\">Abbrechen</button> <button type=\"submit\" class=\"btn btn-primary\">Speichern</button></div></form></div></div></div><!-- Delete Transaction Modal --><div class=\"modal modal-blur fade\" id=\"deleteTransactionModal\" tabindex=\"-1\" aria-labelledby=\"deleteTransactionModalLabel\" aria-hidden=\"true\"><div class=\"modal-dialog modal-sm\"><div class=\"modal-content\"><div class=\"modal-header\"><h5 class=\"modal-title\" id=\"deleteTransactionModalLabel\">Transaktion löschen</h5><button type=\"button\" class=\"btn-close\" data-bs-dismiss=\"modal\" aria-label=\"Schließen\"></button></div><div class=\"modal-body\"><p>Möchten Sie diese Transaktion wirklich löschen?</p><div class=\"text-muted\" id=\"delete-transaction-details\"><small>Diese Aktion kann nicht rückgängig gemacht werden.</small></div></div><div class=\"modal-footer\"><button type=\"button\" class=\"btn btn-secondary\" data-bs-dismiss=\"modal\">Abbrechen</button><form method=\"post\" action=\"/portfolio/transaction/delete\" style=\"display: inline;\"><input type=\"hidden\" name=\"activity_id\" id=\"delete-activity-id\"> <input type=\"hidden\" name=\"portfolio_id\" value=\"")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
var templ_7745c5c3_Var34 string
templ_7745c5c3_Var34, templ_7745c5c3_Err = templ.JoinStringErrs(fmt.Sprintf("%d", portfolio.ID))
if templ_7745c5c3_Err != nil {
return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/web/templates/portfolio-detail.templ`, Line: 349, Col: 86}
return templ.Error{Err: templ_7745c5c3_Err, FileName: `portfolio-detail.templ`, Line: 349, Col: 86}
}
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var34))
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("\"> <button type=\"submit\" class=\"btn btn-danger\">Löschen</button></form></div></div></div></div><script>\n\t\t// Set today's date as default\n\t\tdocument.addEventListener('DOMContentLoaded', function() {\n\t\t\tconst today = new Date().toISOString().split('T')[0];\n\t\t\tdocument.getElementById('transaction-date').value = today;\n\n\t\t\t// Handle edit button clicks\n\t\t\tdocument.addEventListener('click', function(e) {\n\t\t\t\tif (e.target.closest('[data-bs-target=\"#editTransactionModal\"]')) {\n\t\t\t\t\tconst button = e.target.closest('[data-bs-target=\"#editTransactionModal\"]');\n\n\t\t\t\t\t// Populate edit modal with transaction data\n\t\t\t\t\tdocument.getElementById('edit-activity-id').value = button.dataset.activityId;\n\t\t\t\t\tdocument.getElementById('edit-transaction-type').value = button.dataset.activityType;\n\t\t\t\t\tdocument.getElementById('edit-transaction-stock').value = button.dataset.activityStock;\n\t\t\t\t\tdocument.getElementById('edit-transaction-amount').value = button.dataset.activityAmount;\n\t\t\t\t\tdocument.getElementById('edit-transaction-price').value = button.dataset.activityPrice;\n\t\t\t\t\tdocument.getElementById('edit-transaction-date').value = button.dataset.activityDate;\n\t\t\t\t\tdocument.getElementById('edit-transaction-note').value = button.dataset.activityNote;\n\t\t\t\t}\n\n\t\t\t\t// Handle delete button clicks\n\t\t\t\tif (e.target.closest('[data-bs-target=\"#deleteTransactionModal\"]')) {\n\t\t\t\t\tconst button = e.target.closest('[data-bs-target=\"#deleteTransactionModal\"]');\n\n\t\t\t\t\t// Populate delete modal with transaction data\n\t\t\t\t\tdocument.getElementById('delete-activity-id').value = button.dataset.activityId;\n\n\t\t\t\t\t// Show transaction details in delete modal\n\t\t\t\t\tconst details = document.getElementById('delete-transaction-details');\n\t\t\t\t\tdetails.innerHTML = `\n\t\t\t\t\t\t<small>\n\t\t\t\t\t\t\t<strong>${button.dataset.activityType}</strong> - ${button.dataset.activityStock}<br>\n\t\t\t\t\t\t\t${button.dataset.activityAmount} Stück am ${button.dataset.activityDate}\n\t\t\t\t\t\t</small>\n\t\t\t\t\t`;\n\t\t\t\t}\n\t\t\t});\n\t\t});\n\t</script>")
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 48, "\"> <button type=\"submit\" class=\"btn btn-danger\">Löschen</button></form></div></div></div></div><script>\n\t\t// Set today's date as default\n\t\tdocument.addEventListener('DOMContentLoaded', function() {\n\t\t\tconst today = new Date().toISOString().split('T')[0];\n\t\t\tdocument.getElementById('transaction-date').value = today;\n\n\t\t\t// Handle edit button clicks\n\t\t\tdocument.addEventListener('click', function(e) {\n\t\t\t\tif (e.target.closest('[data-bs-target=\"#editTransactionModal\"]')) {\n\t\t\t\t\tconst button = e.target.closest('[data-bs-target=\"#editTransactionModal\"]');\n\n\t\t\t\t\t// Populate edit modal with transaction data\n\t\t\t\t\tdocument.getElementById('edit-activity-id').value = button.dataset.activityId;\n\t\t\t\t\tdocument.getElementById('edit-transaction-type').value = button.dataset.activityType;\n\t\t\t\t\tdocument.getElementById('edit-transaction-stock').value = button.dataset.activityStock;\n\t\t\t\t\tdocument.getElementById('edit-transaction-amount').value = button.dataset.activityAmount;\n\t\t\t\t\tdocument.getElementById('edit-transaction-price').value = button.dataset.activityPrice;\n\t\t\t\t\tdocument.getElementById('edit-transaction-date').value = button.dataset.activityDate;\n\t\t\t\t\tdocument.getElementById('edit-transaction-note').value = button.dataset.activityNote;\n\t\t\t\t}\n\n\t\t\t\t// Handle delete button clicks\n\t\t\t\tif (e.target.closest('[data-bs-target=\"#deleteTransactionModal\"]')) {\n\t\t\t\t\tconst button = e.target.closest('[data-bs-target=\"#deleteTransactionModal\"]');\n\n\t\t\t\t\t// Populate delete modal with transaction data\n\t\t\t\t\tdocument.getElementById('delete-activity-id').value = button.dataset.activityId;\n\n\t\t\t\t\t// Show transaction details in delete modal\n\t\t\t\t\tconst details = document.getElementById('delete-transaction-details');\n\t\t\t\t\tdetails.innerHTML = `\n\t\t\t\t\t\t<small>\n\t\t\t\t\t\t\t<strong>${button.dataset.activityType}</strong> - ${button.dataset.activityStock}<br>\n\t\t\t\t\t\t\t${button.dataset.activityAmount} Stück am ${button.dataset.activityDate}\n\t\t\t\t\t\t</small>\n\t\t\t\t\t`;\n\t\t\t\t}\n\t\t\t});\n\t\t});\n\t</script>")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
return templ_7745c5c3_Err
return nil
})
}
@@ -574,50 +578,50 @@ func PortfolioSummary(activities []model.Activity, currency string) templ.Compon
templ_7745c5c3_Var35 = templ.NopComponent
}
ctx = templ.ClearChildren(ctx)
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("<div class=\"row\"><div class=\"col-12\"><div class=\"mb-3\"><div class=\"text-muted\">Anzahl Transaktionen</div><div class=\"h3 mb-0\">")
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 49, "<div class=\"row\"><div class=\"col-12\"><div class=\"mb-3\"><div class=\"text-muted\">Anzahl Transaktionen</div><div class=\"h3 mb-0\">")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
var templ_7745c5c3_Var36 string
templ_7745c5c3_Var36, templ_7745c5c3_Err = templ.JoinStringErrs(fmt.Sprintf("%d", len(activities)))
if templ_7745c5c3_Err != nil {
return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/web/templates/portfolio-detail.templ`, Line: 404, Col: 61}
return templ.Error{Err: templ_7745c5c3_Err, FileName: `portfolio-detail.templ`, Line: 404, Col: 61}
}
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var36))
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("</div></div><div class=\"mb-3\"><div class=\"text-muted\">Gesamtwert investiert</div><div class=\"h2 mb-0\">")
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 50, "</div></div><div class=\"mb-3\"><div class=\"text-muted\">Gesamtwert investiert</div><div class=\"h2 mb-0\">")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
var templ_7745c5c3_Var37 string
templ_7745c5c3_Var37, templ_7745c5c3_Err = templ.JoinStringErrs(formatTotalInvestedWithConversion(activities, currency))
if templ_7745c5c3_Err != nil {
return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/web/templates/portfolio-detail.templ`, Line: 409, Col: 62}
return templ.Error{Err: templ_7745c5c3_Err, FileName: `portfolio-detail.templ`, Line: 409, Col: 62}
}
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var37))
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("</div></div><div class=\"mb-3\"><div class=\"text-muted\">Letzter Kauf</div><div class=\"h4 mb-0 text-muted\">")
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 51, "</div><div class=\"text-muted small\">* = Aktueller Kurs verwendet (historischer Kurs nicht verfügbar)</div></div><div class=\"mb-3\"><div class=\"text-muted\">Letzter Kauf</div><div class=\"h4 mb-0 text-muted\">")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
var templ_7745c5c3_Var38 string
templ_7745c5c3_Var38, templ_7745c5c3_Err = templ.JoinStringErrs(getLastBuyDate(activities))
if templ_7745c5c3_Err != nil {
return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/web/templates/portfolio-detail.templ`, Line: 415, Col: 33}
return templ.Error{Err: templ_7745c5c3_Err, FileName: `portfolio-detail.templ`, Line: 418, Col: 33}
}
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var38))
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("</div></div></div></div>")
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 52, "</div></div></div></div>")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
return templ_7745c5c3_Err
return nil
})
}
@@ -646,7 +650,7 @@ func PortfolioDetail(authenticated bool, username string, portfolio model.Portfo
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
return templ_7745c5c3_Err
return nil
})
}