Wire up tips UI: CSS, settings toggle, dashboard display - Tip button CSS (tip-section, tip-form, tip-toggle, tip-submit) - Settings toggle for tips_enabled and notify_tip in notification preferences - Dashboard payments tab shows tips received with total, count, and message - TipReceived view type for template rendering
- Co-Authored-By
Author: Max J. <87768334+MaxJMath@users.noreply.github.com> - 2026-04-23 03:22 UTC
Commit:
0a038d802aa26aaf9eae82c829cb6a01e30d20f2Parent:
6 files changed,
+161 insertions,
-0 deletions
OldNewLine
@@ -1172,6 +1172,14 @@
1172
1172
}1173
1173
1174
1174
.centered-page .tagline {1175
margin-bottom: 0.25rem;1176
}1177
1178
.subtagline {1179
font-family: var(--font-mono);1180
color: var(--text-muted);1181
text-align: center;1182
font-size: 0.9rem;1175
1183
margin-bottom: 1rem;1176
1184
}1177
1185
@@ -3966,3 +3974,86 @@
3966
3974
opacity: 0.8;3967
3975
border-top: 1px solid var(--border-color, #ccc);3968
3976
}3977
3978
/* ── Tips ── */3979
3980
.tip-section {3981
margin-top: 1rem;3982
text-align: center;3983
}3984
3985
.tip-toggle {3986
font-family: var(--font-mono);3987
font-size: 0.85rem;3988
padding: 0.5rem 1.5rem;3989
background: none;3990
border: 1px solid var(--text);3991
color: var(--text);3992
cursor: pointer;3993
text-decoration: none;3994
display: inline-block;3995
}3996
3997
.tip-toggle:hover {3998
background: var(--text);3999
color: var(--background);4000
}4001
4002
.tip-form {4003
margin-top: 1rem;4004
display: flex;4005
flex-direction: column;4006
gap: 0.75rem;4007
max-width: 300px;4008
margin-left: auto;4009
margin-right: auto;4010
text-align: left;4011
}4012
4013
.tip-form.hidden {4014
display: none;4015
}4016
4017
.tip-amount-row {4018
display: flex;4019
align-items: center;4020
gap: 0.25rem;4021
}4022
4023
.tip-amount-row .pricing-currency {4024
font-size: 1.2rem;4025
opacity: 0.7;4026
}4027
4028
.tip-amount-input {4029
width: 80px;4030
font-size: 1.2rem;4031
padding: 0.4rem 0.5rem;4032
border: 1px solid var(--border);4033
background: var(--light-background);4034
font-family: var(--font-mono);4035
}4036
4037
.tip-message-input {4038
width: 100%;4039
font-size: 0.85rem;4040
padding: 0.5rem;4041
border: 1px solid var(--border);4042
background: var(--light-background);4043
font-family: var(--font-body);4044
resize: vertical;4045
}4046
4047
.tip-submit {4048
font-family: var(--font-mono);4049
font-size: 0.85rem;4050
padding: 0.5rem 1rem;4051
background: var(--text);4052
color: var(--background);4053
border: none;4054
cursor: pointer;4055
}4056
4057
.tip-submit:hover {4058
opacity: 0.85;4059
}OldNewLine
@@ -189,6 +189,9 @@
189
189
pub user: User,190
190
pub payout_summary: Option<PayoutSummary>,191
191
pub transactions: Vec<Transaction>,192
pub tips_received: Vec<TipReceived>,193
pub tips_total: String,194
pub tips_count: i64,192
195
}193
196
194
197
#[derive(Template)]OldNewLine
@@ -363,6 +363,15 @@
363
363
pub details: String,364
364
}365
365
366
/// Tip received for payments tab367
#[derive(Clone)]368
pub struct TipReceived {369
pub date: String,370
pub tipper_name: String,371
pub amount: String,372
pub message: Option<String>,373
}374
366
375
/// Project card for dashboard367
376
#[derive(Clone)]368
377
pub struct ProjectCard {OldNewLine
@@ -315,6 +315,16 @@
315
315
{% if user.notify_issues %}checked{% endif %}>316
316
<label for="notify-issues">Email me about new issues and comments on my repos</label>317
317
</div>318
<div class="checkbox-group" style="margin-top: 1.5rem; padding-top: 1rem; border-top: 1px solid var(--border);">319
<input type="checkbox" id="tips-enabled" name="tips_enabled" value="on"320
{% if user.tips_enabled %}checked{% endif %}>321
<label for="tips-enabled">Accept tips on my profile and project pages</label>322
</div>323
<div class="checkbox-group">324
<input type="checkbox" id="notify-tip" name="notify_tip" value="on"325
{% if user.notify_tip %}checked{% endif %}>326
<label for="notify-tip">Email me when I receive a tip</label>327
</div>318
328
{% endif %}319
329
<div id="preferences-result"></div>320
330
<button type="submit" class="primary" style="margin-top: 1rem;">Save Preferences</button>OldNewLine
@@ -202,6 +202,36 @@
202
202
</div>203
203
{% endif %}204
204
205
{% if tips_count > 0 %}206
<details class="form-section" open>207
<summary><h2>Tips Received ({{ tips_count }})</h2></summary>208
<div style="background: var(--surface-muted); padding: 1.25rem; margin-bottom: 1.5rem;">209
<div style="font-size: 1.25rem; font-weight: bold; margin-bottom: 0.5rem;">{{ tips_total }} total</div>210
<div style="font-size: 0.85rem; opacity: 0.7;">{{ tips_count }} tips received</div>211
</div>212
<table class="data-table">213
<thead>214
<tr>215
<th>Date</th>216
<th>From</th>217
<th>Amount</th>218
<th>Message</th>219
</tr>220
</thead>221
<tbody>222
{% for tip in tips_received %}223
<tr>224
<td>{{ tip.date }}</td>225
<td>{{ tip.tipper_name }}</td>226
<td>{{ tip.amount }}</td>227
<td style="max-width: 300px; overflow: hidden; text-overflow: ellipsis;">{% if let Some(msg) = tip.message %}{{ msg }}{% else %}<span style="opacity: 0.4;">-</span>{% endif %}</td>228
</tr>229
{% endfor %}230
</tbody>231
</table>232
</details>233
{% endif %}234
205
235
<div class="filter-controls">206
236
<div class="filter-group">207
237
<select name="type"OldNewLine
@@ -150,10 +150,28 @@
150
150
.await?;151
151
let transactions = super::super::collect_transactions(incoming_txs, outgoing_txs);152
152
153
// Tips154
let db_tips = db::tips::get_tips_received(&state.db, session_user.id, 20, 0).await?;155
let tips_total_cents = db::tips::total_tips_received(&state.db, session_user.id).await?;156
let tips_count = db::tips::count_tips_received(&state.db, session_user.id).await?;157
let tips_received: Vec<TipReceived> = db_tips158
.iter()159
.map(|t| TipReceived {160
date: t.created_at.format("%Y-%m-%d").to_string(),161
tipper_name: t.tipper_display_name.clone()162
.unwrap_or_else(|| t.tipper_username.clone()),163
amount: helpers::format_price(t.amount_cents),164
message: t.message.clone(),165
})166
.collect();167
153
168
Ok(UserPaymentsTabTemplate {154
169
user,155
170
payout_summary,156
171
transactions,172
tips_received,173
tips_total: helpers::format_revenue(tips_total_cents),174
tips_count,157
175
})158
176
}159
177