Add connection review page with optional message on connection requests

- New GET route and template for reviewing individual connection requests
- Optional personal message field when sending connection requests
- Message visible to recipient on review page and connection list
- Dashboard "Review" button links to per-connection review page
- QR scan flow shows message prompt before sending request
- Fix accepted connections query: include both sent and received
- Fix url_for('uploaded_file') -> url_for('static', 'uploads/')
- Fix request.json -> request.is_json to avoid 415 on form POST
- Remove card from DOM on approve/reject instead of page reload

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
2026-05-28 08:28:21 +00:00
parent 3c26f1310e
commit 009b7d896b
9 changed files with 579 additions and 64 deletions
+263
View File
@@ -2533,6 +2533,269 @@ select:focus {
margin-top: var(--space-6);
}
/* ----- Connection Review Page ----- */
.breadcrumb-nav {
margin-bottom: var(--space-4);
font-size: var(--font-size-sm);
color: var(--text-muted);
}
.breadcrumb-nav a {
color: var(--secondary-color);
text-decoration: none;
}
.breadcrumb-nav a:hover {
text-decoration: underline;
}
.breadcrumb-nav .separator {
margin: 0 var(--space-2);
}
.breadcrumb-nav .current {
color: var(--text-color);
}
.review-card {
background: var(--card-bg);
border: 1px solid var(--border-color);
border-radius: var(--radius-xl);
box-shadow: var(--shadow-md);
overflow: hidden;
}
.review-header {
display: flex;
align-items: center;
gap: var(--space-5);
padding: var(--space-8) var(--space-8) var(--space-4);
background: var(--bg-color);
border-bottom: 1px solid var(--border-color);
}
.review-photo {
width: 120px;
height: 120px;
border-radius: 50%;
object-fit: cover;
border: 4px solid var(--border-color);
}
.review-photo-placeholder {
width: 120px;
height: 120px;
border-radius: 50%;
background: var(--bg-color);
display: flex;
align-items: center;
justify-content: center;
font-size: var(--font-size-3xl);
font-weight: 700;
color: var(--text-muted);
border: 4px solid var(--border-color);
flex-shrink: 0;
}
.review-name-org h2 {
margin: 0 0 var(--space-1) 0;
font-size: var(--font-size-2xl);
}
.review-title {
color: var(--secondary-color);
margin: 0;
font-size: var(--font-size-lg);
}
.review-details {
padding: var(--space-6) var(--space-8);
}
.detail-row {
display: flex;
padding: var(--space-3) 0;
border-bottom: 1px solid var(--border-light, #f0f0f0);
}
.detail-row:last-child {
border-bottom: none;
}
.detail-label {
width: 140px;
flex-shrink: 0;
font-weight: 600;
color: var(--text-muted);
font-size: var(--font-size-sm);
text-transform: uppercase;
letter-spacing: 0.05em;
}
.detail-value {
flex: 1;
color: var(--text-color);
word-break: break-word;
}
.detail-intro {
align-items: flex-start;
}
.intro-text {
font-style: italic;
color: var(--text-muted);
padding-left: var(--space-3);
border-left: 3px solid var(--border-color);
}
.message-text {
font-style: italic;
color: var(--text-color);
padding: var(--space-3);
background: var(--bg-highlight, #f0f7ff);
border-radius: var(--radius-md);
border-left: 3px solid var(--primary-color);
}
.detail-message .detail-label {
color: var(--primary-color);
}
/* ----- Connect Form (attendees list) ----- */
.connect-form.hidden {
display: none;
}
.connect-message-input {
width: 100%;
padding: var(--space-2) var(--space-3);
border: 1px solid var(--border-color);
border-radius: var(--radius-md);
font-size: var(--font-size-sm);
resize: vertical;
min-height: 40px;
font-family: inherit;
margin-bottom: var(--space-2);
}
.connect-message-input:focus {
outline: none;
border-color: var(--primary-color);
box-shadow: 0 0 0 2px var(--primary-color-alpha, rgba(67, 97, 238, 0.15));
}
.connect-form-actions {
display: flex;
gap: var(--space-2);
}
.btn-ghost {
background: transparent;
color: var(--text-muted);
border: 1px solid transparent;
padding: var(--space-1) var(--space-3);
border-radius: var(--radius-md);
cursor: pointer;
font-size: var(--font-size-sm);
}
.btn-ghost:hover {
background: var(--bg-color);
color: var(--text-color);
}
/* ----- Request Message (list page) ----- */
.request-message {
font-style: italic;
color: var(--text-color);
margin: 0 0 var(--space-2) 0;
font-size: var(--font-size-sm);
padding: var(--space-2) var(--space-3);
background: var(--bg-highlight, #f0f7ff);
border-radius: var(--radius-md);
border-left: 3px solid var(--primary-color);
}
/* ----- Scan Result Actions ----- */
.result-actions {
margin-top: var(--space-4);
}
.message-input {
width: 100%;
padding: var(--space-3);
border: 1px solid var(--border-color);
border-radius: var(--radius-md);
font-size: var(--font-size-base);
resize: vertical;
min-height: 48px;
font-family: inherit;
margin-bottom: var(--space-3);
box-sizing: border-box;
}
.message-input:focus {
outline: none;
border-color: var(--primary-color);
box-shadow: 0 0 0 2px var(--primary-color-alpha, rgba(67, 97, 238, 0.15));
}
.result-buttons {
display: flex;
gap: var(--space-3);
justify-content: center;
}
.review-actions {
display: flex;
gap: var(--space-4);
padding: var(--space-6) var(--space-8);
background: var(--bg-color);
border-top: 1px solid var(--border-color);
justify-content: center;
}
.review-actions .btn-lg {
padding: var(--space-3) var(--space-8);
font-size: var(--font-size-lg);
min-width: 160px;
}
.review-form {
display: inline;
}
@media (max-width: 768px) {
.review-header {
flex-direction: column;
text-align: center;
padding: var(--space-6) var(--space-4) var(--space-4);
}
.review-details {
padding: var(--space-4);
}
.detail-row {
flex-direction: column;
gap: var(--space-1);
}
.detail-label {
width: 100%;
}
.review-actions {
flex-direction: column;
padding: var(--space-4);
}
.review-actions .btn-lg {
width: 100%;
}
}
/* ----- Attendee Dashboard ----- */
.attendee-dashboard {
padding: var(--space-6) 0;