Skip to content

Commit 1c98e29

Browse files
committed
feat: Add confirmation for final result
1 parent 4478cc7 commit 1c98e29

File tree

5 files changed

+69
-52
lines changed

5 files changed

+69
-52
lines changed
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
ALTER TABLE participants ADD COLUMN confirmed BOOLEAN DEFAULT FALSE;

src/lib/database.ts

Lines changed: 10 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,7 @@ export class DatabaseService {
6262
async getParticipants(sessionId: number): Promise<Participant[]> {
6363
const { results } = await this.db
6464
.prepare(
65-
'SELECT id, name, description, role_weight as roleWeight, ppp_weight as pppWeight FROM participants WHERE session_id = ?'
65+
'SELECT id, name, description, role_weight as roleWeight, ppp_weight as pppWeight, confirmed FROM participants WHERE session_id = ?'
6666
)
6767
.bind(sessionId)
6868
.all<Participant>();
@@ -101,14 +101,17 @@ export class DatabaseService {
101101
return count > 0;
102102
}
103103

104-
async setParticipantDescription(
105-
participantId: number,
106-
description: string
107-
): Promise<boolean> {
104+
async updateParticipant(participant: Participant): Promise<boolean> {
108105
try {
109106
const { success } = await this.db
110-
.prepare('UPDATE participants SET description = ? WHERE id = ?')
111-
.bind(description, participantId)
107+
.prepare(
108+
`
109+
UPDATE participants
110+
SET description = ?, confirmed = ?
111+
WHERE id = ?
112+
`
113+
)
114+
.bind(participant.description, participant.confirmed, participant.id)
112115
.run();
113116
return success;
114117
} catch (error) {

src/lib/types.ts

Lines changed: 1 addition & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ export interface Participant {
1212
description: string;
1313
roleWeight: number;
1414
pppWeight: number;
15+
confirmed: boolean;
1516
}
1617

1718
export interface CreateSessionRequest {
@@ -33,18 +34,3 @@ export interface SubmitVoteRequest {
3334
reason: string;
3435
}>;
3536
}
36-
37-
export interface PatchDescriptionRequest {
38-
participantId: number;
39-
description: string;
40-
}
41-
42-
export interface SessionResponse {
43-
topic: string;
44-
description: string;
45-
stake: number;
46-
participants: Array<{
47-
name: string;
48-
share: number;
49-
}>;
50-
}

src/routes/+page.svelte

Lines changed: 25 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
topic: string;
2222
description: string;
2323
stake: number;
24+
confirmed: boolean;
2425
participants: {
2526
id: number;
2627
name: string;
@@ -39,6 +40,7 @@
3940
let currentParticipant: {
4041
id: number;
4142
description?: string;
43+
confirmed: boolean;
4244
} | null = null;
4345
4446
let stakeDistributed = false;
@@ -69,7 +71,11 @@
6971
function selectParticipant(participant) {
7072
currentParticipant = participant;
7173
72-
if (!adminToken && allDescriptionsSubmitted) {
74+
if (
75+
participant.reasons?.length == 0 &&
76+
!adminToken &&
77+
allDescriptionsSubmitted
78+
) {
7379
currentSession.participants = currentSession.participants.filter(
7480
(p) => p.id !== currentParticipant.id
7581
);
@@ -82,12 +88,7 @@
8288
}
8389
}
8490
85-
function submitCurrentParticipantDescription() {
86-
if (!(adminToken || currentParticipant.description)) {
87-
showMessage('Description cannot be empty', 'error');
88-
return;
89-
}
90-
91+
function updateCurrentParticipant() {
9192
const headers = {
9293
'Content-Type': 'application/json'
9394
};
@@ -99,15 +100,15 @@
99100
method: 'PATCH',
100101
headers,
101102
body: JSON.stringify({
102-
participantId: currentParticipant.id,
103+
...currentParticipant,
103104
description: currentParticipant.description
104105
? currentParticipant.description
105106
: null
106107
})
107108
})
108109
.then(async (response) => {
109110
if (response.ok) {
110-
showMessage('Description submitted successfully!', 'success');
111+
showMessage('Updated participant successfully!', 'success');
111112
currentParticipant = null;
112113
await viewSession();
113114
} else {
@@ -389,7 +390,10 @@
389390
<strong>Stake:</strong>
390391
{currentSession.stake - totalAllocatedShares}
391392
</p>
392-
393+
<p>
394+
<strong>Status:</strong>
395+
{currentSession.confirmed ? 'Ended' : 'Ongoing'}
396+
</p>
393397
<h3>Participants</h3>
394398
{#each currentSession.participants as participant}
395399
<div class="section">
@@ -405,7 +409,7 @@
405409
</p>
406410
{/if}
407411

408-
{#if adminToken || participant.share}
412+
{#if adminToken || participant.reasons}
409413
<p><strong>Share:</strong> {participant.share || 0}</p>
410414
{#if participant.reasons.length > 0}
411415
<strong>Reasons:</strong>
@@ -415,7 +419,14 @@
415419
{/each}
416420
</ul>
417421
{/if}
418-
{:else if allDescriptionsSubmitted}
422+
{#if currentParticipant}
423+
<button
424+
on:click={() =>
425+
(currentParticipant.confirmed = true) &&
426+
updateCurrentParticipant()}>Confirm share</button
427+
>
428+
{/if}
429+
{:else if allDescriptionsSubmitted && currentParticipant}
419430
<input
420431
bind:value={participant.share}
421432
on:input={() => {
@@ -431,7 +442,7 @@
431442
<textarea bind:value={participant.reason} placeholder="Reason"
432443
></textarea>
433444
{/if}
434-
{#if (!currentParticipant && adminToken) || !(currentParticipant || participant.description)}
445+
{#if !currentSession.confirmed && !currentParticipant && ((participant.share && !currentSession.confirmed) || !participant.description || adminToken || allDescriptionsSubmitted)}
435446
<button on:click={() => selectParticipant(participant)}>
436447
This is me
437448
</button>
@@ -442,8 +453,7 @@
442453
placeholder="Description"
443454
class="input"
444455
></textarea>
445-
<button on:click={() => submitCurrentParticipantDescription()}
446-
>Submit</button
456+
<button on:click={() => updateCurrentParticipant()}>Submit</button
447457
>
448458
{/if}
449459
</div>

src/routes/api/[sessionKey]/+server.ts

Lines changed: 32 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ import { json } from '@sveltejs/kit';
22
import type { RequestHandler } from './$types';
33
import { DatabaseService } from '$lib/database';
44
import { badRequestError, notFoundError, unauthorizedError } from '$lib/utils';
5-
import type { PatchDescriptionRequest, SubmitVoteRequest } from '$lib/types';
5+
import type { Participant, SubmitVoteRequest } from '$lib/types';
66

77
export const GET: RequestHandler = async ({ params, request, platform }) => {
88
try {
@@ -99,10 +99,13 @@ export const GET: RequestHandler = async ({ params, request, platform }) => {
9999
reasons: p.reasons
100100
}));
101101

102+
const allConfirmed = participants.every((p) => p.confirmed);
103+
102104
return json({
103105
topic: session.topic,
104106
description: session.description,
105107
stake: session.stake,
108+
confirmed: allConfirmed,
106109
participants: weightedParticipants
107110
});
108111
} catch (err) {
@@ -210,42 +213,56 @@ export const PATCH: RequestHandler = async ({ params, request, platform }) => {
210213
badRequestError('Session key is required');
211214
}
212215

213-
const body: PatchDescriptionRequest = await request.json();
214-
if (!body.participantId || !(token || body.description)) {
215-
badRequestError('Participant ID and description are required');
216+
const updateParticipant = (await request.json()) as Partial<Participant> & {
217+
id: number;
218+
};
219+
if (!updateParticipant.id) {
220+
badRequestError('Participant ID required');
216221
}
222+
217223
const db = new DatabaseService(platform.env.DB);
218224
const session = await db.getSession(sessionKey);
219225
if (!session) {
220226
notFoundError();
221227
}
222228

223229
const participants = await db.getParticipants(session.id);
224-
const participant = participants.find((p) => p.id === body.participantId);
225-
if (!participant) {
230+
const existing = participants.find((p) => p.id === updateParticipant.id);
231+
if (!existing) {
226232
badRequestError('Participant does not exist in this session');
227233
}
228234

229-
if (!token && participant.description) {
230-
badRequestError('Description has already been set and cannot be changed');
235+
const updatedParticipant: Participant = { ...existing };
236+
237+
if (updateParticipant.description !== undefined) {
238+
if (!token && existing.description != existing.description) {
239+
unauthorizedError();
240+
}
241+
242+
updatedParticipant.description = updateParticipant.description;
231243
}
232244

233-
const success = await db.setParticipantDescription(
234-
body.participantId,
235-
body.description
236-
);
245+
if (updateParticipant.confirmed !== undefined) {
246+
if (!token && updateParticipant.confirmed == false) {
247+
unauthorizedError();
248+
}
249+
250+
updatedParticipant.confirmed = updateParticipant.confirmed;
251+
}
252+
253+
const success = await db.updateParticipant(updatedParticipant);
237254
if (!success) {
238-
badRequestError('Failed to update participant description');
255+
badRequestError('Failed to update participant');
239256
}
257+
240258
return json({ success: true });
241259
} catch (err) {
242260
console.error('Error updating participant description:', err);
243261
if (err instanceof Response) {
244262
throw err;
245263
}
246-
247264
badRequestError(
248-
'Failed to update participant description: ' + err.body.message
265+
'Failed to update participant description: ' + (err as any).body?.message
249266
);
250267
}
251268
};

0 commit comments

Comments
 (0)