comparison mrjunejune/src/notes/login.html @ 201:6cdee35a7ba9

[MrJuneJune] notes
author MrJuneJune <me@mrjunejune.com>
date Sun, 15 Feb 2026 07:07:50 -0800
parents
children
comparison
equal deleted inserted replaced
200:90dfcef375fb 201:6cdee35a7ba9
1 <!DOCTYPE html>
2 <html lang="en">
3 <head>
4 {{/parts/base_head.html}}
5 <title>Login | Notes</title>
6 <style>
7 .login-page {
8 max-width: 400px;
9 margin: 100px auto;
10 padding: 20px;
11 }
12 .login-box {
13 background: #fff;
14 border: 1px solid #ddd;
15 border-radius: 8px;
16 padding: 32px;
17 box-shadow: 0 2px 8px rgba(0,0,0,0.1);
18 }
19 .login-box h1 {
20 margin: 0 0 24px 0;
21 font-size: 24px;
22 text-align: center;
23 }
24 .login-box label {
25 display: block;
26 margin-bottom: 8px;
27 font-weight: 500;
28 }
29 .login-box input {
30 width: 100%;
31 padding: 12px;
32 border: 1px solid #ccc;
33 border-radius: 4px;
34 font-size: 16px;
35 box-sizing: border-box;
36 }
37 .login-box input:focus {
38 outline: none;
39 border-color: #0078ff;
40 }
41 .login-box button {
42 width: 100%;
43 padding: 12px;
44 margin-top: 16px;
45 background: #0078ff;
46 color: white;
47 border: none;
48 border-radius: 4px;
49 font-size: 16px;
50 cursor: pointer;
51 }
52 .login-box button:hover {
53 background: #0066dd;
54 }
55 .error-msg {
56 color: #d32f2f;
57 margin-top: 12px;
58 text-align: center;
59 display: none;
60 }
61 </style>
62 </head>
63 <body>
64 {{/parts/header.html}}
65
66 <main class="login-page">
67 <div class="login-box">
68 <h1>Notes Login</h1>
69 <form id="login-form">
70 <label for="token">Access Token</label>
71 <input type="password" id="token" placeholder="Enter your access token" required>
72 <button type="submit">Login</button>
73 <p class="error-msg" id="error-msg">Invalid token</p>
74 </form>
75 </div>
76 </main>
77
78 {{/parts/footer.html}}
79
80 <script>
81 // Check if already logged in
82 const savedToken = localStorage.getItem('notes-auth-token');
83 if (savedToken) {
84 window.location.href = '/notes/';
85 }
86
87 document.getElementById('login-form').addEventListener('submit', async function(e) {
88 e.preventDefault();
89
90 const token = document.getElementById('token').value.trim();
91 if (!token) return;
92
93 // Verify token by trying to load a document
94 try {
95 const response = await fetch('/api/editor/load/index', {
96 headers: { 'Authorization': 'Bearer ' + token }
97 });
98
99 if (response.ok) {
100 localStorage.setItem('notes-auth-token', token);
101 // Redirect to originally requested page or /notes/
102 const returnUrl = new URLSearchParams(window.location.search).get('return') || '/notes/';
103 window.location.href = returnUrl;
104 } else {
105 document.getElementById('error-msg').style.display = 'block';
106 }
107 } catch (err) {
108 document.getElementById('error-msg').style.display = 'block';
109 }
110 });
111 </script>
112 </body>
113 </html>