a tool for shared writing and social publishing
at main 3.2 kB view raw
1"use server"; 2import { cookies } from "next/headers"; 3import { v7 } from "uuid"; 4import { getIdentityData } from "./getIdentityData"; 5import { supabaseServerClient } from "supabase/serverClient"; 6 7export async function getPollData(entity_sets: string[]) { 8 let voter_token = (await cookies()).get("poll_voter_token")?.value; 9 10 const { data: polls, error } = await supabaseServerClient 11 .from("poll_votes_on_entity") 12 .select( 13 ` 14 poll_entity, 15 voter_token, 16 option_entity, 17 entities!poll_votes_on_entity_poll_entity_fkey!inner(set) 18 `, 19 ) 20 .in("entities.set", entity_sets); 21 22 if (error) throw error; 23 24 let pollVotes = polls 25 .reduce< 26 Array<{ 27 poll_entity: string; 28 votes: { option_entity: string; voter_token: string }[]; 29 }> 30 >((acc, p) => { 31 let x = acc.find((a) => a.poll_entity === p.poll_entity); 32 if (!x) 33 acc.push({ 34 poll_entity: p.poll_entity, 35 votes: [p], 36 }); 37 else x.votes.push(p); 38 return acc; 39 }, []) 40 .map((poll) => { 41 return { 42 poll_entity: poll.poll_entity, 43 unique_votes: poll.votes.reduce<string[]>((acc, v) => { 44 if (!acc.includes(v.voter_token)) acc.push(v.voter_token); 45 return acc; 46 }, []).length, 47 votesByOption: poll.votes.reduce<{ 48 [key: string]: number; 49 }>((acc, v) => { 50 if (!acc[v.option_entity]) acc[v.option_entity] = 0; 51 acc[v.option_entity] = acc[v.option_entity] + 1; 52 return acc; 53 }, {}), 54 }; 55 }); 56 57 return { 58 pollVotes, 59 polls: polls.map((p) => ({ 60 poll_votes_on_entity: { 61 ...p, 62 voter_token: voter_token === p.voter_token ? voter_token : undefined, 63 }, 64 })), 65 voter_token, 66 }; 67} 68 69export async function voteOnPoll( 70 poll_entity: string, 71 option_entities: string[], 72) { 73 let voter_token = (await cookies()).get("poll_voter_token")?.value; 74 if (!voter_token) { 75 let identity = await getIdentityData(); 76 if (identity) voter_token = identity.id; 77 else voter_token = v7(); 78 (await cookies()).set("poll_voter_token", voter_token, { 79 maxAge: 60 * 60 * 24 * 365, 80 secure: process.env.NODE_ENV === "production", 81 httpOnly: true, 82 sameSite: "lax", 83 }); 84 } 85 const { data: existingVotes, error: selectError } = await supabaseServerClient 86 .from("poll_votes_on_entity") 87 .select("*") 88 .eq("poll_entity", poll_entity); 89 90 if (selectError) throw selectError; 91 92 const existingVote = existingVotes?.find( 93 (v) => v.voter_token === voter_token, 94 ); 95 96 if (existingVote) { 97 const { error: deleteError } = await supabaseServerClient 98 .from("poll_votes_on_entity") 99 .delete() 100 .eq("voter_token", voter_token) 101 .eq("poll_entity", poll_entity); 102 103 if (deleteError) throw deleteError; 104 } 105 106 const { error: insertError } = await supabaseServerClient 107 .from("poll_votes_on_entity") 108 .insert( 109 option_entities.map((option_entity) => ({ 110 option_entity, 111 poll_entity, 112 voter_token, 113 })), 114 ); 115 116 if (insertError) throw insertError; 117 118 return; 119}