1- const SUPABASE_URL = 'https://kvezyhwbkvpyndkaemsw.supabase.co' ;
2- const SUPABASE_ANON_KEY = 'sb_publishable_MWtbxI1_Gm_yYTSxHofq2Q_z0nGwItH' ;
3-
41const preregisterButton = document . getElementById ( 'google-preregister-button' ) ;
52const signOutButton = document . getElementById ( 'google-signout-button' ) ;
63const statusText = document . getElementById ( 'preregister-status' ) ;
74const resultBanner = document . getElementById ( 'preregister-result' ) ;
8- const preregisterSection = document . getElementById ( 'preregister' ) ;
95const preregisterModal = document . getElementById ( 'preregister-modal' ) ;
106const preregisterModalClose = document . getElementById ( 'preregister-modal-close' ) ;
117const watchModelInputs = Array . from ( document . querySelectorAll ( 'input[name="watch-model"]' ) ) ;
128const feedbackInput = document . getElementById ( 'preregister-feedback' ) ;
9+
1310const PREREG_DRAFT_KEY = 'clawwatch-preregister-draft' ;
1411const PREREG_PENDING_KEY = 'clawwatch-preregister-pending' ;
1512const XFOR_PREREGISTER_START_URL = 'https://xfor.bot/api/v1/clawwatch/start' ;
1613
17- let supabaseClient = null ;
1814let hasShownThankYou = false ;
1915
2016function showThankYouModal ( ) {
@@ -53,7 +49,7 @@ function clearBanner() {
5349function getFormState ( ) {
5450 return {
5551 watchModels : watchModelInputs . filter ( ( input ) => input . checked ) . map ( ( input ) => input . value ) ,
56- feedback : feedbackInput ?. value . trim ( ) || ''
52+ feedback : feedbackInput ?. value . trim ( ) || '' ,
5753 } ;
5854}
5955
@@ -89,35 +85,6 @@ function setPendingPreregistration(isPending) {
8985 } catch { }
9086}
9187
92- function hasPendingPreregistration ( ) {
93- try {
94- return window . localStorage . getItem ( PREREG_PENDING_KEY ) === '1' ;
95- } catch {
96- return false ;
97- }
98- }
99-
100- function buildSharedAuthRedirectUrl ( ) {
101- const { watchModels, feedback } = getFormState ( ) ;
102- const params = new URLSearchParams ( {
103- return_to : `${ window . location . origin } ${ window . location . pathname } ?preregister=complete#preregister` ,
104- watch_models : watchModels . join ( ',' ) ,
105- feedback
106- } ) ;
107- return `${ XFOR_PREREGISTER_START_URL } ?${ params . toString ( ) } ` ;
108- }
109-
110- function applyFormState ( metadata = { } ) {
111- const selected = Array . isArray ( metadata . clawwatch_watch_models ) ? metadata . clawwatch_watch_models : [ ] ;
112- const selectedSet = new Set ( selected ) ;
113- watchModelInputs . forEach ( ( input ) => {
114- input . checked = selectedSet . has ( input . value ) ;
115- } ) ;
116- if ( feedbackInput ) {
117- feedbackInput . value = typeof metadata . clawwatch_feedback === 'string' ? metadata . clawwatch_feedback : '' ;
118- }
119- }
120-
12188function applyDraftState ( draft = { } ) {
12289 const selected = Array . isArray ( draft . watchModels ) ? draft . watchModels : [ ] ;
12390 const selectedSet = new Set ( selected ) ;
@@ -129,7 +96,7 @@ function applyDraftState(draft = {}) {
12996 }
13097}
13198
132- function renderSignedOut ( ) {
99+ function renderReady ( ) {
133100 clearBanner ( ) ;
134101 if ( statusText ) {
135102 statusText . textContent = 'Sign in with Google and we will mark your account for the future install-ready ClawWatch release.' ;
@@ -157,148 +124,62 @@ function renderBusy(message) {
157124 }
158125}
159126
160- function renderRegistered ( user ) {
161- const email = user . email || 'your Google account' ;
162- if ( statusText ) {
163- statusText . textContent = `You are registered for ClawWatch install updates as ${ email } . You can update your watch details below any time.` ;
164- }
165- if ( preregisterButton ) {
166- preregisterButton . disabled = false ;
167- preregisterButton . innerHTML = '<span class="google-mark">✓</span><span>Update my interest details</span>' ;
168- }
169- if ( signOutButton ) {
170- signOutButton . hidden = false ;
171- }
172- setBanner ( "Thank you for your interest! We'll be back when the easy-to-install ClawWatch is here." , 'success' ) ;
173- }
174-
175- async function ensureInterest ( user , { showModal = false , forceUpdate = false } = { } ) {
176- const metadata = user . user_metadata || { } ;
177- if ( metadata . clawwatch_interest_at && ! forceUpdate ) {
178- applyFormState ( metadata ) ;
179- renderRegistered ( user ) ;
180- if ( showModal ) {
181- showThankYouModal ( ) ;
182- }
183- return ;
184- }
185- renderRegistered ( user ) ;
186- if ( showModal ) {
187- showThankYouModal ( ) ;
188- }
127+ function buildSharedAuthRedirectUrl ( ) {
128+ const { watchModels, feedback } = getFormState ( ) ;
129+ const params = new URLSearchParams ( {
130+ return_to : `${ window . location . origin } ${ window . location . pathname } ?preregister=complete#preregister` ,
131+ watch_models : watchModels . join ( ',' ) ,
132+ feedback,
133+ } ) ;
134+ return `${ XFOR_PREREGISTER_START_URL } ?${ params . toString ( ) } ` ;
189135}
190136
191- async function startGoogleSignIn ( ) {
192- clearBanner ( ) ;
137+ function startGoogleSignIn ( ) {
193138 renderBusy ( 'Redirecting to Google sign-in…' ) ;
194139 track ( 'clawwatch_preregister_start' ) ;
195140 saveDraftState ( ) ;
196141 setPendingPreregistration ( true ) ;
197142 window . location . assign ( buildSharedAuthRedirectUrl ( ) ) ;
198143}
199144
200- async function handlePreregisterAction ( ) {
201- const { data } = await supabaseClient . auth . getSession ( ) ;
202- if ( data . session ?. user ) {
203- await ensureInterest ( data . session . user , { showModal : true , forceUpdate : true } ) ;
204- return ;
205- }
206- await startGoogleSignIn ( ) ;
207- }
208-
209- async function signOut ( ) {
210- const { error } = await supabaseClient . auth . signOut ( ) ;
211- if ( error ) {
212- setBanner ( error . message , 'error' ) ;
213- return ;
214- }
215- renderSignedOut ( ) ;
216- }
217-
218- async function init ( ) {
219- const { createClient } = await import ( 'https://esm.sh/@supabase/supabase-js@2' ) ;
220- supabaseClient = createClient ( SUPABASE_URL , SUPABASE_ANON_KEY , {
221- auth : {
222- autoRefreshToken : true ,
223- detectSessionInUrl : true ,
224- persistSession : true ,
225- flowType : 'pkce'
226- }
227- } ) ;
228-
229- preregisterButton ?. addEventListener ( 'click' , handlePreregisterAction ) ;
230- signOutButton ?. addEventListener ( 'click' , signOut ) ;
145+ function init ( ) {
146+ preregisterButton ?. addEventListener ( 'click' , startGoogleSignIn ) ;
231147 preregisterModalClose ?. addEventListener ( 'click' , closeThankYouModal ) ;
232148 preregisterModal ?. addEventListener ( 'click' , ( event ) => {
233149 if ( event . target ?. dataset ?. closeModal === 'true' ) {
234150 closeThankYouModal ( ) ;
235151 }
236152 } ) ;
153+
237154 const savedDraft = loadDraftState ( ) ;
238155 if ( savedDraft ) {
239156 applyDraftState ( savedDraft ) ;
240157 }
241158
242- const { data, error } = await supabaseClient . auth . getSession ( ) ;
243- if ( error ) {
244- setBanner ( error . message , 'error' ) ;
245- return ;
246- }
247-
248- const preregComplete = new URLSearchParams ( window . location . search ) . get ( 'preregister' ) === 'complete' ;
249- const pendingPreregistration = hasPendingPreregistration ( ) ;
159+ const url = new URL ( window . location . href ) ;
160+ const preregStatus = url . searchParams . get ( 'preregister' ) ;
250161
251- if ( data . session ?. user ) {
252- applyFormState ( data . session . user . user_metadata || { } ) ;
253- if ( preregComplete || pendingPreregistration ) {
254- if ( savedDraft ) {
255- applyDraftState ( savedDraft ) ;
256- }
257- await ensureInterest ( data . session . user , {
258- showModal : true ,
259- forceUpdate : true
260- } ) ;
261- } else {
262- renderRegistered ( data . session . user ) ;
263- }
264- } else if ( preregComplete ) {
162+ if ( preregStatus === 'complete' ) {
265163 if ( savedDraft ) {
266164 applyDraftState ( savedDraft ) ;
267165 }
268166 clearDraftState ( ) ;
269167 setPendingPreregistration ( false ) ;
270- renderSignedOut ( ) ;
168+ renderReady ( ) ;
271169 setBanner ( "Thank you for your interest! We'll be back when the easy-to-install ClawWatch is here." , 'success' ) ;
272170 showThankYouModal ( ) ;
171+ } else if ( preregStatus === 'error' ) {
172+ renderReady ( ) ;
173+ setPendingPreregistration ( false ) ;
174+ setBanner ( 'Google sign-in finished, but ClawWatch preregistration was not stored. Please try again.' , 'error' ) ;
273175 } else {
274- renderSignedOut ( ) ;
176+ renderReady ( ) ;
275177 }
276178
277- if ( preregComplete ) {
179+ if ( preregStatus ) {
278180 const cleanUrl = `${ window . location . origin } ${ window . location . pathname } ${ window . location . hash || '' } ` ;
279181 window . history . replaceState ( { } , document . title , cleanUrl ) ;
280182 }
281-
282- supabaseClient . auth . onAuthStateChange ( async ( event , session ) => {
283- if ( event === 'SIGNED_IN' && session ?. user ) {
284- applyFormState ( session . user . user_metadata || { } ) ;
285- if ( hasPendingPreregistration ( ) ) {
286- const draft = loadDraftState ( ) ;
287- if ( draft ) {
288- applyDraftState ( draft ) ;
289- }
290- }
291- await ensureInterest ( session . user , { showModal : true , forceUpdate : hasPendingPreregistration ( ) } ) ;
292- return ;
293- }
294-
295- if ( event === 'SIGNED_OUT' ) {
296- renderSignedOut ( ) ;
297- }
298- } ) ;
299183}
300184
301- init ( ) . catch ( ( error ) => {
302- renderSignedOut ( ) ;
303- setBanner ( error . message || 'Failed to initialize preregistration.' , 'error' ) ;
304- } ) ;
185+ init ( ) ;
0 commit comments