@richpods/coloeus 0.1.2 → 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
|
@@ -1 +1 @@
|
|
|
1
|
-
.coloeus-poll{font-family:-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Oxygen,Ubuntu,sans-serif;max-width:600px;margin:0 auto;padding:1.5rem;background:#fff;border-radius:8px;box-shadow:0 2px 8px #0000001a}.coloeus-poll__title{font-size:1.25rem;font-weight:600;margin:0 0 .5rem;color:#1a1a1a}.coloeus-poll__form{margin:0}.coloeus-poll__fieldset{border:none;margin:0;padding:0}.coloeus-poll__instructions{font-size:.875rem;color:#4b5563;margin:0 0 1rem}.coloeus-poll__instructions-note{display:block;margin-top:.25rem;font-size:.8125rem;color:#6b7280}.coloeus-poll__options{list-style:none;padding:0;margin:0}.coloeus-poll__option{position:relative;margin-bottom:.75rem;border-radius:6px;
|
|
1
|
+
.coloeus-poll{font-family:-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Oxygen,Ubuntu,sans-serif;max-width:600px;margin:0 auto;padding:1.5rem;background:#fff;border-radius:8px;box-shadow:0 2px 8px #0000001a}.coloeus-poll__title{font-size:1.25rem;font-weight:600;margin:0 0 .5rem;color:#1a1a1a}.coloeus-poll__form{margin:0}.coloeus-poll__fieldset{border:none;margin:0;padding:0}.coloeus-poll__instructions{font-size:.875rem;color:#4b5563;margin:0 0 1rem}.coloeus-poll__instructions-note{display:block;margin-top:.25rem;font-size:.8125rem;color:#6b7280}.coloeus-poll__options{list-style:none;padding:0;margin:0}.coloeus-poll__option{position:relative;margin-bottom:.75rem;border-radius:6px;padding:2px;transition:transform .15s ease}.coloeus-poll__option:hover:not(.coloeus-poll__option--disabled){transform:translate(4px)}.coloeus-poll__option--selected{outline:none}.coloeus-poll__option--voted .coloeus-poll__option-content{background-color:#f0f9ff}.coloeus-poll__option--disabled{cursor:default}.coloeus-poll__option-label{display:block;position:relative}.coloeus-poll__option-content{width:100%;display:flex;align-items:center;justify-content:space-between;gap:.75rem;padding:.875rem 1rem;background:#f5f5f5;border:1px solid #e5e5e5;border-radius:6px;font-size:1rem;text-align:left;transition:background-color .15s ease,border-color .15s ease,box-shadow .15s ease;position:relative;z-index:1;cursor:pointer;overflow:hidden}.coloeus-poll__option:not(.coloeus-poll__option--disabled) .coloeus-poll__option-content:hover{background:#ebebeb}.coloeus-poll__option--disabled .coloeus-poll__option-content{cursor:default;opacity:.9}.coloeus-poll__option--selected .coloeus-poll__option-content{border-color:#3b82f6;box-shadow:0 0 0 2px #3b82f640}.coloeus-poll__option-input{position:absolute;opacity:0;width:100%;height:100%;top:0;left:0;margin:0;cursor:pointer;z-index:2}.coloeus-poll__option-input:disabled{cursor:default}.coloeus-poll__option-input:focus-visible+.coloeus-poll__option-content{outline:2px solid #2563eb;outline-offset:2px;box-shadow:0 0 0 4px #2563eb40}.coloeus-poll__option-progress{position:absolute;top:0;left:0;height:100%;background:#dbeafe;border-radius:6px;transition:width .3s ease;z-index:0}.coloeus-poll__option-text{flex:1;color:#1a1a1a;position:relative;z-index:1}.coloeus-poll__option-stats{display:flex;align-items:center;gap:.5rem;font-size:.875rem;color:#666;position:relative;z-index:1}.coloeus-poll__option-percentage{font-weight:600;color:#3b82f6}.coloeus-poll__sr{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0,0,0,0);white-space:nowrap;border:0}.coloeus-poll__footer{margin-top:1rem;display:flex;align-items:center;justify-content:space-between;flex-wrap:wrap;gap:.5rem}.coloeus-poll__actions{display:flex;gap:.5rem}.coloeus-poll__vote-btn{padding:.75rem 1.5rem;background:#3b82f6;color:#fff;border:none;border-radius:6px;font-size:1rem;font-weight:500;cursor:pointer;transition:background-color .15s ease}.coloeus-poll__vote-btn:hover:not(:disabled){background:#2563eb}.coloeus-poll__vote-btn:disabled{background:#94a3b8;cursor:not-allowed}.coloeus-poll__results-btn{padding:.75rem 1.5rem;background:transparent;color:#6b7280;border:1px solid #d1d5db;border-radius:6px;font-size:1rem;cursor:pointer;transition:background-color .15s ease,border-color .15s ease}.coloeus-poll__results-btn:hover{background:#f3f4f6;border-color:#9ca3af}.coloeus-poll__total{font-size:.875rem;color:#666}.coloeus-poll__status-group{display:flex;align-items:center;gap:.5rem}.coloeus-poll__error{margin-top:.75rem;padding:.75rem;background:#fef2f2;border:1px solid #fecaca;border-radius:6px;color:#dc2626;font-size:.875rem}.coloeus-poll__loading{text-align:center;padding:2rem;color:#666}.coloeus-poll__status{display:inline-block;padding:.25rem .5rem;border-radius:4px;font-size:.75rem;font-weight:500}.coloeus-poll__status--active{background:#dcfce7;color:#166534}.coloeus-poll__status--open{background:#e0f2fe;color:#075985}.coloeus-poll__status--inactive{background:#fef3c7;color:#92400e}.coloeus-editor{font-family:-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Oxygen,Ubuntu,sans-serif;max-width:600px;margin:0 auto;padding:1.5rem;background:#fff;border-radius:8px;box-shadow:0 2px 8px #0000001a}.coloeus-editor__title{font-size:1.25rem;font-weight:600;margin:0 0 1.5rem;color:#1a1a1a}.coloeus-editor__field{margin-bottom:1.25rem}.coloeus-editor__label{display:block;font-size:.875rem;font-weight:500;color:#374151;margin-bottom:.5rem}.coloeus-editor__input,.coloeus-editor__textarea{width:100%;padding:.75rem;border:1px solid #d1d5db;border-radius:6px;font-size:1rem;transition:border-color .15s ease;box-sizing:border-box}.coloeus-editor__input:focus,.coloeus-editor__textarea:focus{outline:none;border-color:#3b82f6;box-shadow:0 0 0 3px #3b82f61a}.coloeus-editor__options{list-style:none;padding:0;margin:0}.coloeus-editor__option{display:flex;gap:.5rem;margin-bottom:.5rem}.coloeus-editor__option-input{flex:1;padding:.625rem .75rem;border:1px solid #d1d5db;border-radius:6px;font-size:.9375rem}.coloeus-editor__option-input:focus{outline:none;border-color:#3b82f6}.coloeus-editor__remove-btn{padding:.625rem .875rem;background:#fee2e2;color:#dc2626;border:none;border-radius:6px;cursor:pointer;font-size:.875rem;transition:background-color .15s ease}.coloeus-editor__remove-btn:hover{background:#fecaca}.coloeus-editor__add-btn{margin-top:.5rem;padding:.625rem 1rem;background:#f3f4f6;color:#374151;border:1px dashed #d1d5db;border-radius:6px;cursor:pointer;font-size:.875rem;width:100%;transition:background-color .15s ease}.coloeus-editor__add-btn:hover{background:#e5e7eb}.coloeus-editor__actions{margin-top:1.5rem;display:flex;gap:.75rem}.coloeus-editor__submit-btn{flex:1;padding:.75rem 1.5rem;background:#3b82f6;color:#fff;border:none;border-radius:6px;font-size:1rem;font-weight:500;cursor:pointer;transition:background-color .15s ease}.coloeus-editor__submit-btn:hover:not(:disabled){background:#2563eb}.coloeus-editor__submit-btn:disabled{background:#94a3b8;cursor:not-allowed}.coloeus-editor__cancel-btn{padding:.75rem 1.5rem;background:#f3f4f6;color:#374151;border:1px solid #d1d5db;border-radius:6px;font-size:1rem;cursor:pointer;transition:background-color .15s ease}.coloeus-editor__cancel-btn:hover{background:#e5e7eb}.coloeus-editor__error{margin-top:1rem;padding:.75rem;background:#fef2f2;border:1px solid #fecaca;border-radius:6px;color:#dc2626;font-size:.875rem}.coloeus-editor__max-selections{margin-top:1rem}.coloeus-editor__input--small{width:80px}.coloeus-editor__hint{margin-top:.5rem;font-size:.875rem;color:#666;font-style:italic}.coloeus-editor__max-selections-readonly{margin-top:1rem;display:flex;align-items:center;gap:.75rem}.coloeus-editor__max-selections-readonly .coloeus-editor__label{margin-bottom:0}.coloeus-editor__readonly-value{font-weight:500;color:#1a1a1a}
|
|
@@ -1,595 +1,659 @@
|
|
|
1
|
-
import { ref as
|
|
2
|
-
|
|
1
|
+
import { ref as S, computed as f, onMounted as Q, reactive as pe, toRaw as ve, watch as j, defineComponent as W, createElementBlock as c, openBlock as u, Fragment as x, createElementVNode as n, createCommentVNode as C, withModifiers as X, toDisplayString as h, createTextVNode as Y, renderList as Z, normalizeClass as fe, normalizeStyle as me, withDirectives as N, vModelText as D } from "vue";
|
|
2
|
+
class $ extends Error {
|
|
3
|
+
constructor(o, d, e) {
|
|
4
|
+
super(d), this.status = o, this.data = e, this.name = "ApiError";
|
|
5
|
+
}
|
|
6
|
+
}
|
|
7
|
+
let E = {
|
|
3
8
|
apiUrl: ""
|
|
4
9
|
};
|
|
5
|
-
function
|
|
6
|
-
|
|
10
|
+
function ko(l) {
|
|
11
|
+
E = { ...E, ...l };
|
|
7
12
|
}
|
|
8
|
-
function
|
|
9
|
-
return
|
|
13
|
+
function To() {
|
|
14
|
+
return E;
|
|
10
15
|
}
|
|
11
|
-
async function
|
|
12
|
-
const
|
|
16
|
+
async function q() {
|
|
17
|
+
const l = {
|
|
13
18
|
"Content-Type": "application/json"
|
|
14
19
|
};
|
|
15
|
-
if (
|
|
16
|
-
const
|
|
17
|
-
|
|
20
|
+
if (E.getAuthToken) {
|
|
21
|
+
const o = await E.getAuthToken();
|
|
22
|
+
o && (l.Authorization = `Bearer ${o}`);
|
|
18
23
|
}
|
|
19
|
-
return
|
|
24
|
+
return l;
|
|
20
25
|
}
|
|
21
|
-
async function L(
|
|
22
|
-
if (!
|
|
23
|
-
const
|
|
24
|
-
throw new
|
|
26
|
+
async function L(l) {
|
|
27
|
+
if (!l.ok) {
|
|
28
|
+
const o = await l.json().catch(() => ({ error: "Unknown error" }));
|
|
29
|
+
throw new $(
|
|
30
|
+
l.status,
|
|
31
|
+
o.error || `HTTP error ${l.status}`,
|
|
32
|
+
o.data
|
|
33
|
+
);
|
|
25
34
|
}
|
|
26
|
-
return
|
|
35
|
+
return l.json();
|
|
27
36
|
}
|
|
28
|
-
async function
|
|
29
|
-
const
|
|
37
|
+
async function he(l) {
|
|
38
|
+
const o = await fetch(`${E.apiUrl}/polls/${l}`, {
|
|
30
39
|
method: "GET",
|
|
31
40
|
headers: {
|
|
32
41
|
"Content-Type": "application/json"
|
|
33
42
|
}
|
|
34
43
|
});
|
|
35
|
-
return L(
|
|
44
|
+
return L(o);
|
|
36
45
|
}
|
|
37
|
-
async function
|
|
38
|
-
if (
|
|
46
|
+
async function ye(l, o) {
|
|
47
|
+
if (o.length === 0)
|
|
39
48
|
throw new Error("At least one option must be selected");
|
|
40
|
-
const
|
|
49
|
+
const d = await fetch(`${E.apiUrl}/polls/${l}/vote`, {
|
|
41
50
|
method: "POST",
|
|
42
51
|
headers: {
|
|
43
52
|
"Content-Type": "application/json"
|
|
44
53
|
},
|
|
45
|
-
body: JSON.stringify({ optionIndices:
|
|
54
|
+
body: JSON.stringify({ optionIndices: o })
|
|
46
55
|
});
|
|
47
|
-
return L(
|
|
56
|
+
return L(d);
|
|
48
57
|
}
|
|
49
|
-
async function
|
|
50
|
-
const
|
|
58
|
+
async function be(l) {
|
|
59
|
+
const o = await q(), d = await fetch(`${E.apiUrl}/admin/polls`, {
|
|
51
60
|
method: "POST",
|
|
52
|
-
headers:
|
|
53
|
-
body: JSON.stringify(
|
|
61
|
+
headers: o,
|
|
62
|
+
body: JSON.stringify(l)
|
|
54
63
|
});
|
|
55
|
-
return L(
|
|
64
|
+
return L(d);
|
|
56
65
|
}
|
|
57
|
-
async function
|
|
58
|
-
const
|
|
66
|
+
async function ge(l, o) {
|
|
67
|
+
const d = await q(), e = await fetch(`${E.apiUrl}/admin/polls/${l}`, {
|
|
59
68
|
method: "PUT",
|
|
60
|
-
headers:
|
|
61
|
-
body: JSON.stringify(
|
|
69
|
+
headers: d,
|
|
70
|
+
body: JSON.stringify(o)
|
|
62
71
|
});
|
|
63
72
|
return L(e);
|
|
64
73
|
}
|
|
65
|
-
async function
|
|
66
|
-
const
|
|
74
|
+
async function Se(l) {
|
|
75
|
+
const o = await q(), d = await fetch(`${E.apiUrl}/admin/polls/${l}`, {
|
|
67
76
|
method: "GET",
|
|
68
|
-
headers:
|
|
77
|
+
headers: o
|
|
69
78
|
});
|
|
70
|
-
return L(
|
|
79
|
+
return L(d);
|
|
71
80
|
}
|
|
72
|
-
function
|
|
73
|
-
const
|
|
74
|
-
(
|
|
81
|
+
function Oe(l) {
|
|
82
|
+
const o = S(null), d = S(!0), e = S(null), r = f(() => o.value?.totalVotes ?? 0), p = f(() => o.value?.isActive ?? !1), s = f(() => !o.value || r.value === 0 ? o.value?.options.map(() => 0) ?? [] : o.value.options.map(
|
|
83
|
+
(_) => Math.round(_.voteCount / r.value * 100)
|
|
75
84
|
));
|
|
76
|
-
async function
|
|
77
|
-
|
|
85
|
+
async function t() {
|
|
86
|
+
d.value = !0, e.value = null;
|
|
78
87
|
try {
|
|
79
|
-
|
|
80
|
-
} catch (
|
|
81
|
-
e.value =
|
|
88
|
+
o.value = await he(l);
|
|
89
|
+
} catch (_) {
|
|
90
|
+
e.value = _ instanceof Error ? _.message : "Failed to load poll", o.value = null;
|
|
82
91
|
} finally {
|
|
83
|
-
|
|
92
|
+
d.value = !1;
|
|
84
93
|
}
|
|
85
94
|
}
|
|
86
|
-
function a(
|
|
87
|
-
|
|
95
|
+
function a(_) {
|
|
96
|
+
o.value = _;
|
|
88
97
|
}
|
|
89
|
-
return
|
|
90
|
-
|
|
98
|
+
return Q(() => {
|
|
99
|
+
t();
|
|
91
100
|
}), {
|
|
92
|
-
poll:
|
|
93
|
-
loading:
|
|
101
|
+
poll: o,
|
|
102
|
+
loading: d,
|
|
94
103
|
error: e,
|
|
95
|
-
totalVotes:
|
|
96
|
-
isActive:
|
|
97
|
-
optionPercentages:
|
|
98
|
-
loadPoll:
|
|
104
|
+
totalVotes: r,
|
|
105
|
+
isActive: p,
|
|
106
|
+
optionPercentages: s,
|
|
107
|
+
loadPoll: t,
|
|
99
108
|
updatePoll: a
|
|
100
109
|
};
|
|
101
110
|
}
|
|
102
|
-
const
|
|
103
|
-
function
|
|
111
|
+
const ee = "coloeus-votes";
|
|
112
|
+
function Ve() {
|
|
104
113
|
try {
|
|
105
|
-
const
|
|
106
|
-
return
|
|
114
|
+
const l = localStorage.getItem(ee);
|
|
115
|
+
return l ? JSON.parse(l) : {};
|
|
107
116
|
} catch {
|
|
108
117
|
return {};
|
|
109
118
|
}
|
|
110
119
|
}
|
|
111
|
-
function
|
|
120
|
+
function J(l) {
|
|
112
121
|
try {
|
|
113
|
-
localStorage.setItem(
|
|
122
|
+
localStorage.setItem(ee, JSON.stringify(ve(l)));
|
|
114
123
|
} catch {
|
|
115
124
|
}
|
|
116
125
|
}
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
function l(
|
|
120
|
-
return
|
|
126
|
+
const w = pe(Ve());
|
|
127
|
+
function ke() {
|
|
128
|
+
function l(p) {
|
|
129
|
+
return p in w;
|
|
121
130
|
}
|
|
122
|
-
function
|
|
123
|
-
const
|
|
124
|
-
if (
|
|
131
|
+
function o(p) {
|
|
132
|
+
const s = w[p];
|
|
133
|
+
if (s == null)
|
|
125
134
|
return [];
|
|
126
|
-
const
|
|
127
|
-
return Array.from(new Set(
|
|
135
|
+
const t = Array.isArray(s) ? s : [s];
|
|
136
|
+
return Array.from(new Set(t)).sort((a, _) => a - _);
|
|
128
137
|
}
|
|
129
|
-
function
|
|
130
|
-
const
|
|
131
|
-
|
|
132
|
-
...t.value,
|
|
133
|
-
[n]: i.length === 1 ? i[0] : i
|
|
134
|
-
}, R(t.value);
|
|
138
|
+
function d(p, s) {
|
|
139
|
+
const t = Array.isArray(s) ? s : [s], a = Array.from(new Set(t)).sort((_, y) => _ - y);
|
|
140
|
+
w[p] = a.length === 1 ? a[0] : a, J(w);
|
|
135
141
|
}
|
|
136
|
-
function p
|
|
137
|
-
|
|
138
|
-
delete o[n], t.value = o, R(t.value);
|
|
142
|
+
function e(p) {
|
|
143
|
+
delete w[p], J(w);
|
|
139
144
|
}
|
|
140
|
-
function
|
|
141
|
-
|
|
145
|
+
function r() {
|
|
146
|
+
for (const p of Object.keys(w))
|
|
147
|
+
delete w[p];
|
|
148
|
+
J(w);
|
|
142
149
|
}
|
|
143
150
|
return {
|
|
144
|
-
votes:
|
|
151
|
+
votes: w,
|
|
145
152
|
hasVoted: l,
|
|
146
|
-
getVotedOptions:
|
|
147
|
-
recordVote:
|
|
148
|
-
clearVote:
|
|
149
|
-
clearAllVotes:
|
|
153
|
+
getVotedOptions: o,
|
|
154
|
+
recordVote: d,
|
|
155
|
+
clearVote: e,
|
|
156
|
+
clearAllVotes: r
|
|
150
157
|
};
|
|
151
158
|
}
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
159
|
+
const Te = 409;
|
|
160
|
+
function we(l, o) {
|
|
161
|
+
const { hasVoted: d, getVotedOptions: e, recordVote: r } = ke(), p = S(!1), s = S(null), t = S([]), a = S(1);
|
|
162
|
+
o?.selectionLimit && j(
|
|
163
|
+
o.selectionLimit,
|
|
164
|
+
(v) => {
|
|
165
|
+
a.value = Ce(v), t.value.length > a.value && (t.value = t.value.slice(0, a.value));
|
|
158
166
|
},
|
|
159
167
|
{ immediate: !0 }
|
|
160
168
|
);
|
|
161
|
-
const
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
(
|
|
165
|
-
|
|
169
|
+
const _ = f(() => d(l)), y = f(() => e(l)), I = f(() => a.value > 1), P = f(() => t.value.length > 0);
|
|
170
|
+
j(
|
|
171
|
+
y,
|
|
172
|
+
(v) => {
|
|
173
|
+
_.value && v.length && (t.value = [...v]);
|
|
166
174
|
},
|
|
167
175
|
{ immediate: !0 }
|
|
168
176
|
);
|
|
169
|
-
function
|
|
170
|
-
if (!
|
|
171
|
-
if (k(),
|
|
172
|
-
if (
|
|
173
|
-
|
|
177
|
+
function O(v) {
|
|
178
|
+
if (!_.value)
|
|
179
|
+
if (k(), I.value) {
|
|
180
|
+
if (t.value.includes(v)) {
|
|
181
|
+
t.value = t.value.filter((m) => m !== v);
|
|
174
182
|
return;
|
|
175
183
|
}
|
|
176
|
-
if (
|
|
177
|
-
|
|
184
|
+
if (t.value.length < a.value) {
|
|
185
|
+
t.value = [...t.value, v];
|
|
178
186
|
return;
|
|
179
187
|
}
|
|
180
|
-
|
|
188
|
+
s.value = `You can select up to ${a.value} options.`;
|
|
181
189
|
} else
|
|
182
|
-
|
|
190
|
+
t.value = [v];
|
|
183
191
|
}
|
|
184
|
-
async function
|
|
185
|
-
if (!
|
|
186
|
-
return
|
|
187
|
-
if (
|
|
188
|
-
return
|
|
189
|
-
|
|
190
|
-
const
|
|
192
|
+
async function A() {
|
|
193
|
+
if (!P.value)
|
|
194
|
+
return s.value = "Please select at least one option", null;
|
|
195
|
+
if (_.value)
|
|
196
|
+
return s.value = "You have already voted on this poll", null;
|
|
197
|
+
p.value = !0, s.value = null;
|
|
198
|
+
const v = [...t.value].sort((m, T) => m - T);
|
|
191
199
|
try {
|
|
192
|
-
const
|
|
193
|
-
return
|
|
194
|
-
} catch (
|
|
195
|
-
|
|
200
|
+
const m = await ye(l, v);
|
|
201
|
+
return r(l, v), m.poll;
|
|
202
|
+
} catch (m) {
|
|
203
|
+
if (s.value = m instanceof Error ? m.message : "Failed to submit vote", m instanceof $ && m.status === Te) {
|
|
204
|
+
const T = m.data?.optionIndices;
|
|
205
|
+
Array.isArray(T) ? r(l, T) : r(l, v);
|
|
206
|
+
}
|
|
207
|
+
return null;
|
|
196
208
|
} finally {
|
|
197
|
-
|
|
209
|
+
p.value = !1;
|
|
198
210
|
}
|
|
199
211
|
}
|
|
200
212
|
function k() {
|
|
201
|
-
|
|
213
|
+
s.value = null;
|
|
202
214
|
}
|
|
203
215
|
return {
|
|
204
|
-
submitting:
|
|
205
|
-
error:
|
|
206
|
-
selectedOptions:
|
|
216
|
+
submitting: p,
|
|
217
|
+
error: s,
|
|
218
|
+
selectedOptions: t,
|
|
207
219
|
selectionLimit: a,
|
|
208
|
-
isMultiSelect:
|
|
209
|
-
hasSelection:
|
|
210
|
-
alreadyVoted:
|
|
211
|
-
votedOptionIndices:
|
|
212
|
-
selectOption:
|
|
213
|
-
submitVote:
|
|
220
|
+
isMultiSelect: I,
|
|
221
|
+
hasSelection: P,
|
|
222
|
+
alreadyVoted: _,
|
|
223
|
+
votedOptionIndices: y,
|
|
224
|
+
selectOption: O,
|
|
225
|
+
submitVote: A,
|
|
214
226
|
clearError: k
|
|
215
227
|
};
|
|
216
228
|
}
|
|
217
|
-
function
|
|
218
|
-
return typeof
|
|
229
|
+
function Ce(l) {
|
|
230
|
+
return typeof l != "number" || !Number.isFinite(l) || l <= 0 ? 1 : Math.max(1, Math.floor(l));
|
|
219
231
|
}
|
|
220
|
-
const
|
|
232
|
+
const Ee = /* @__PURE__ */ W({
|
|
221
233
|
__name: "ColoeusPolls",
|
|
222
234
|
props: {
|
|
223
235
|
id: { type: String, required: !0 }
|
|
224
236
|
},
|
|
225
237
|
emits: ["voted", "error"],
|
|
226
|
-
setup(
|
|
227
|
-
|
|
228
|
-
const e =
|
|
229
|
-
const
|
|
230
|
-
return typeof
|
|
238
|
+
setup(l, { expose: o, emit: d }) {
|
|
239
|
+
o();
|
|
240
|
+
const e = S(!1), r = l, p = d, { poll: s, loading: t, error: a, totalVotes: _, isActive: y, optionPercentages: I, updatePoll: P } = Oe(r.id), O = f(() => {
|
|
241
|
+
const g = s.value?.maxSelections;
|
|
242
|
+
return typeof g == "number" && g > 0 ? Math.floor(g) : 1;
|
|
231
243
|
}), {
|
|
232
|
-
submitting:
|
|
233
|
-
error:
|
|
234
|
-
selectedOptions:
|
|
235
|
-
selectionLimit:
|
|
236
|
-
isMultiSelect:
|
|
237
|
-
hasSelection:
|
|
238
|
-
alreadyVoted:
|
|
239
|
-
votedOptionIndices:
|
|
240
|
-
selectOption:
|
|
241
|
-
submitVote:
|
|
242
|
-
clearError:
|
|
243
|
-
} =
|
|
244
|
-
async function
|
|
245
|
-
|
|
246
|
-
const
|
|
247
|
-
|
|
244
|
+
submitting: A,
|
|
245
|
+
error: k,
|
|
246
|
+
selectedOptions: v,
|
|
247
|
+
selectionLimit: m,
|
|
248
|
+
isMultiSelect: T,
|
|
249
|
+
hasSelection: z,
|
|
250
|
+
alreadyVoted: M,
|
|
251
|
+
votedOptionIndices: R,
|
|
252
|
+
selectOption: F,
|
|
253
|
+
submitVote: U,
|
|
254
|
+
clearError: i
|
|
255
|
+
} = we(r.id, { selectionLimit: O }), b = f(() => a.value || k.value), V = f(() => y.value && !M.value), B = f(() => M.value || !y.value || e.value), te = f(() => `coloeus-poll-title-${r.id}`), le = f(() => `coloeus-poll-instructions-${r.id}`), se = f(() => `coloeus-poll-status-${r.id}`), ne = f(() => y.value ? M.value ? "You have already voted on this poll" : "Voting is open" : "Voting is closed"), ie = f(() => T.value ? "checkbox" : "radio"), ae = f(() => T.value ? `Select up to ${m.value} options and submit your vote.` : "Select one option and submit your vote.");
|
|
256
|
+
async function re() {
|
|
257
|
+
i();
|
|
258
|
+
const g = await U();
|
|
259
|
+
g ? (P(g), p("voted", r.id, [...v.value])) : k.value && p("error", k.value);
|
|
248
260
|
}
|
|
249
|
-
function
|
|
250
|
-
|
|
261
|
+
function ce(g) {
|
|
262
|
+
V.value && F(g);
|
|
251
263
|
}
|
|
252
|
-
function
|
|
253
|
-
return `coloeus-poll-option-${
|
|
264
|
+
function ue(g) {
|
|
265
|
+
return `coloeus-poll-option-${r.id}-stats-${g}`;
|
|
254
266
|
}
|
|
255
|
-
function
|
|
256
|
-
return
|
|
267
|
+
function G(g) {
|
|
268
|
+
return v.value.includes(g);
|
|
257
269
|
}
|
|
258
|
-
function
|
|
259
|
-
return
|
|
270
|
+
function H(g) {
|
|
271
|
+
return R.value.includes(g);
|
|
260
272
|
}
|
|
261
|
-
function
|
|
262
|
-
return
|
|
273
|
+
function de(g) {
|
|
274
|
+
return G(g) || H(g);
|
|
263
275
|
}
|
|
264
|
-
|
|
265
|
-
|
|
276
|
+
function _e() {
|
|
277
|
+
e.value = !0;
|
|
278
|
+
}
|
|
279
|
+
const K = { resultsRevealed: e, props: r, emit: p, poll: s, loading: t, pollError: a, totalVotes: _, isActive: y, optionPercentages: I, updatePoll: P, pollSelectionLimit: O, submitting: A, voteError: k, selectedOptions: v, selectionLimit: m, isMultiSelect: T, hasSelection: z, alreadyVoted: M, votedOptionIndices: R, selectOption: F, submitVote: U, clearError: i, displayError: b, canVote: V, showResults: B, pollTitleId: te, pollInstructionsId: le, pollStatusId: se, pollStatusMessage: ne, optionInputType: ie, selectionInstruction: ae, handleVote: re, handleOptionSelect: ce, getOptionStatsId: ue, isOptionCurrentlySelected: G, hasVotedForOption: H, isOptionChecked: de, revealResults: _e };
|
|
280
|
+
return Object.defineProperty(K, "__isScriptSetup", { enumerable: !1, value: !0 }), K;
|
|
266
281
|
}
|
|
267
|
-
}),
|
|
268
|
-
const
|
|
269
|
-
for (const [e,
|
|
270
|
-
|
|
271
|
-
return
|
|
272
|
-
},
|
|
282
|
+
}), oe = (l, o) => {
|
|
283
|
+
const d = l.__vccOpts || l;
|
|
284
|
+
for (const [e, r] of o)
|
|
285
|
+
d[e] = r;
|
|
286
|
+
return d;
|
|
287
|
+
}, Pe = { class: "coloeus-poll" }, Ie = {
|
|
273
288
|
key: 0,
|
|
274
289
|
class: "coloeus-poll__loading"
|
|
275
|
-
},
|
|
290
|
+
}, Ae = ["aria-labelledby", "aria-describedby"], Me = ["aria-describedby", "aria-disabled"], Ue = ["id"], xe = ["id"], Le = {
|
|
276
291
|
key: 0,
|
|
277
292
|
class: "coloeus-poll__instructions-note"
|
|
278
|
-
},
|
|
293
|
+
}, Re = {
|
|
279
294
|
class: "coloeus-poll__options",
|
|
280
295
|
role: "list"
|
|
281
|
-
},
|
|
282
|
-
key:
|
|
296
|
+
}, Fe = { class: "coloeus-poll__option-label" }, Ne = ["type", "name", "value", "checked", "disabled", "aria-describedby", "onChange"], De = { class: "coloeus-poll__option-content" }, je = { class: "coloeus-poll__option-text" }, ze = {
|
|
297
|
+
key: 1,
|
|
283
298
|
class: "coloeus-poll__option-stats",
|
|
284
299
|
"aria-hidden": "true"
|
|
285
|
-
},
|
|
300
|
+
}, Ye = { class: "coloeus-poll__option-percentage" }, Je = ["id"], qe = { key: 0 }, Be = { class: "coloeus-poll__footer" }, Ge = { class: "coloeus-poll__actions" }, He = ["disabled"], Ke = {
|
|
286
301
|
class: "coloeus-poll__total",
|
|
287
302
|
"aria-live": "polite"
|
|
288
|
-
},
|
|
303
|
+
}, Qe = ["id"], We = {
|
|
289
304
|
key: 0,
|
|
290
305
|
class: "coloeus-poll__status coloeus-poll__status--inactive"
|
|
291
|
-
},
|
|
306
|
+
}, Xe = {
|
|
292
307
|
key: 1,
|
|
293
308
|
class: "coloeus-poll__status coloeus-poll__status--active"
|
|
294
|
-
},
|
|
309
|
+
}, Ze = {
|
|
295
310
|
key: 2,
|
|
296
311
|
class: "coloeus-poll__status coloeus-poll__status--open"
|
|
297
|
-
},
|
|
312
|
+
}, $e = { class: "coloeus-poll__sr" }, eo = {
|
|
298
313
|
key: 0,
|
|
299
314
|
class: "coloeus-poll__error",
|
|
300
315
|
role: "alert",
|
|
301
316
|
"aria-live": "assertive"
|
|
302
|
-
},
|
|
317
|
+
}, oo = {
|
|
303
318
|
key: 2,
|
|
304
319
|
class: "coloeus-poll__error"
|
|
305
320
|
};
|
|
306
|
-
function
|
|
307
|
-
return
|
|
308
|
-
e.loading ? (
|
|
309
|
-
|
|
321
|
+
function to(l, o, d, e, r, p) {
|
|
322
|
+
return u(), c("div", Pe, [
|
|
323
|
+
e.loading ? (u(), c("div", Ie, "Loading poll...")) : e.poll ? (u(), c(x, { key: 1 }, [
|
|
324
|
+
n("form", {
|
|
310
325
|
class: "coloeus-poll__form",
|
|
311
326
|
role: "form",
|
|
312
327
|
"aria-labelledby": e.pollTitleId,
|
|
313
328
|
"aria-describedby": `${e.pollInstructionsId} ${e.pollStatusId}`,
|
|
314
|
-
onSubmit:
|
|
329
|
+
onSubmit: X(e.handleVote, ["prevent"])
|
|
315
330
|
}, [
|
|
316
|
-
|
|
331
|
+
n("fieldset", {
|
|
317
332
|
class: "coloeus-poll__fieldset",
|
|
318
333
|
"aria-describedby": `${e.pollInstructionsId} ${e.pollStatusId}`,
|
|
319
334
|
"aria-disabled": !e.canVote
|
|
320
335
|
}, [
|
|
321
|
-
|
|
336
|
+
n("legend", {
|
|
322
337
|
id: e.pollTitleId,
|
|
323
338
|
class: "coloeus-poll__title"
|
|
324
|
-
}, h(e.poll.title), 9,
|
|
325
|
-
|
|
339
|
+
}, h(e.poll.title), 9, Ue),
|
|
340
|
+
n("p", {
|
|
326
341
|
id: e.pollInstructionsId,
|
|
327
342
|
class: "coloeus-poll__instructions"
|
|
328
343
|
}, [
|
|
329
|
-
|
|
330
|
-
e.canVote ?
|
|
331
|
-
], 8,
|
|
332
|
-
|
|
333
|
-
(
|
|
334
|
-
key:
|
|
335
|
-
class:
|
|
336
|
-
"coloeus-poll__option--selected": e.isOptionCurrentlySelected(
|
|
337
|
-
"coloeus-poll__option--voted": e.hasVotedForOption(
|
|
344
|
+
Y(h(e.selectionInstruction) + " ", 1),
|
|
345
|
+
e.canVote ? C("", !0) : (u(), c("span", Le, h(e.pollStatusMessage), 1))
|
|
346
|
+
], 8, xe),
|
|
347
|
+
n("ul", Re, [
|
|
348
|
+
(u(!0), c(x, null, Z(e.poll.options, (s, t) => (u(), c("li", {
|
|
349
|
+
key: t,
|
|
350
|
+
class: fe(["coloeus-poll__option", {
|
|
351
|
+
"coloeus-poll__option--selected": e.isOptionCurrentlySelected(t),
|
|
352
|
+
"coloeus-poll__option--voted": e.hasVotedForOption(t),
|
|
338
353
|
"coloeus-poll__option--disabled": !e.canVote
|
|
339
354
|
}])
|
|
340
355
|
}, [
|
|
341
|
-
|
|
342
|
-
|
|
356
|
+
n("label", Fe, [
|
|
357
|
+
n("input", {
|
|
343
358
|
type: e.optionInputType,
|
|
344
359
|
class: "coloeus-poll__option-input",
|
|
345
360
|
name: `coloeus-poll-${e.props.id}`,
|
|
346
|
-
value:
|
|
347
|
-
checked: e.isOptionChecked(
|
|
361
|
+
value: t,
|
|
362
|
+
checked: e.isOptionChecked(t),
|
|
348
363
|
disabled: !e.canVote,
|
|
349
|
-
"aria-describedby": e.getOptionStatsId(
|
|
350
|
-
onChange: (a) => e.handleOptionSelect(
|
|
351
|
-
}, null, 40,
|
|
352
|
-
|
|
353
|
-
|
|
364
|
+
"aria-describedby": e.getOptionStatsId(t),
|
|
365
|
+
onChange: (a) => e.handleOptionSelect(t)
|
|
366
|
+
}, null, 40, Ne),
|
|
367
|
+
n("span", De, [
|
|
368
|
+
e.showResults ? (u(), c("span", {
|
|
369
|
+
key: 0,
|
|
354
370
|
class: "coloeus-poll__option-progress",
|
|
355
|
-
style:
|
|
371
|
+
style: me({ width: `${e.optionPercentages[t]}%` }),
|
|
356
372
|
"aria-hidden": "true"
|
|
357
|
-
}, null, 4),
|
|
358
|
-
|
|
359
|
-
e.showResults ? (
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
])) :
|
|
363
|
-
|
|
364
|
-
id: e.getOptionStatsId(
|
|
373
|
+
}, null, 4)) : C("", !0),
|
|
374
|
+
n("span", je, h(s.text), 1),
|
|
375
|
+
e.showResults ? (u(), c("span", ze, [
|
|
376
|
+
n("span", Ye, h(e.optionPercentages[t]) + "%", 1),
|
|
377
|
+
n("span", null, "(" + h(s.voteCount) + ")", 1)
|
|
378
|
+
])) : C("", !0),
|
|
379
|
+
n("span", {
|
|
380
|
+
id: e.getOptionStatsId(t),
|
|
365
381
|
class: "coloeus-poll__sr"
|
|
366
382
|
}, [
|
|
367
|
-
e.showResults ? (
|
|
368
|
-
|
|
369
|
-
e.hasVotedForOption(
|
|
370
|
-
], 64)) : (
|
|
371
|
-
|
|
383
|
+
e.showResults ? (u(), c(x, { key: 0 }, [
|
|
384
|
+
Y(h(s.voteCount) + " vote" + h(s.voteCount === 1 ? "" : "s") + " (" + h(e.optionPercentages[t]) + " percent). ", 1),
|
|
385
|
+
e.hasVotedForOption(t) ? (u(), c("span", qe, "You selected this option.")) : C("", !0)
|
|
386
|
+
], 64)) : (u(), c(x, { key: 1 }, [
|
|
387
|
+
Y(" Results are hidden until voting closes. ")
|
|
372
388
|
], 64))
|
|
373
|
-
], 8,
|
|
389
|
+
], 8, Je)
|
|
374
390
|
])
|
|
375
391
|
])
|
|
376
392
|
], 2))), 128))
|
|
377
393
|
])
|
|
378
|
-
], 8,
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
394
|
+
], 8, Me),
|
|
395
|
+
n("div", Be, [
|
|
396
|
+
n("div", Ge, [
|
|
397
|
+
e.canVote ? (u(), c("button", {
|
|
398
|
+
key: 0,
|
|
399
|
+
type: "submit",
|
|
400
|
+
class: "coloeus-poll__vote-btn",
|
|
401
|
+
disabled: !e.hasSelection || e.submitting
|
|
402
|
+
}, h(e.submitting ? "Voting..." : "Vote"), 9, He)) : C("", !0),
|
|
403
|
+
e.canVote && !e.showResults ? (u(), c("button", {
|
|
404
|
+
key: 1,
|
|
405
|
+
type: "button",
|
|
406
|
+
class: "coloeus-poll__results-btn",
|
|
407
|
+
onClick: e.revealResults
|
|
408
|
+
}, " Show results ")) : C("", !0)
|
|
409
|
+
]),
|
|
410
|
+
n("span", Ke, h(e.totalVotes) + " vote" + h(e.totalVotes === 1 ? "" : "s") + " cast ", 1),
|
|
411
|
+
n("div", {
|
|
388
412
|
id: e.pollStatusId,
|
|
389
413
|
class: "coloeus-poll__status-group",
|
|
390
414
|
role: "status",
|
|
391
415
|
"aria-live": "polite"
|
|
392
416
|
}, [
|
|
393
|
-
e.isActive ? e.alreadyVoted ? (
|
|
394
|
-
|
|
395
|
-
], 8,
|
|
417
|
+
e.isActive ? e.alreadyVoted ? (u(), c("span", Xe, " You voted ")) : (u(), c("span", Ze, " Voting open ")) : (u(), c("span", We, " Voting closed ")),
|
|
418
|
+
n("span", $e, h(e.pollStatusMessage), 1)
|
|
419
|
+
], 8, Qe)
|
|
396
420
|
])
|
|
397
|
-
], 40,
|
|
398
|
-
e.displayError ? (
|
|
399
|
-
], 64)) : (
|
|
421
|
+
], 40, Ae),
|
|
422
|
+
e.displayError ? (u(), c("div", eo, h(e.displayError), 1)) : C("", !0)
|
|
423
|
+
], 64)) : (u(), c("div", oo, "Failed to load poll"))
|
|
400
424
|
]);
|
|
401
425
|
}
|
|
402
|
-
const
|
|
426
|
+
const wo = /* @__PURE__ */ oe(Ee, [["render", to], ["__file", "/Users/philipp/Code/coloeus/frontend/components/src/components/ColoeusPolls.vue"]]), lo = /* @__PURE__ */ W({
|
|
403
427
|
__name: "ColoeusEditor",
|
|
404
428
|
props: {
|
|
405
429
|
id: { type: String, required: !1 }
|
|
406
430
|
},
|
|
407
431
|
emits: ["saved", "cancel", "error"],
|
|
408
|
-
setup(
|
|
409
|
-
|
|
410
|
-
const e =
|
|
411
|
-
|
|
432
|
+
setup(l, { expose: o, emit: d }) {
|
|
433
|
+
o();
|
|
434
|
+
const e = l, r = d, p = f(() => !!e.id), s = S(""), t = S(["", ""]), a = S(1), _ = S(""), y = S(""), I = S(!1), P = S(!1), O = S(null), A = f(() => t.value.filter((i) => i.trim()).length || 1);
|
|
435
|
+
j(A, (i) => {
|
|
436
|
+
a.value > i && (a.value = i);
|
|
437
|
+
});
|
|
438
|
+
const k = f(() => {
|
|
439
|
+
if (!s.value.trim()) return !1;
|
|
440
|
+
const i = t.value.filter((b) => b.trim());
|
|
441
|
+
return !(i.length < 2 || a.value < 1 || a.value > i.length);
|
|
442
|
+
});
|
|
443
|
+
async function v() {
|
|
412
444
|
if (e.id) {
|
|
413
|
-
|
|
445
|
+
I.value = !0, O.value = null;
|
|
414
446
|
try {
|
|
415
|
-
const
|
|
416
|
-
|
|
417
|
-
} catch (
|
|
418
|
-
|
|
447
|
+
const i = await Se(e.id);
|
|
448
|
+
s.value = i.title, t.value = i.options.map((b) => b.text), a.value = i.maxSelections ?? 1, _.value = i.startTime ? m(i.startTime) : "", y.value = i.endTime ? m(i.endTime) : "";
|
|
449
|
+
} catch (i) {
|
|
450
|
+
O.value = i instanceof Error ? i.message : "Failed to load poll", r("error", O.value);
|
|
419
451
|
} finally {
|
|
420
|
-
|
|
452
|
+
I.value = !1;
|
|
421
453
|
}
|
|
422
454
|
}
|
|
423
455
|
}
|
|
424
|
-
function
|
|
425
|
-
const
|
|
426
|
-
return new Date(
|
|
456
|
+
function m(i) {
|
|
457
|
+
const b = new Date(i), V = b.getTimezoneOffset();
|
|
458
|
+
return new Date(b.getTime() - V * 60 * 1e3).toISOString().slice(0, 16);
|
|
427
459
|
}
|
|
428
|
-
function
|
|
429
|
-
|
|
460
|
+
function T() {
|
|
461
|
+
t.value.length < 20 && (t.value = [...t.value, ""]);
|
|
430
462
|
}
|
|
431
|
-
function
|
|
432
|
-
|
|
463
|
+
function z(i) {
|
|
464
|
+
t.value.length > 2 && (t.value = t.value.filter((b, V) => V !== i));
|
|
433
465
|
}
|
|
434
|
-
function
|
|
435
|
-
const V = [...
|
|
436
|
-
V[
|
|
466
|
+
function M(i, b) {
|
|
467
|
+
const V = [...t.value];
|
|
468
|
+
V[i] = b, t.value = V;
|
|
437
469
|
}
|
|
438
|
-
async function
|
|
439
|
-
if (
|
|
440
|
-
|
|
470
|
+
async function R() {
|
|
471
|
+
if (k.value) {
|
|
472
|
+
P.value = !0, O.value = null;
|
|
441
473
|
try {
|
|
442
|
-
const
|
|
443
|
-
if (
|
|
444
|
-
const
|
|
445
|
-
title:
|
|
446
|
-
startTime:
|
|
447
|
-
endTime:
|
|
448
|
-
}, V = await
|
|
449
|
-
|
|
474
|
+
const i = t.value.filter((b) => b.trim());
|
|
475
|
+
if (p.value && e.id) {
|
|
476
|
+
const b = {
|
|
477
|
+
title: s.value.trim(),
|
|
478
|
+
startTime: _.value ? new Date(_.value).toISOString() : null,
|
|
479
|
+
endTime: y.value ? new Date(y.value).toISOString() : null
|
|
480
|
+
}, V = await ge(e.id, b);
|
|
481
|
+
r("saved", V);
|
|
450
482
|
} else {
|
|
451
|
-
const
|
|
452
|
-
title:
|
|
453
|
-
options:
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
483
|
+
const b = {
|
|
484
|
+
title: s.value.trim(),
|
|
485
|
+
options: i,
|
|
486
|
+
maxSelections: a.value,
|
|
487
|
+
startTime: _.value ? new Date(_.value).toISOString() : void 0,
|
|
488
|
+
endTime: y.value ? new Date(y.value).toISOString() : void 0
|
|
489
|
+
}, V = await be(b);
|
|
490
|
+
r("saved", V);
|
|
458
491
|
}
|
|
459
|
-
} catch (
|
|
460
|
-
|
|
492
|
+
} catch (i) {
|
|
493
|
+
O.value = i instanceof Error ? i.message : "Failed to save poll", r("error", O.value);
|
|
461
494
|
} finally {
|
|
462
|
-
|
|
495
|
+
P.value = !1;
|
|
463
496
|
}
|
|
464
497
|
}
|
|
465
498
|
}
|
|
466
499
|
function F() {
|
|
467
|
-
|
|
500
|
+
r("cancel");
|
|
468
501
|
}
|
|
469
|
-
|
|
470
|
-
e.id &&
|
|
471
|
-
}),
|
|
502
|
+
Q(() => {
|
|
503
|
+
e.id && v();
|
|
504
|
+
}), j(
|
|
472
505
|
() => e.id,
|
|
473
|
-
(
|
|
474
|
-
|
|
506
|
+
(i) => {
|
|
507
|
+
i ? v() : (s.value = "", t.value = ["", ""], a.value = 1, _.value = "", y.value = "", O.value = null);
|
|
475
508
|
}
|
|
476
509
|
);
|
|
477
|
-
const
|
|
478
|
-
return Object.defineProperty(
|
|
510
|
+
const U = { props: e, emit: r, isEditMode: p, title: s, options: t, maxSelections: a, startTime: _, endTime: y, loading: I, submitting: P, error: O, validOptionsCount: A, canSubmit: k, loadPoll: v, formatDateTimeLocal: m, addOption: T, removeOption: z, updateOption: M, handleSubmit: R, handleCancel: F };
|
|
511
|
+
return Object.defineProperty(U, "__isScriptSetup", { enumerable: !1, value: !0 }), U;
|
|
479
512
|
}
|
|
480
|
-
}),
|
|
513
|
+
}), so = { class: "coloeus-editor" }, no = { class: "coloeus-editor__title" }, io = {
|
|
481
514
|
key: 0,
|
|
482
515
|
class: "coloeus-poll__loading"
|
|
483
|
-
},
|
|
516
|
+
}, ao = { class: "coloeus-editor__field" }, ro = { class: "coloeus-editor__field" }, co = { class: "coloeus-editor__options" }, uo = ["value", "placeholder", "disabled", "onInput"], _o = ["onClick"], po = {
|
|
517
|
+
key: 1,
|
|
518
|
+
class: "coloeus-editor__max-selections"
|
|
519
|
+
}, vo = ["max"], fo = {
|
|
520
|
+
key: 2,
|
|
521
|
+
class: "coloeus-editor__max-selections-readonly"
|
|
522
|
+
}, mo = { class: "coloeus-editor__readonly-value" }, ho = { class: "coloeus-editor__field" }, yo = { class: "coloeus-editor__field" }, bo = { class: "coloeus-editor__actions" }, go = ["disabled"], So = {
|
|
484
523
|
key: 0,
|
|
485
524
|
class: "coloeus-editor__error"
|
|
486
525
|
};
|
|
487
|
-
function
|
|
488
|
-
return
|
|
489
|
-
|
|
490
|
-
e.loading ? (
|
|
526
|
+
function Oo(l, o, d, e, r, p) {
|
|
527
|
+
return u(), c("div", so, [
|
|
528
|
+
n("h3", no, h(e.isEditMode ? "Edit Poll" : "Create Poll"), 1),
|
|
529
|
+
e.loading ? (u(), c("div", io, "Loading...")) : (u(), c("form", {
|
|
491
530
|
key: 1,
|
|
492
|
-
onSubmit:
|
|
531
|
+
onSubmit: X(e.handleSubmit, ["prevent"])
|
|
493
532
|
}, [
|
|
494
|
-
|
|
495
|
-
|
|
533
|
+
n("div", ao, [
|
|
534
|
+
o[4] || (o[4] = n("label", {
|
|
496
535
|
class: "coloeus-editor__label",
|
|
497
536
|
for: "poll-title"
|
|
498
537
|
}, "Title", -1)),
|
|
499
|
-
|
|
538
|
+
N(n("input", {
|
|
500
539
|
id: "poll-title",
|
|
501
|
-
"onUpdate:modelValue":
|
|
540
|
+
"onUpdate:modelValue": o[0] || (o[0] = (s) => e.title = s),
|
|
502
541
|
type: "text",
|
|
503
542
|
class: "coloeus-editor__input",
|
|
504
543
|
placeholder: "Enter poll title",
|
|
505
544
|
maxlength: "500",
|
|
506
545
|
required: ""
|
|
507
546
|
}, null, 512), [
|
|
508
|
-
[
|
|
547
|
+
[D, e.title]
|
|
509
548
|
])
|
|
510
549
|
]),
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
(
|
|
515
|
-
key:
|
|
550
|
+
n("div", ro, [
|
|
551
|
+
o[8] || (o[8] = n("label", { class: "coloeus-editor__label" }, "Options", -1)),
|
|
552
|
+
n("ul", co, [
|
|
553
|
+
(u(!0), c(x, null, Z(e.options, (s, t) => (u(), c("li", {
|
|
554
|
+
key: t,
|
|
516
555
|
class: "coloeus-editor__option"
|
|
517
556
|
}, [
|
|
518
|
-
|
|
519
|
-
value:
|
|
557
|
+
n("input", {
|
|
558
|
+
value: s,
|
|
520
559
|
type: "text",
|
|
521
560
|
class: "coloeus-editor__option-input",
|
|
522
|
-
placeholder: `Option ${
|
|
561
|
+
placeholder: `Option ${t + 1}`,
|
|
523
562
|
maxlength: "150",
|
|
524
563
|
disabled: e.isEditMode,
|
|
525
|
-
onInput: (a) => e.updateOption(
|
|
526
|
-
}, null, 40,
|
|
527
|
-
e.options.length > 2 && !e.isEditMode ? (
|
|
564
|
+
onInput: (a) => e.updateOption(t, a.target.value)
|
|
565
|
+
}, null, 40, uo),
|
|
566
|
+
e.options.length > 2 && !e.isEditMode ? (u(), c("button", {
|
|
528
567
|
key: 0,
|
|
529
568
|
type: "button",
|
|
530
569
|
class: "coloeus-editor__remove-btn",
|
|
531
|
-
onClick: (a) => e.removeOption(
|
|
532
|
-
}, " Remove ", 8,
|
|
570
|
+
onClick: (a) => e.removeOption(t)
|
|
571
|
+
}, " Remove ", 8, _o)) : C("", !0)
|
|
533
572
|
]))), 128))
|
|
534
573
|
]),
|
|
535
|
-
e.options.length < 20 && !e.isEditMode ? (
|
|
574
|
+
e.options.length < 20 && !e.isEditMode ? (u(), c("button", {
|
|
536
575
|
key: 0,
|
|
537
576
|
type: "button",
|
|
538
577
|
class: "coloeus-editor__add-btn",
|
|
539
578
|
onClick: e.addOption
|
|
540
|
-
}, " + Add Option ")) :
|
|
579
|
+
}, " + Add Option ")) : C("", !0),
|
|
580
|
+
e.isEditMode ? (u(), c("div", fo, [
|
|
581
|
+
o[7] || (o[7] = n("label", { class: "coloeus-editor__label" }, "Max Selections", -1)),
|
|
582
|
+
n("span", mo, h(e.maxSelections), 1)
|
|
583
|
+
])) : (u(), c("div", po, [
|
|
584
|
+
o[5] || (o[5] = n("label", {
|
|
585
|
+
class: "coloeus-editor__label",
|
|
586
|
+
for: "poll-max-selections"
|
|
587
|
+
}, " Max Selections ", -1)),
|
|
588
|
+
N(n("input", {
|
|
589
|
+
id: "poll-max-selections",
|
|
590
|
+
"onUpdate:modelValue": o[1] || (o[1] = (s) => e.maxSelections = s),
|
|
591
|
+
type: "number",
|
|
592
|
+
class: "coloeus-editor__input coloeus-editor__input--small",
|
|
593
|
+
min: "1",
|
|
594
|
+
max: e.validOptionsCount
|
|
595
|
+
}, null, 8, vo), [
|
|
596
|
+
[
|
|
597
|
+
D,
|
|
598
|
+
e.maxSelections,
|
|
599
|
+
void 0,
|
|
600
|
+
{ number: !0 }
|
|
601
|
+
]
|
|
602
|
+
]),
|
|
603
|
+
o[6] || (o[6] = n("p", { class: "coloeus-editor__hint" }, " Users can select up to this many options (1 = single choice) ", -1))
|
|
604
|
+
]))
|
|
541
605
|
]),
|
|
542
|
-
|
|
543
|
-
|
|
606
|
+
n("div", ho, [
|
|
607
|
+
o[9] || (o[9] = n("label", {
|
|
544
608
|
class: "coloeus-editor__label",
|
|
545
609
|
for: "poll-start"
|
|
546
610
|
}, "Start Time (optional)", -1)),
|
|
547
|
-
|
|
611
|
+
N(n("input", {
|
|
548
612
|
id: "poll-start",
|
|
549
|
-
"onUpdate:modelValue":
|
|
613
|
+
"onUpdate:modelValue": o[2] || (o[2] = (s) => e.startTime = s),
|
|
550
614
|
type: "datetime-local",
|
|
551
615
|
class: "coloeus-editor__input"
|
|
552
616
|
}, null, 512), [
|
|
553
|
-
[
|
|
617
|
+
[D, e.startTime]
|
|
554
618
|
])
|
|
555
619
|
]),
|
|
556
|
-
|
|
557
|
-
|
|
620
|
+
n("div", yo, [
|
|
621
|
+
o[10] || (o[10] = n("label", {
|
|
558
622
|
class: "coloeus-editor__label",
|
|
559
623
|
for: "poll-end"
|
|
560
624
|
}, "End Time (optional)", -1)),
|
|
561
|
-
|
|
625
|
+
N(n("input", {
|
|
562
626
|
id: "poll-end",
|
|
563
|
-
"onUpdate:modelValue":
|
|
627
|
+
"onUpdate:modelValue": o[3] || (o[3] = (s) => e.endTime = s),
|
|
564
628
|
type: "datetime-local",
|
|
565
629
|
class: "coloeus-editor__input"
|
|
566
630
|
}, null, 512), [
|
|
567
|
-
[
|
|
631
|
+
[D, e.endTime]
|
|
568
632
|
])
|
|
569
633
|
]),
|
|
570
|
-
|
|
571
|
-
|
|
634
|
+
n("div", bo, [
|
|
635
|
+
n("button", {
|
|
572
636
|
type: "submit",
|
|
573
637
|
class: "coloeus-editor__submit-btn",
|
|
574
638
|
disabled: !e.canSubmit || e.submitting
|
|
575
|
-
}, h(e.submitting ? "Saving..." : e.isEditMode ? "Update Poll" : "Create Poll"), 9,
|
|
576
|
-
|
|
639
|
+
}, h(e.submitting ? "Saving..." : e.isEditMode ? "Update Poll" : "Create Poll"), 9, go),
|
|
640
|
+
n("button", {
|
|
577
641
|
type: "button",
|
|
578
642
|
class: "coloeus-editor__cancel-btn",
|
|
579
643
|
onClick: e.handleCancel
|
|
580
644
|
}, " Cancel ")
|
|
581
645
|
]),
|
|
582
|
-
e.error ? (
|
|
646
|
+
e.error ? (u(), c("div", So, h(e.error), 1)) : C("", !0)
|
|
583
647
|
], 32))
|
|
584
648
|
]);
|
|
585
649
|
}
|
|
586
|
-
const
|
|
650
|
+
const Co = /* @__PURE__ */ oe(lo, [["render", Oo], ["__file", "/Users/philipp/Code/coloeus/frontend/components/src/components/ColoeusEditor.vue"]]);
|
|
587
651
|
export {
|
|
588
|
-
|
|
589
|
-
|
|
590
|
-
|
|
591
|
-
|
|
592
|
-
|
|
593
|
-
|
|
594
|
-
|
|
652
|
+
Co as ColoeusEditor,
|
|
653
|
+
wo as ColoeusPolls,
|
|
654
|
+
ko as configureColoeus,
|
|
655
|
+
To as getConfig,
|
|
656
|
+
ke as useLocalStorage,
|
|
657
|
+
Oe as usePoll,
|
|
658
|
+
we as useVote
|
|
595
659
|
};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
(function(y,e){typeof exports=="object"&&typeof module<"u"?e(exports,require("vue")):typeof define=="function"&&define.amd?define(["exports","vue"],e):(y=typeof globalThis<"u"?globalThis:y||self,e(y.ColoeusComponents={},y.Vue))})(this,(function(y,e){"use strict";let E={apiUrl:""};function R(l){E={...E,...l}}function Y(){return E}async function v(){const l={"Content-Type":"application/json"};if(E.getAuthToken){const n=await E.getAuthToken();n&&(l.Authorization=`Bearer ${n}`)}return l}async function C(l){if(!l.ok){const n=await l.json().catch(()=>({error:"Unknown error"}));throw new Error(n.error||`HTTP error ${l.status}`)}return l.json()}async function J(l){const n=await fetch(`${E.apiUrl}/polls/${l}`,{method:"GET",headers:{"Content-Type":"application/json"}});return C(n)}async function q(l,n){if(n.length===0)throw new Error("At least one option must be selected");const c=await fetch(`${E.apiUrl}/polls/${l}/vote`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({optionIndices:n})});return C(c)}async function G(l){const n=await v(),c=await fetch(`${E.apiUrl}/admin/polls`,{method:"POST",headers:n,body:JSON.stringify(l)});return C(c)}async function H(l,n){const c=await v(),t=await fetch(`${E.apiUrl}/admin/polls/${l}`,{method:"PUT",headers:c,body:JSON.stringify(n)});return C(t)}async function K(l){const n=await v(),c=await fetch(`${E.apiUrl}/admin/polls/${l}`,{method:"GET",headers:n});return C(c)}function I(l){const n=e.ref(null),c=e.ref(!0),t=e.ref(null),d=e.computed(()=>n.value?.totalVotes??0),_=e.computed(()=>n.value?.isActive??!1),s=e.computed(()=>!n.value||d.value===0?n.value?.options.map(()=>0)??[]:n.value.options.map(a=>Math.round(a.voteCount/d.value*100)));async function o(){c.value=!0,t.value=null;try{n.value=await J(l)}catch(a){t.value=a instanceof Error?a.message:"Failed to load poll",n.value=null}finally{c.value=!1}}function i(a){n.value=a}return e.onMounted(()=>{o()}),{poll:n,loading:c,error:t,totalVotes:d,isActive:_,optionPercentages:s,loadPoll:o,updatePoll:i}}const M="coloeus-votes";function Q(){try{const l=localStorage.getItem(M);return l?JSON.parse(l):{}}catch{return{}}}function P(l){try{localStorage.setItem(M,JSON.stringify(l))}catch{}}function A(){const l=e.ref(Q());function n(s){return s in l.value}function c(s){const o=l.value[s];if(o==null)return[];const i=Array.isArray(o)?o:[o];return Array.from(new Set(i)).sort((a,g)=>a-g)}function t(s,o){const i=Array.isArray(o)?o:[o],a=Array.from(new Set(i)).sort((g,b)=>g-b);l.value={...l.value,[s]:a.length===1?a[0]:a},P(l.value)}function d(s){const o={...l.value};delete o[s],l.value=o,P(l.value)}function _(){l.value={},P(l.value)}return{votes:l,hasVoted:n,getVotedOptions:c,recordVote:t,clearVote:d,clearAllVotes:_}}function L(l,n){const{hasVoted:c,getVotedOptions:t,recordVote:d}=A(),_=e.ref(!1),s=e.ref(null),o=e.ref([]),i=e.ref(1);n?.selectionLimit&&e.watch(n.selectionLimit,u=>{i.value=W(u),o.value.length>i.value&&(o.value=o.value.slice(0,i.value))},{immediate:!0});const a=e.computed(()=>c(l)),g=e.computed(()=>t(l)),b=e.computed(()=>i.value>1),f=e.computed(()=>o.value.length>0);e.watch(g,u=>{a.value&&u.length&&(o.value=[...u])},{immediate:!0});function N(u){if(!a.value)if(S(),b.value){if(o.value.includes(u)){o.value=o.value.filter(h=>h!==u);return}if(o.value.length<i.value){o.value=[...o.value,u];return}s.value=`You can select up to ${i.value} options.`}else o.value=[u]}async function k(){if(!f.value)return s.value="Please select at least one option",null;if(a.value)return s.value="You have already voted on this poll",null;_.value=!0,s.value=null;const u=[...o.value].sort((h,B)=>h-B);try{const h=await q(l,u);return d(l,u),h.poll}catch(h){return s.value=h instanceof Error?h.message:"Failed to submit vote",null}finally{_.value=!1}}function S(){s.value=null}return{submitting:_,error:s,selectedOptions:o,selectionLimit:i,isMultiSelect:b,hasSelection:f,alreadyVoted:a,votedOptionIndices:g,selectOption:N,submitVote:k,clearError:S}}function W(l){return typeof l!="number"||!Number.isFinite(l)||l<=0?1:Math.max(1,Math.floor(l))}const X=e.defineComponent({__name:"ColoeusPolls",props:{id:{type:String,required:!0}},emits:["voted","error"],setup(l,{expose:n,emit:c}){n();const t=l,d=c,{poll:_,loading:s,error:o,totalVotes:i,isActive:a,optionPercentages:g,updatePoll:b}=I(t.id),f=e.computed(()=>{const m=_.value?.maxSelections;return typeof m=="number"&&m>0?Math.floor(m):1}),{submitting:N,error:k,selectedOptions:S,selectionLimit:u,isMultiSelect:h,hasSelection:B,alreadyVoted:O,votedOptionIndices:w,selectOption:T,submitVote:r,clearError:p}=L(t.id,{selectionLimit:f}),V=e.computed(()=>o.value||k.value),D=e.computed(()=>a.value&&!O.value),Re=e.computed(()=>O.value||!a.value),Ye=e.computed(()=>`coloeus-poll-title-${t.id}`),Je=e.computed(()=>`coloeus-poll-instructions-${t.id}`),qe=e.computed(()=>`coloeus-poll-status-${t.id}`),Ge=e.computed(()=>a.value?O.value?"You have already voted on this poll":"Voting is open":"Voting is closed"),He=e.computed(()=>h.value?"checkbox":"radio"),Ke=e.computed(()=>h.value?`Select up to ${u.value} options and submit your vote.`:"Select one option and submit your vote.");async function Qe(){p();const m=await r();m?(b(m),d("voted",t.id,[...S.value])):k.value&&d("error",k.value)}function We(m){D.value&&T(m)}function Xe(m){return`coloeus-poll-option-${t.id}-stats-${m}`}function U(m){return S.value.includes(m)}function j(m){return w.value.includes(m)}function Ze(m){return U(m)||j(m)}const z={props:t,emit:d,poll:_,loading:s,pollError:o,totalVotes:i,isActive:a,optionPercentages:g,updatePoll:b,pollSelectionLimit:f,submitting:N,voteError:k,selectedOptions:S,selectionLimit:u,isMultiSelect:h,hasSelection:B,alreadyVoted:O,votedOptionIndices:w,selectOption:T,submitVote:r,clearError:p,displayError:V,canVote:D,showResults:Re,pollTitleId:Ye,pollInstructionsId:Je,pollStatusId:qe,pollStatusMessage:Ge,optionInputType:He,selectionInstruction:Ke,handleVote:Qe,handleOptionSelect:We,getOptionStatsId:Xe,isOptionCurrentlySelected:U,hasVotedForOption:j,isOptionChecked:Ze};return Object.defineProperty(z,"__isScriptSetup",{enumerable:!1,value:!0}),z}}),F=(l,n)=>{const c=l.__vccOpts||l;for(const[t,d]of n)c[t]=d;return c},Z={class:"coloeus-poll"},x={key:0,class:"coloeus-poll__loading"},$=["aria-labelledby","aria-describedby"],ee=["aria-describedby","aria-disabled"],te=["id"],oe=["id"],le={key:0,class:"coloeus-poll__instructions-note"},ne={class:"coloeus-poll__options",role:"list"},se={class:"coloeus-poll__option-label"},ae=["type","name","value","checked","disabled","aria-describedby","onChange"],ie={class:"coloeus-poll__option-content"},re={class:"coloeus-poll__option-text"},ce={key:0,class:"coloeus-poll__option-stats","aria-hidden":"true"},de={class:"coloeus-poll__option-percentage"},pe=["id"],ue={key:0},me={class:"coloeus-poll__footer"},_e=["disabled"],fe={class:"coloeus-poll__total","aria-live":"polite"},he=["id"],ye={key:0,class:"coloeus-poll__status coloeus-poll__status--inactive"},ge={key:1,class:"coloeus-poll__status coloeus-poll__status--active"},Ve={key:2,class:"coloeus-poll__status coloeus-poll__status--open"},be={class:"coloeus-poll__sr"},Ee={key:0,class:"coloeus-poll__error",role:"alert","aria-live":"assertive"},ke={key:2,class:"coloeus-poll__error"};function Se(l,n,c,t,d,_){return e.openBlock(),e.createElementBlock("div",Z,[t.loading?(e.openBlock(),e.createElementBlock("div",x,"Loading poll...")):t.poll?(e.openBlock(),e.createElementBlock(e.Fragment,{key:1},[e.createElementVNode("form",{class:"coloeus-poll__form",role:"form","aria-labelledby":t.pollTitleId,"aria-describedby":`${t.pollInstructionsId} ${t.pollStatusId}`,onSubmit:e.withModifiers(t.handleVote,["prevent"])},[e.createElementVNode("fieldset",{class:"coloeus-poll__fieldset","aria-describedby":`${t.pollInstructionsId} ${t.pollStatusId}`,"aria-disabled":!t.canVote},[e.createElementVNode("legend",{id:t.pollTitleId,class:"coloeus-poll__title"},e.toDisplayString(t.poll.title),9,te),e.createElementVNode("p",{id:t.pollInstructionsId,class:"coloeus-poll__instructions"},[e.createTextVNode(e.toDisplayString(t.selectionInstruction)+" ",1),t.canVote?e.createCommentVNode("",!0):(e.openBlock(),e.createElementBlock("span",le,e.toDisplayString(t.pollStatusMessage),1))],8,oe),e.createElementVNode("ul",ne,[(e.openBlock(!0),e.createElementBlock(e.Fragment,null,e.renderList(t.poll.options,(s,o)=>(e.openBlock(),e.createElementBlock("li",{key:o,class:e.normalizeClass(["coloeus-poll__option",{"coloeus-poll__option--selected":t.isOptionCurrentlySelected(o),"coloeus-poll__option--voted":t.hasVotedForOption(o),"coloeus-poll__option--disabled":!t.canVote}])},[e.createElementVNode("label",se,[e.createElementVNode("input",{type:t.optionInputType,class:"coloeus-poll__option-input",name:`coloeus-poll-${t.props.id}`,value:o,checked:t.isOptionChecked(o),disabled:!t.canVote,"aria-describedby":t.getOptionStatsId(o),onChange:i=>t.handleOptionSelect(o)},null,40,ae),e.createElementVNode("span",ie,[e.createElementVNode("span",{class:"coloeus-poll__option-progress",style:e.normalizeStyle({width:`${t.optionPercentages[o]}%`}),"aria-hidden":"true"},null,4),e.createElementVNode("span",re,e.toDisplayString(s.text),1),t.showResults?(e.openBlock(),e.createElementBlock("span",ce,[e.createElementVNode("span",de,e.toDisplayString(t.optionPercentages[o])+"%",1),e.createElementVNode("span",null,"("+e.toDisplayString(s.voteCount)+")",1)])):e.createCommentVNode("",!0),e.createElementVNode("span",{id:t.getOptionStatsId(o),class:"coloeus-poll__sr"},[t.showResults?(e.openBlock(),e.createElementBlock(e.Fragment,{key:0},[e.createTextVNode(e.toDisplayString(s.voteCount)+" vote"+e.toDisplayString(s.voteCount===1?"":"s")+" ("+e.toDisplayString(t.optionPercentages[o])+" percent). ",1),t.hasVotedForOption(o)?(e.openBlock(),e.createElementBlock("span",ue,"You selected this option.")):e.createCommentVNode("",!0)],64)):(e.openBlock(),e.createElementBlock(e.Fragment,{key:1},[e.createTextVNode(" Results are hidden until voting closes. ")],64))],8,pe)])])],2))),128))])],8,ee),e.createElementVNode("div",me,[t.canVote?(e.openBlock(),e.createElementBlock("button",{key:0,type:"submit",class:"coloeus-poll__vote-btn",disabled:!t.hasSelection||t.submitting},e.toDisplayString(t.submitting?"Voting...":"Vote"),9,_e)):e.createCommentVNode("",!0),e.createElementVNode("span",fe,e.toDisplayString(t.totalVotes)+" vote"+e.toDisplayString(t.totalVotes===1?"":"s")+" cast ",1),e.createElementVNode("div",{id:t.pollStatusId,class:"coloeus-poll__status-group",role:"status","aria-live":"polite"},[t.isActive?t.alreadyVoted?(e.openBlock(),e.createElementBlock("span",ge," You voted ")):(e.openBlock(),e.createElementBlock("span",Ve," Voting open ")):(e.openBlock(),e.createElementBlock("span",ye," Voting closed ")),e.createElementVNode("span",be,e.toDisplayString(t.pollStatusMessage),1)],8,he)])],40,$),t.displayError?(e.openBlock(),e.createElementBlock("div",Ee,e.toDisplayString(t.displayError),1)):e.createCommentVNode("",!0)],64)):(e.openBlock(),e.createElementBlock("div",ke,"Failed to load poll"))])}const Ne=F(X,[["render",Se],["__file","/Users/philipp/Code/coloeus/frontend/components/src/components/ColoeusPolls.vue"]]),Oe=e.defineComponent({__name:"ColoeusEditor",props:{id:{type:String,required:!1}},emits:["saved","cancel","error"],setup(l,{expose:n,emit:c}){n();const t=l,d=c,_=e.computed(()=>!!t.id),s=e.ref(""),o=e.ref(["",""]),i=e.ref(""),a=e.ref(""),g=e.ref(!1),b=e.ref(!1),f=e.ref(null),N=e.computed(()=>!(!s.value.trim()||o.value.filter(p=>p.trim()).length<2));async function k(){if(t.id){g.value=!0,f.value=null;try{const r=await K(t.id);s.value=r.title,o.value=r.options.map(p=>p.text),i.value=r.startTime?S(r.startTime):"",a.value=r.endTime?S(r.endTime):""}catch(r){f.value=r instanceof Error?r.message:"Failed to load poll",d("error",f.value)}finally{g.value=!1}}}function S(r){const p=new Date(r),V=p.getTimezoneOffset();return new Date(p.getTime()-V*60*1e3).toISOString().slice(0,16)}function u(){o.value.length<20&&(o.value=[...o.value,""])}function h(r){o.value.length>2&&(o.value=o.value.filter((p,V)=>V!==r))}function B(r,p){const V=[...o.value];V[r]=p,o.value=V}async function O(){if(N.value){b.value=!0,f.value=null;try{const r=o.value.filter(p=>p.trim());if(_.value&&t.id){const p={title:s.value.trim(),startTime:i.value?new Date(i.value).toISOString():null,endTime:a.value?new Date(a.value).toISOString():null},V=await H(t.id,p);d("saved",V)}else{const p={title:s.value.trim(),options:r,startTime:i.value?new Date(i.value).toISOString():void 0,endTime:a.value?new Date(a.value).toISOString():void 0},V=await G(p);d("saved",V)}}catch(r){f.value=r instanceof Error?r.message:"Failed to save poll",d("error",f.value)}finally{b.value=!1}}}function w(){d("cancel")}e.onMounted(()=>{t.id&&k()}),e.watch(()=>t.id,r=>{r?k():(s.value="",o.value=["",""],i.value="",a.value="",f.value=null)});const T={props:t,emit:d,isEditMode:_,title:s,options:o,startTime:i,endTime:a,loading:g,submitting:b,error:f,canSubmit:N,loadPoll:k,formatDateTimeLocal:S,addOption:u,removeOption:h,updateOption:B,handleSubmit:O,handleCancel:w};return Object.defineProperty(T,"__isScriptSetup",{enumerable:!1,value:!0}),T}}),Ce={class:"coloeus-editor"},Be={class:"coloeus-editor__title"},Te={key:0,class:"coloeus-poll__loading"},we={class:"coloeus-editor__field"},ve={class:"coloeus-editor__field"},Pe={class:"coloeus-editor__options"},De=["value","placeholder","disabled","onInput"],Ie=["onClick"],Me={class:"coloeus-editor__field"},Ae={class:"coloeus-editor__field"},Le={class:"coloeus-editor__actions"},Fe=["disabled"],Ue={key:0,class:"coloeus-editor__error"};function je(l,n,c,t,d,_){return e.openBlock(),e.createElementBlock("div",Ce,[e.createElementVNode("h3",Be,e.toDisplayString(t.isEditMode?"Edit Poll":"Create Poll"),1),t.loading?(e.openBlock(),e.createElementBlock("div",Te,"Loading...")):(e.openBlock(),e.createElementBlock("form",{key:1,onSubmit:e.withModifiers(t.handleSubmit,["prevent"])},[e.createElementVNode("div",we,[n[3]||(n[3]=e.createElementVNode("label",{class:"coloeus-editor__label",for:"poll-title"},"Title",-1)),e.withDirectives(e.createElementVNode("input",{id:"poll-title","onUpdate:modelValue":n[0]||(n[0]=s=>t.title=s),type:"text",class:"coloeus-editor__input",placeholder:"Enter poll title",maxlength:"500",required:""},null,512),[[e.vModelText,t.title]])]),e.createElementVNode("div",ve,[n[4]||(n[4]=e.createElementVNode("label",{class:"coloeus-editor__label"},"Options",-1)),e.createElementVNode("ul",Pe,[(e.openBlock(!0),e.createElementBlock(e.Fragment,null,e.renderList(t.options,(s,o)=>(e.openBlock(),e.createElementBlock("li",{key:o,class:"coloeus-editor__option"},[e.createElementVNode("input",{value:s,type:"text",class:"coloeus-editor__option-input",placeholder:`Option ${o+1}`,maxlength:"150",disabled:t.isEditMode,onInput:i=>t.updateOption(o,i.target.value)},null,40,De),t.options.length>2&&!t.isEditMode?(e.openBlock(),e.createElementBlock("button",{key:0,type:"button",class:"coloeus-editor__remove-btn",onClick:i=>t.removeOption(o)}," Remove ",8,Ie)):e.createCommentVNode("",!0)]))),128))]),t.options.length<20&&!t.isEditMode?(e.openBlock(),e.createElementBlock("button",{key:0,type:"button",class:"coloeus-editor__add-btn",onClick:t.addOption}," + Add Option ")):e.createCommentVNode("",!0)]),e.createElementVNode("div",Me,[n[5]||(n[5]=e.createElementVNode("label",{class:"coloeus-editor__label",for:"poll-start"},"Start Time (optional)",-1)),e.withDirectives(e.createElementVNode("input",{id:"poll-start","onUpdate:modelValue":n[1]||(n[1]=s=>t.startTime=s),type:"datetime-local",class:"coloeus-editor__input"},null,512),[[e.vModelText,t.startTime]])]),e.createElementVNode("div",Ae,[n[6]||(n[6]=e.createElementVNode("label",{class:"coloeus-editor__label",for:"poll-end"},"End Time (optional)",-1)),e.withDirectives(e.createElementVNode("input",{id:"poll-end","onUpdate:modelValue":n[2]||(n[2]=s=>t.endTime=s),type:"datetime-local",class:"coloeus-editor__input"},null,512),[[e.vModelText,t.endTime]])]),e.createElementVNode("div",Le,[e.createElementVNode("button",{type:"submit",class:"coloeus-editor__submit-btn",disabled:!t.canSubmit||t.submitting},e.toDisplayString(t.submitting?"Saving...":t.isEditMode?"Update Poll":"Create Poll"),9,Fe),e.createElementVNode("button",{type:"button",class:"coloeus-editor__cancel-btn",onClick:t.handleCancel}," Cancel ")]),t.error?(e.openBlock(),e.createElementBlock("div",Ue,e.toDisplayString(t.error),1)):e.createCommentVNode("",!0)],32))])}const ze=F(Oe,[["render",je],["__file","/Users/philipp/Code/coloeus/frontend/components/src/components/ColoeusEditor.vue"]]);y.ColoeusEditor=ze,y.ColoeusPolls=Ne,y.configureColoeus=R,y.getConfig=Y,y.useLocalStorage=A,y.usePoll=I,y.useVote=L,Object.defineProperty(y,Symbol.toStringTag,{value:"Module"})}));
|
|
1
|
+
(function(y,e){typeof exports=="object"&&typeof module<"u"?e(exports,require("vue")):typeof define=="function"&&define.amd?define(["exports","vue"],e):(y=typeof globalThis<"u"?globalThis:y||self,e(y.ColoeusComponents={},y.Vue))})(this,(function(y,e){"use strict";class A extends Error{constructor(o,c,t){super(c),this.status=o,this.data=t,this.name="ApiError"}}let V={apiUrl:""};function q(n){V={...V,...n}}function G(){return V}async function v(){const n={"Content-Type":"application/json"};if(V.getAuthToken){const o=await V.getAuthToken();o&&(n.Authorization=`Bearer ${o}`)}return n}async function T(n){if(!n.ok){const o=await n.json().catch(()=>({error:"Unknown error"}));throw new A(n.status,o.error||`HTTP error ${n.status}`,o.data)}return n.json()}async function H(n){const o=await fetch(`${V.apiUrl}/polls/${n}`,{method:"GET",headers:{"Content-Type":"application/json"}});return T(o)}async function K(n,o){if(o.length===0)throw new Error("At least one option must be selected");const c=await fetch(`${V.apiUrl}/polls/${n}/vote`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({optionIndices:o})});return T(c)}async function Q(n){const o=await v(),c=await fetch(`${V.apiUrl}/admin/polls`,{method:"POST",headers:o,body:JSON.stringify(n)});return T(c)}async function W(n,o){const c=await v(),t=await fetch(`${V.apiUrl}/admin/polls/${n}`,{method:"PUT",headers:c,body:JSON.stringify(o)});return T(t)}async function X(n){const o=await v(),c=await fetch(`${V.apiUrl}/admin/polls/${n}`,{method:"GET",headers:o});return T(c)}function L(n){const o=e.ref(null),c=e.ref(!0),t=e.ref(null),r=e.computed(()=>o.value?.totalVotes??0),p=e.computed(()=>o.value?.isActive??!1),s=e.computed(()=>!o.value||r.value===0?o.value?.options.map(()=>0)??[]:o.value.options.map(d=>Math.round(d.voteCount/r.value*100)));async function l(){c.value=!0,t.value=null;try{o.value=await H(n)}catch(d){t.value=d instanceof Error?d.message:"Failed to load poll",o.value=null}finally{c.value=!1}}function i(d){o.value=d}return e.onMounted(()=>{l()}),{poll:o,loading:c,error:t,totalVotes:r,isActive:p,optionPercentages:s,loadPoll:l,updatePoll:i}}const U="coloeus-votes";function Z(){try{const n=localStorage.getItem(U);return n?JSON.parse(n):{}}catch{return{}}}function I(n){try{localStorage.setItem(U,JSON.stringify(e.toRaw(n)))}catch{}}const b=e.reactive(Z());function x(){function n(p){return p in b}function o(p){const s=b[p];if(s==null)return[];const l=Array.isArray(s)?s:[s];return Array.from(new Set(l)).sort((i,d)=>i-d)}function c(p,s){const l=Array.isArray(s)?s:[s],i=Array.from(new Set(l)).sort((d,_)=>d-_);b[p]=i.length===1?i[0]:i,I(b)}function t(p){delete b[p],I(b)}function r(){for(const p of Object.keys(b))delete b[p];I(b)}return{votes:b,hasVoted:n,getVotedOptions:o,recordVote:c,clearVote:t,clearAllVotes:r}}const $=409;function F(n,o){const{hasVoted:c,getVotedOptions:t,recordVote:r}=x(),p=e.ref(!1),s=e.ref(null),l=e.ref([]),i=e.ref(1);o?.selectionLimit&&e.watch(o.selectionLimit,u=>{i.value=ee(u),l.value.length>i.value&&(l.value=l.value.slice(0,i.value))},{immediate:!0});const d=e.computed(()=>c(n)),_=e.computed(()=>t(n)),B=e.computed(()=>i.value>1),N=e.computed(()=>l.value.length>0);e.watch(_,u=>{d.value&&u.length&&(l.value=[...u])},{immediate:!0});function g(u){if(!d.value)if(k(),B.value){if(l.value.includes(u)){l.value=l.value.filter(m=>m!==u);return}if(l.value.length<i.value){l.value=[...l.value,u];return}s.value=`You can select up to ${i.value} options.`}else l.value=[u]}async function C(){if(!N.value)return s.value="Please select at least one option",null;if(d.value)return s.value="You have already voted on this poll",null;p.value=!0,s.value=null;const u=[...l.value].sort((m,S)=>m-S);try{const m=await K(n,u);return r(n,u),m.poll}catch(m){if(s.value=m instanceof Error?m.message:"Failed to submit vote",m instanceof A&&m.status===$){const S=m.data?.optionIndices;Array.isArray(S)?r(n,S):r(n,u)}return null}finally{p.value=!1}}function k(){s.value=null}return{submitting:p,error:s,selectedOptions:l,selectionLimit:i,isMultiSelect:B,hasSelection:N,alreadyVoted:d,votedOptionIndices:_,selectOption:g,submitVote:C,clearError:k}}function ee(n){return typeof n!="number"||!Number.isFinite(n)||n<=0?1:Math.max(1,Math.floor(n))}const te=e.defineComponent({__name:"ColoeusPolls",props:{id:{type:String,required:!0}},emits:["voted","error"],setup(n,{expose:o,emit:c}){o();const t=e.ref(!1),r=n,p=c,{poll:s,loading:l,error:i,totalVotes:d,isActive:_,optionPercentages:B,updatePoll:N}=L(r.id),g=e.computed(()=>{const h=s.value?.maxSelections;return typeof h=="number"&&h>0?Math.floor(h):1}),{submitting:C,error:k,selectedOptions:u,selectionLimit:m,isMultiSelect:S,hasSelection:M,alreadyVoted:O,votedOptionIndices:P,selectOption:D,submitVote:w,clearError:a}=F(r.id,{selectionLimit:g}),f=e.computed(()=>i.value||k.value),E=e.computed(()=>_.value&&!O.value),j=e.computed(()=>O.value||!_.value||t.value),Xe=e.computed(()=>`coloeus-poll-title-${r.id}`),Ze=e.computed(()=>`coloeus-poll-instructions-${r.id}`),$e=e.computed(()=>`coloeus-poll-status-${r.id}`),et=e.computed(()=>_.value?O.value?"You have already voted on this poll":"Voting is open":"Voting is closed"),tt=e.computed(()=>S.value?"checkbox":"radio"),ot=e.computed(()=>S.value?`Select up to ${m.value} options and submit your vote.`:"Select one option and submit your vote.");async function lt(){a();const h=await w();h?(N(h),p("voted",r.id,[...u.value])):k.value&&p("error",k.value)}function nt(h){E.value&&D(h)}function st(h){return`coloeus-poll-option-${r.id}-stats-${h}`}function z(h){return u.value.includes(h)}function Y(h){return P.value.includes(h)}function at(h){return z(h)||Y(h)}function it(){t.value=!0}const J={resultsRevealed:t,props:r,emit:p,poll:s,loading:l,pollError:i,totalVotes:d,isActive:_,optionPercentages:B,updatePoll:N,pollSelectionLimit:g,submitting:C,voteError:k,selectedOptions:u,selectionLimit:m,isMultiSelect:S,hasSelection:M,alreadyVoted:O,votedOptionIndices:P,selectOption:D,submitVote:w,clearError:a,displayError:f,canVote:E,showResults:j,pollTitleId:Xe,pollInstructionsId:Ze,pollStatusId:$e,pollStatusMessage:et,optionInputType:tt,selectionInstruction:ot,handleVote:lt,handleOptionSelect:nt,getOptionStatsId:st,isOptionCurrentlySelected:z,hasVotedForOption:Y,isOptionChecked:at,revealResults:it};return Object.defineProperty(J,"__isScriptSetup",{enumerable:!1,value:!0}),J}}),R=(n,o)=>{const c=n.__vccOpts||n;for(const[t,r]of o)c[t]=r;return c},oe={class:"coloeus-poll"},le={key:0,class:"coloeus-poll__loading"},ne=["aria-labelledby","aria-describedby"],se=["aria-describedby","aria-disabled"],ae=["id"],ie=["id"],re={key:0,class:"coloeus-poll__instructions-note"},ce={class:"coloeus-poll__options",role:"list"},de={class:"coloeus-poll__option-label"},pe=["type","name","value","checked","disabled","aria-describedby","onChange"],ue={class:"coloeus-poll__option-content"},me={class:"coloeus-poll__option-text"},_e={key:1,class:"coloeus-poll__option-stats","aria-hidden":"true"},fe={class:"coloeus-poll__option-percentage"},he=["id"],ye={key:0},ge={class:"coloeus-poll__footer"},Ee={class:"coloeus-poll__actions"},Ve=["disabled"],be={class:"coloeus-poll__total","aria-live":"polite"},ke=["id"],Se={key:0,class:"coloeus-poll__status coloeus-poll__status--inactive"},Ne={key:1,class:"coloeus-poll__status coloeus-poll__status--active"},Be={key:2,class:"coloeus-poll__status coloeus-poll__status--open"},Ce={class:"coloeus-poll__sr"},Oe={key:0,class:"coloeus-poll__error",role:"alert","aria-live":"assertive"},Te={key:2,class:"coloeus-poll__error"};function we(n,o,c,t,r,p){return e.openBlock(),e.createElementBlock("div",oe,[t.loading?(e.openBlock(),e.createElementBlock("div",le,"Loading poll...")):t.poll?(e.openBlock(),e.createElementBlock(e.Fragment,{key:1},[e.createElementVNode("form",{class:"coloeus-poll__form",role:"form","aria-labelledby":t.pollTitleId,"aria-describedby":`${t.pollInstructionsId} ${t.pollStatusId}`,onSubmit:e.withModifiers(t.handleVote,["prevent"])},[e.createElementVNode("fieldset",{class:"coloeus-poll__fieldset","aria-describedby":`${t.pollInstructionsId} ${t.pollStatusId}`,"aria-disabled":!t.canVote},[e.createElementVNode("legend",{id:t.pollTitleId,class:"coloeus-poll__title"},e.toDisplayString(t.poll.title),9,ae),e.createElementVNode("p",{id:t.pollInstructionsId,class:"coloeus-poll__instructions"},[e.createTextVNode(e.toDisplayString(t.selectionInstruction)+" ",1),t.canVote?e.createCommentVNode("",!0):(e.openBlock(),e.createElementBlock("span",re,e.toDisplayString(t.pollStatusMessage),1))],8,ie),e.createElementVNode("ul",ce,[(e.openBlock(!0),e.createElementBlock(e.Fragment,null,e.renderList(t.poll.options,(s,l)=>(e.openBlock(),e.createElementBlock("li",{key:l,class:e.normalizeClass(["coloeus-poll__option",{"coloeus-poll__option--selected":t.isOptionCurrentlySelected(l),"coloeus-poll__option--voted":t.hasVotedForOption(l),"coloeus-poll__option--disabled":!t.canVote}])},[e.createElementVNode("label",de,[e.createElementVNode("input",{type:t.optionInputType,class:"coloeus-poll__option-input",name:`coloeus-poll-${t.props.id}`,value:l,checked:t.isOptionChecked(l),disabled:!t.canVote,"aria-describedby":t.getOptionStatsId(l),onChange:i=>t.handleOptionSelect(l)},null,40,pe),e.createElementVNode("span",ue,[t.showResults?(e.openBlock(),e.createElementBlock("span",{key:0,class:"coloeus-poll__option-progress",style:e.normalizeStyle({width:`${t.optionPercentages[l]}%`}),"aria-hidden":"true"},null,4)):e.createCommentVNode("",!0),e.createElementVNode("span",me,e.toDisplayString(s.text),1),t.showResults?(e.openBlock(),e.createElementBlock("span",_e,[e.createElementVNode("span",fe,e.toDisplayString(t.optionPercentages[l])+"%",1),e.createElementVNode("span",null,"("+e.toDisplayString(s.voteCount)+")",1)])):e.createCommentVNode("",!0),e.createElementVNode("span",{id:t.getOptionStatsId(l),class:"coloeus-poll__sr"},[t.showResults?(e.openBlock(),e.createElementBlock(e.Fragment,{key:0},[e.createTextVNode(e.toDisplayString(s.voteCount)+" vote"+e.toDisplayString(s.voteCount===1?"":"s")+" ("+e.toDisplayString(t.optionPercentages[l])+" percent). ",1),t.hasVotedForOption(l)?(e.openBlock(),e.createElementBlock("span",ye,"You selected this option.")):e.createCommentVNode("",!0)],64)):(e.openBlock(),e.createElementBlock(e.Fragment,{key:1},[e.createTextVNode(" Results are hidden until voting closes. ")],64))],8,he)])])],2))),128))])],8,se),e.createElementVNode("div",ge,[e.createElementVNode("div",Ee,[t.canVote?(e.openBlock(),e.createElementBlock("button",{key:0,type:"submit",class:"coloeus-poll__vote-btn",disabled:!t.hasSelection||t.submitting},e.toDisplayString(t.submitting?"Voting...":"Vote"),9,Ve)):e.createCommentVNode("",!0),t.canVote&&!t.showResults?(e.openBlock(),e.createElementBlock("button",{key:1,type:"button",class:"coloeus-poll__results-btn",onClick:t.revealResults}," Show results ")):e.createCommentVNode("",!0)]),e.createElementVNode("span",be,e.toDisplayString(t.totalVotes)+" vote"+e.toDisplayString(t.totalVotes===1?"":"s")+" cast ",1),e.createElementVNode("div",{id:t.pollStatusId,class:"coloeus-poll__status-group",role:"status","aria-live":"polite"},[t.isActive?t.alreadyVoted?(e.openBlock(),e.createElementBlock("span",Ne," You voted ")):(e.openBlock(),e.createElementBlock("span",Be," Voting open ")):(e.openBlock(),e.createElementBlock("span",Se," Voting closed ")),e.createElementVNode("span",Ce,e.toDisplayString(t.pollStatusMessage),1)],8,ke)])],40,ne),t.displayError?(e.openBlock(),e.createElementBlock("div",Oe,e.toDisplayString(t.displayError),1)):e.createCommentVNode("",!0)],64)):(e.openBlock(),e.createElementBlock("div",Te,"Failed to load poll"))])}const Pe=R(te,[["render",we],["__file","/Users/philipp/Code/coloeus/frontend/components/src/components/ColoeusPolls.vue"]]),De=e.defineComponent({__name:"ColoeusEditor",props:{id:{type:String,required:!1}},emits:["saved","cancel","error"],setup(n,{expose:o,emit:c}){o();const t=n,r=c,p=e.computed(()=>!!t.id),s=e.ref(""),l=e.ref(["",""]),i=e.ref(1),d=e.ref(""),_=e.ref(""),B=e.ref(!1),N=e.ref(!1),g=e.ref(null),C=e.computed(()=>l.value.filter(a=>a.trim()).length||1);e.watch(C,a=>{i.value>a&&(i.value=a)});const k=e.computed(()=>{if(!s.value.trim())return!1;const a=l.value.filter(f=>f.trim());return!(a.length<2||i.value<1||i.value>a.length)});async function u(){if(t.id){B.value=!0,g.value=null;try{const a=await X(t.id);s.value=a.title,l.value=a.options.map(f=>f.text),i.value=a.maxSelections??1,d.value=a.startTime?m(a.startTime):"",_.value=a.endTime?m(a.endTime):""}catch(a){g.value=a instanceof Error?a.message:"Failed to load poll",r("error",g.value)}finally{B.value=!1}}}function m(a){const f=new Date(a),E=f.getTimezoneOffset();return new Date(f.getTime()-E*60*1e3).toISOString().slice(0,16)}function S(){l.value.length<20&&(l.value=[...l.value,""])}function M(a){l.value.length>2&&(l.value=l.value.filter((f,E)=>E!==a))}function O(a,f){const E=[...l.value];E[a]=f,l.value=E}async function P(){if(k.value){N.value=!0,g.value=null;try{const a=l.value.filter(f=>f.trim());if(p.value&&t.id){const f={title:s.value.trim(),startTime:d.value?new Date(d.value).toISOString():null,endTime:_.value?new Date(_.value).toISOString():null},E=await W(t.id,f);r("saved",E)}else{const f={title:s.value.trim(),options:a,maxSelections:i.value,startTime:d.value?new Date(d.value).toISOString():void 0,endTime:_.value?new Date(_.value).toISOString():void 0},E=await Q(f);r("saved",E)}}catch(a){g.value=a instanceof Error?a.message:"Failed to save poll",r("error",g.value)}finally{N.value=!1}}}function D(){r("cancel")}e.onMounted(()=>{t.id&&u()}),e.watch(()=>t.id,a=>{a?u():(s.value="",l.value=["",""],i.value=1,d.value="",_.value="",g.value=null)});const w={props:t,emit:r,isEditMode:p,title:s,options:l,maxSelections:i,startTime:d,endTime:_,loading:B,submitting:N,error:g,validOptionsCount:C,canSubmit:k,loadPoll:u,formatDateTimeLocal:m,addOption:S,removeOption:M,updateOption:O,handleSubmit:P,handleCancel:D};return Object.defineProperty(w,"__isScriptSetup",{enumerable:!1,value:!0}),w}}),ve={class:"coloeus-editor"},Ie={class:"coloeus-editor__title"},Me={key:0,class:"coloeus-poll__loading"},Ae={class:"coloeus-editor__field"},Le={class:"coloeus-editor__field"},Ue={class:"coloeus-editor__options"},xe=["value","placeholder","disabled","onInput"],Fe=["onClick"],Re={key:1,class:"coloeus-editor__max-selections"},je=["max"],ze={key:2,class:"coloeus-editor__max-selections-readonly"},Ye={class:"coloeus-editor__readonly-value"},Je={class:"coloeus-editor__field"},qe={class:"coloeus-editor__field"},Ge={class:"coloeus-editor__actions"},He=["disabled"],Ke={key:0,class:"coloeus-editor__error"};function Qe(n,o,c,t,r,p){return e.openBlock(),e.createElementBlock("div",ve,[e.createElementVNode("h3",Ie,e.toDisplayString(t.isEditMode?"Edit Poll":"Create Poll"),1),t.loading?(e.openBlock(),e.createElementBlock("div",Me,"Loading...")):(e.openBlock(),e.createElementBlock("form",{key:1,onSubmit:e.withModifiers(t.handleSubmit,["prevent"])},[e.createElementVNode("div",Ae,[o[4]||(o[4]=e.createElementVNode("label",{class:"coloeus-editor__label",for:"poll-title"},"Title",-1)),e.withDirectives(e.createElementVNode("input",{id:"poll-title","onUpdate:modelValue":o[0]||(o[0]=s=>t.title=s),type:"text",class:"coloeus-editor__input",placeholder:"Enter poll title",maxlength:"500",required:""},null,512),[[e.vModelText,t.title]])]),e.createElementVNode("div",Le,[o[8]||(o[8]=e.createElementVNode("label",{class:"coloeus-editor__label"},"Options",-1)),e.createElementVNode("ul",Ue,[(e.openBlock(!0),e.createElementBlock(e.Fragment,null,e.renderList(t.options,(s,l)=>(e.openBlock(),e.createElementBlock("li",{key:l,class:"coloeus-editor__option"},[e.createElementVNode("input",{value:s,type:"text",class:"coloeus-editor__option-input",placeholder:`Option ${l+1}`,maxlength:"150",disabled:t.isEditMode,onInput:i=>t.updateOption(l,i.target.value)},null,40,xe),t.options.length>2&&!t.isEditMode?(e.openBlock(),e.createElementBlock("button",{key:0,type:"button",class:"coloeus-editor__remove-btn",onClick:i=>t.removeOption(l)}," Remove ",8,Fe)):e.createCommentVNode("",!0)]))),128))]),t.options.length<20&&!t.isEditMode?(e.openBlock(),e.createElementBlock("button",{key:0,type:"button",class:"coloeus-editor__add-btn",onClick:t.addOption}," + Add Option ")):e.createCommentVNode("",!0),t.isEditMode?(e.openBlock(),e.createElementBlock("div",ze,[o[7]||(o[7]=e.createElementVNode("label",{class:"coloeus-editor__label"},"Max Selections",-1)),e.createElementVNode("span",Ye,e.toDisplayString(t.maxSelections),1)])):(e.openBlock(),e.createElementBlock("div",Re,[o[5]||(o[5]=e.createElementVNode("label",{class:"coloeus-editor__label",for:"poll-max-selections"}," Max Selections ",-1)),e.withDirectives(e.createElementVNode("input",{id:"poll-max-selections","onUpdate:modelValue":o[1]||(o[1]=s=>t.maxSelections=s),type:"number",class:"coloeus-editor__input coloeus-editor__input--small",min:"1",max:t.validOptionsCount},null,8,je),[[e.vModelText,t.maxSelections,void 0,{number:!0}]]),o[6]||(o[6]=e.createElementVNode("p",{class:"coloeus-editor__hint"}," Users can select up to this many options (1 = single choice) ",-1))]))]),e.createElementVNode("div",Je,[o[9]||(o[9]=e.createElementVNode("label",{class:"coloeus-editor__label",for:"poll-start"},"Start Time (optional)",-1)),e.withDirectives(e.createElementVNode("input",{id:"poll-start","onUpdate:modelValue":o[2]||(o[2]=s=>t.startTime=s),type:"datetime-local",class:"coloeus-editor__input"},null,512),[[e.vModelText,t.startTime]])]),e.createElementVNode("div",qe,[o[10]||(o[10]=e.createElementVNode("label",{class:"coloeus-editor__label",for:"poll-end"},"End Time (optional)",-1)),e.withDirectives(e.createElementVNode("input",{id:"poll-end","onUpdate:modelValue":o[3]||(o[3]=s=>t.endTime=s),type:"datetime-local",class:"coloeus-editor__input"},null,512),[[e.vModelText,t.endTime]])]),e.createElementVNode("div",Ge,[e.createElementVNode("button",{type:"submit",class:"coloeus-editor__submit-btn",disabled:!t.canSubmit||t.submitting},e.toDisplayString(t.submitting?"Saving...":t.isEditMode?"Update Poll":"Create Poll"),9,He),e.createElementVNode("button",{type:"button",class:"coloeus-editor__cancel-btn",onClick:t.handleCancel}," Cancel ")]),t.error?(e.openBlock(),e.createElementBlock("div",Ke,e.toDisplayString(t.error),1)):e.createCommentVNode("",!0)],32))])}const We=R(De,[["render",Qe],["__file","/Users/philipp/Code/coloeus/frontend/components/src/components/ColoeusEditor.vue"]]);y.ColoeusEditor=We,y.ColoeusPolls=Pe,y.configureColoeus=q,y.getConfig=G,y.useLocalStorage=x,y.usePoll=L,y.useVote=F,Object.defineProperty(y,Symbol.toStringTag,{value:"Module"})}));
|
|
@@ -3,7 +3,7 @@ interface VoteStorage {
|
|
|
3
3
|
[pollId: string]: VoteRecord;
|
|
4
4
|
}
|
|
5
5
|
export declare function useLocalStorage(): {
|
|
6
|
-
votes:
|
|
6
|
+
votes: VoteStorage;
|
|
7
7
|
hasVoted: (pollId: string) => boolean;
|
|
8
8
|
getVotedOptions: (pollId: string) => number[];
|
|
9
9
|
recordVote: (pollId: string, optionIndices: number | number[]) => void;
|
package/dist/services/api.d.ts
CHANGED
|
@@ -1,4 +1,9 @@
|
|
|
1
1
|
import type { PublicPoll, VoteResponse, CreatePollInput, UpdatePollInput, AdminPoll, ColoeusConfig } from "../types/index.js";
|
|
2
|
+
export declare class ApiError extends Error {
|
|
3
|
+
readonly status: number;
|
|
4
|
+
readonly data?: Record<string, unknown> | undefined;
|
|
5
|
+
constructor(status: number, message: string, data?: Record<string, unknown> | undefined);
|
|
6
|
+
}
|
|
2
7
|
export declare function configureColoeus(config: ColoeusConfig): void;
|
|
3
8
|
export declare function getConfig(): ColoeusConfig;
|
|
4
9
|
export declare function fetchPoll(pollId: string): Promise<PublicPoll>;
|