/ public / unsubscribe.html
unsubscribe.html
  1  <!doctype html>
  2  <html lang="en">
  3    <head>
  4      <meta charset="UTF-8" />
  5      <meta name="viewport" content="width=device-width, initial-scale=1.0" />
  6      <title>Unsubscribe - 333 Method</title>
  7      <style>
  8        * {
  9          margin: 0;
 10          padding: 0;
 11          box-sizing: border-box;
 12        }
 13  
 14        body {
 15          font-family:
 16            -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif;
 17          background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
 18          min-height: 100vh;
 19          display: flex;
 20          align-items: center;
 21          justify-content: center;
 22          padding: 20px;
 23          line-height: 1.6;
 24          color: #333;
 25        }
 26  
 27        .container {
 28          background: white;
 29          border-radius: 12px;
 30          box-shadow: 0 10px 40px rgba(0, 0, 0, 0.1);
 31          max-width: 500px;
 32          width: 100%;
 33          padding: 40px;
 34          text-align: center;
 35        }
 36  
 37        h1 {
 38          font-size: 28px;
 39          margin-bottom: 20px;
 40          color: #2d3748;
 41        }
 42  
 43        .status-icon {
 44          font-size: 64px;
 45          margin-bottom: 20px;
 46        }
 47  
 48        .loading {
 49          color: #667eea;
 50        }
 51  
 52        .success {
 53          color: #48bb78;
 54        }
 55  
 56        .error {
 57          color: #f56565;
 58        }
 59  
 60        p {
 61          font-size: 16px;
 62          color: #4a5568;
 63          margin-bottom: 15px;
 64        }
 65  
 66        .small-text {
 67          font-size: 14px;
 68          color: #718096;
 69          margin-top: 20px;
 70        }
 71  
 72        .spinner {
 73          border: 4px solid #f3f4f6;
 74          border-top: 4px solid #667eea;
 75          border-radius: 50%;
 76          width: 48px;
 77          height: 48px;
 78          animation: spin 1s linear infinite;
 79          margin: 20px auto;
 80        }
 81  
 82        @keyframes spin {
 83          0% {
 84            transform: rotate(0deg);
 85          }
 86          100% {
 87            transform: rotate(360deg);
 88          }
 89        }
 90  
 91        .button {
 92          display: inline-block;
 93          background: #667eea;
 94          color: white;
 95          padding: 12px 24px;
 96          border-radius: 6px;
 97          text-decoration: none;
 98          font-weight: 500;
 99          margin-top: 20px;
100          transition: background 0.2s;
101        }
102  
103        .button:hover {
104          background: #5a67d8;
105        }
106      </style>
107    </head>
108    <body>
109      <div class="container">
110        <div id="loading-state">
111          <div class="spinner"></div>
112          <h1>Processing your request...</h1>
113          <p>Please wait while we unsubscribe you from our emails.</p>
114        </div>
115  
116        <div id="success-state" style="display: none">
117          <div class="status-icon success">✓</div>
118          <h1>Successfully Unsubscribed</h1>
119          <p>You've been removed from our email list and won't receive any further emails from us.</p>
120          <p class="small-text">
121            If you received this email in error or change your mind, please contact us directly.
122          </p>
123        </div>
124  
125        <div id="error-state" style="display: none">
126          <div class="status-icon error">✕</div>
127          <h1>Something Went Wrong</h1>
128          <p id="error-message">
129            We couldn't process your unsubscribe request. The link may be invalid or expired.
130          </p>
131          <p class="small-text">
132            If you continue to receive emails, please contact us directly for assistance.
133          </p>
134        </div>
135      </div>
136  
137      <script>
138        // Get URL parameters
139        const params = new URLSearchParams(window.location.search);
140        const id = params.get('id');
141        const token = params.get('token');
142  
143        // Cloudflare Worker endpoint (update with your actual Worker URL)
144        const WORKER_URL = 'https://unsubscribe.auditandfix.workers.dev';
145  
146        // Show appropriate state
147        function showState(state, errorMsg = null) {
148          document.getElementById('loading-state').style.display = 'none';
149          document.getElementById('success-state').style.display = 'none';
150          document.getElementById('error-state').style.display = 'none';
151  
152          if (state === 'success') {
153            document.getElementById('success-state').style.display = 'block';
154          } else if (state === 'error') {
155            if (errorMsg) {
156              document.getElementById('error-message').textContent = errorMsg;
157            }
158            document.getElementById('error-state').style.display = 'block';
159          }
160        }
161  
162        // Validate parameters
163        if (!id || !token) {
164          showState(
165            'error',
166            'Invalid unsubscribe link. The link appears to be incomplete or malformed.'
167          );
168        } else {
169          // Send unsubscribe request
170          fetch(WORKER_URL, {
171            method: 'POST',
172            headers: {
173              'Content-Type': 'application/json',
174            },
175            body: JSON.stringify({ id, token }),
176          })
177            .then(response => response.json())
178            .then(data => {
179              if (data.success) {
180                showState('success');
181              } else {
182                showState('error', data.error || 'Unable to process unsubscribe request.');
183              }
184            })
185            .catch(error => {
186              console.error('Error:', error);
187              showState('error', 'Network error. Please check your connection and try again.');
188            });
189        }
190      </script>
191    </body>
192  </html>