Navbar.svelte 20 KB
Newer Older
Timothy J. Baek's avatar
Timothy J. Baek committed
1
<script lang="ts">
2
3
	import { goto } from '$app/navigation';
	import { user } from '$lib/stores';
4
5
	import { onMount } from 'svelte';

Timothy J. Baek's avatar
Timothy J. Baek committed
6
7
	let show = false;
	let navElement;
8
9
	let importFileInputElement;
	let importFiles;
10

Timothy J. Baek's avatar
Timothy J. Baek committed
11
	export let selectedChatId = '';
12
13
14
15
16
	export let title: string = 'Ollama Web UI';
	export let chats = [];

	export let createNewChat: Function;
	export let loadChat: Function;
Timothy J. Baek's avatar
Timothy J. Baek committed
17
18
	export let deleteChat: Function;
	export let editChatTitle: Function;
19
20
	export let importChatHistory: Function;
	export let exportChatHistory: Function;
21
	export let deleteChatHistory: Function;
Timothy J. Baek's avatar
Timothy J. Baek committed
22
	export let openSettings: Function;
23

Timothy J. Baek's avatar
Timothy J. Baek committed
24
25
26
	let chatTitleEditIdx = null;
	let chatTitle = '';

27
	let showDropdown = false;
Timothy J. Baek's avatar
Timothy J. Baek committed
28

29
	let _chats = chats.map((item, idx) => chats[chats.length - 1 - idx]);
30

Timothy J. Baek's avatar
Timothy J. Baek committed
31
32
33
34
	$: if (chats) {
		_chats = chats.map((item, idx) => chats[chats.length - 1 - idx]);
	}

35
36
37
38
39
40
41
42
43
44
45
46
	$: if (importFiles) {
		console.log(importFiles);

		let reader = new FileReader();
		reader.onload = (event) => {
			let chats = JSON.parse(event.target.result);
			console.log(chats);
			importChatHistory(chats);
		};

		reader.readAsText(importFiles[0]);
	}
Timothy J. Baek's avatar
Timothy J. Baek committed
47
48
49
</script>

<div
Timothy J. Baek's avatar
Timothy J. Baek committed
50
	class=" fixed top-0 flex flex-row justify-center bg-white/95 dark:bg-gray-800/90 dark:text-gray-200 backdrop-blur-xl w-full z-30"
Timothy J. Baek's avatar
Timothy J. Baek committed
51
>
Timothy J. Baek's avatar
Timothy J. Baek committed
52
	<div class="basis-full">
Timothy J. Baek's avatar
Timothy J. Baek committed
53
		<nav class="py-3" id="nav">
Timothy J. Baek's avatar
Timothy J. Baek committed
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
			<div class=" flex max-w-3xl mx-auto px-3">
				<div class="flex w-full max-w-full overflow-hidden text-ellipsis whitespace-nowrap">
					<div class="pr-2">
						<button
							class=" cursor-pointer p-1 flex dark:hover:bg-gray-700 rounded-lg transition"
							on:click={() => {
								createNewChat();
							}}
						>
							<div class=" m-auto self-center">
								<svg
									xmlns="http://www.w3.org/2000/svg"
									viewBox="0 0 20 20"
									fill="currentColor"
									class="w-5 h-5"
								>
									<path
										d="M5.433 13.917l1.262-3.155A4 4 0 017.58 9.42l6.92-6.918a2.121 2.121 0 013 3l-6.92 6.918c-.383.383-.84.685-1.343.886l-3.154 1.262a.5.5 0 01-.65-.65z"
									/>
									<path
										d="M3.5 5.75c0-.69.56-1.25 1.25-1.25H10A.75.75 0 0010 3H4.75A2.75 2.75 0 002 5.75v9.5A2.75 2.75 0 004.75 18h9.5A2.75 2.75 0 0017 15.25V10a.75.75 0 00-1.5 0v5.25c0 .69-.56 1.25-1.25 1.25h-9.5c-.69 0-1.25-.56-1.25-1.25v-9.5z"
									/>
								</svg>
							</div>
						</button>
					</div>
					<div
						class=" flex-1 self-center font-medium overflow-hidden text-ellipsis whitespace-nowrap w-[80vw] pr-4"
Timothy J. Baek's avatar
Timothy J. Baek committed
82
					>
Timothy J. Baek's avatar
Timothy J. Baek committed
83
84
						{title != '' ? title : 'Ollama Web UI'}
					</div>
Timothy J. Baek's avatar
Timothy J. Baek committed
85
86
87
88
89
90
91
92
93
94
				</div>
			</div>
		</nav>
	</div>
</div>

<div
	bind:this={navElement}
	class="h-screen {show
		? ''
Timothy J. Baek's avatar
Timothy J. Baek committed
95
		: '-translate-x-[260px]'} w-[260px] fixed top-0 left-0 z-40 transition bg-[#0a0a0a] text-gray-200 shadow-2xl text-sm
Timothy J. Baek's avatar
Timothy J. Baek committed
96
97
        "
>
Timothy J. Baek's avatar
Timothy J. Baek committed
98
99
	<div class="py-2.5 my-auto flex flex-col justify-between h-screen">
		<div class="px-2.5 flex justify-center space-x-2">
Timothy J. Baek's avatar
Timothy J. Baek committed
100
			<button
Timothy J. Baek's avatar
Timothy J. Baek committed
101
				class="flex-grow flex justify-between rounded-md px-3 py-1.5 my-2 hover:bg-gray-900 transition"
Timothy J. Baek's avatar
Timothy J. Baek committed
102
				on:click={() => {
103
					// goto('/');
104
					createNewChat();
Timothy J. Baek's avatar
Timothy J. Baek committed
105
106
				}}
			>
Timothy J. Baek's avatar
Timothy J. Baek committed
107
108
109
110
111
112
113
114
115
				<div class="flex self-center">
					<div class="self-center mr-3.5">
						<img src="/ollama.png" class=" w-5 invert-[100%] rounded-full" />
					</div>

					<div class=" self-center font-medium text-sm">New Chat</div>
				</div>

				<div class="self-center">
Timothy J. Baek's avatar
Timothy J. Baek committed
116
117
118
119
					<svg
						xmlns="http://www.w3.org/2000/svg"
						viewBox="0 0 20 20"
						fill="currentColor"
Timothy J. Baek's avatar
Timothy J. Baek committed
120
						class="w-4 h-4"
Timothy J. Baek's avatar
Timothy J. Baek committed
121
122
					>
						<path
Timothy J. Baek's avatar
Timothy J. Baek committed
123
124
125
126
							d="M5.433 13.917l1.262-3.155A4 4 0 017.58 9.42l6.92-6.918a2.121 2.121 0 013 3l-6.92 6.918c-.383.383-.84.685-1.343.886l-3.154 1.262a.5.5 0 01-.65-.65z"
						/>
						<path
							d="M3.5 5.75c0-.69.56-1.25 1.25-1.25H10A.75.75 0 0010 3H4.75A2.75 2.75 0 002 5.75v9.5A2.75 2.75 0 004.75 18h9.5A2.75 2.75 0 0017 15.25V10a.75.75 0 00-1.5 0v5.25c0 .69-.56 1.25-1.25 1.25h-9.5c-.69 0-1.25-.56-1.25-1.25v-9.5z"
Timothy J. Baek's avatar
Timothy J. Baek committed
127
128
129
130
131
						/>
					</svg>
				</div>
			</button>

Timothy J. Baek's avatar
Timothy J. Baek committed
132
133
			<!-- <button
				class=" cursor-pointer w-12 rounded-md flex"
Timothy J. Baek's avatar
Timothy J. Baek committed
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
				on:click={() => {
					show = !show;
				}}
			>
				<div class=" m-auto self-center">
					<svg
						xmlns="http://www.w3.org/2000/svg"
						viewBox="0 0 20 20"
						fill="currentColor"
						class="w-5 h-5"
					>
						<path
							fill-rule="evenodd"
							d="M3 4.25A2.25 2.25 0 015.25 2h5.5A2.25 2.25 0 0113 4.25v2a.75.75 0 01-1.5 0v-2a.75.75 0 00-.75-.75h-5.5a.75.75 0 00-.75.75v11.5c0 .414.336.75.75.75h5.5a.75.75 0 00.75-.75v-2a.75.75 0 011.5 0v2A2.25 2.25 0 0110.75 18h-5.5A2.25 2.25 0 013 15.75V4.25z"
							clip-rule="evenodd"
						/>
						<path
							fill-rule="evenodd"
							d="M19 10a.75.75 0 00-.75-.75H8.704l1.048-.943a.75.75 0 10-1.004-1.114l-2.5 2.25a.75.75 0 000 1.114l2.5 2.25a.75.75 0 101.004-1.114l-1.048-.943h9.546A.75.75 0 0019 10z"
							clip-rule="evenodd"
						/>
					</svg>
				</div>
Timothy J. Baek's avatar
Timothy J. Baek committed
157
			</button> -->
Timothy J. Baek's avatar
Timothy J. Baek committed
158
159
		</div>

Timothy J. Baek's avatar
Timothy J. Baek committed
160
161
162
163
		<div class="pl-2.5 my-3 flex-1 flex flex-col space-y-1 overflow-y-auto">
			{#each _chats as chat, i}
				<div class=" w-full pr-2 relative">
					<button
Timothy J. Baek's avatar
Timothy J. Baek committed
164
						class=" w-full flex justify-between rounded-md px-3 py-2 hover:bg-gray-900 {chat.id ===
Timothy J. Baek's avatar
Timothy J. Baek committed
165
						selectedChatId
Timothy J. Baek's avatar
Timothy J. Baek committed
166
							? 'bg-gray-900'
Timothy J. Baek's avatar
Timothy J. Baek committed
167
168
							: ''} transition whitespace-nowrap text-ellipsis"
						on:click={() => {
169
							// goto(`/c/${chat.id}`);
Timothy J. Baek's avatar
Timothy J. Baek committed
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
							if (chat.id !== chatTitleEditIdx) {
								chatTitleEditIdx = null;
								chatTitle = '';
							}

							loadChat(chat.id);
						}}
					>
						<div class=" flex self-center flex-1">
							<div class=" self-center mr-3">
								<svg
									xmlns="http://www.w3.org/2000/svg"
									fill="none"
									viewBox="0 0 24 24"
									stroke-width="1.5"
									stroke="currentColor"
									class="w-4 h-4"
								>
									<path
										stroke-linecap="round"
										stroke-linejoin="round"
										d="M2.25 12.76c0 1.6 1.123 2.994 2.707 3.227 1.087.16 2.185.283 3.293.369V21l4.076-4.076a1.526 1.526 0 011.037-.443 48.282 48.282 0 005.68-.494c1.584-.233 2.707-1.626 2.707-3.228V6.741c0-1.602-1.123-2.995-2.707-3.228A48.394 48.394 0 0012 3c-2.392 0-4.744.175-7.043.513C3.373 3.746 2.25 5.14 2.25 6.741v6.018z"
									/>
								</svg>
							</div>
							<div
								class=" text-left self-center overflow-hidden {chat.id === selectedChatId
Timothy J. Baek's avatar
Timothy J. Baek committed
197
198
									? 'w-[120px]'
									: 'w-[180px]'} "
Timothy J. Baek's avatar
Timothy J. Baek committed
199
200
201
202
203
204
205
206
207
208
209
							>
								{#if chatTitleEditIdx === chat.id}
									<input bind:value={chatTitle} class=" bg-transparent w-full" />
								{:else}
									{chat.title}
								{/if}
							</div>
						</div>
					</button>

					{#if chat.id === selectedChatId}
Timothy J. Baek's avatar
Timothy J. Baek committed
210
						<div class=" absolute right-[22px] top-[10px]">
Timothy J. Baek's avatar
Timothy J. Baek committed
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
							{#if chatTitleEditIdx === chat.id}
								<div class="flex self-center space-x-1.5">
									<button
										class=" self-center hover:text-white transition"
										on:click={() => {
											editChatTitle(chat.id, chatTitle);
											chatTitleEditIdx = null;
											chatTitle = '';
										}}
									>
										<svg
											xmlns="http://www.w3.org/2000/svg"
											viewBox="0 0 20 20"
											fill="currentColor"
											class="w-4 h-4"
										>
											<path
												fill-rule="evenodd"
												d="M16.704 4.153a.75.75 0 01.143 1.052l-8 10.5a.75.75 0 01-1.127.075l-4.5-4.5a.75.75 0 011.06-1.06l3.894 3.893 7.48-9.817a.75.75 0 011.05-.143z"
												clip-rule="evenodd"
											/>
										</svg>
									</button>
									<button
										class=" self-center hover:text-white transition"
										on:click={() => {
											chatTitleEditIdx = null;
											chatTitle = '';
										}}
									>
										<svg
											xmlns="http://www.w3.org/2000/svg"
											viewBox="0 0 20 20"
											fill="currentColor"
											class="w-4 h-4"
										>
											<path
												d="M6.28 5.22a.75.75 0 00-1.06 1.06L8.94 10l-3.72 3.72a.75.75 0 101.06 1.06L10 11.06l3.72 3.72a.75.75 0 101.06-1.06L11.06 10l3.72-3.72a.75.75 0 00-1.06-1.06L10 8.94 6.28 5.22z"
											/>
										</svg>
									</button>
								</div>
							{:else}
								<div class="flex self-center space-x-1.5">
									<button
										class=" self-center hover:text-white transition"
										on:click={() => {
											chatTitle = chat.title;
											chatTitleEditIdx = chat.id;
											// editChatTitle(chat.id, 'a');
										}}
									>
										<svg
											xmlns="http://www.w3.org/2000/svg"
											fill="none"
											viewBox="0 0 24 24"
											stroke-width="1.5"
											stroke="currentColor"
											class="w-4 h-4"
										>
											<path
												stroke-linecap="round"
												stroke-linejoin="round"
												d="M16.862 4.487l1.687-1.688a1.875 1.875 0 112.652 2.652L6.832 19.82a4.5 4.5 0 01-1.897 1.13l-2.685.8.8-2.685a4.5 4.5 0 011.13-1.897L16.863 4.487zm0 0L19.5 7.125"
											/>
										</svg>
									</button>
									<button
										class=" self-center hover:text-white transition"
										on:click={() => {
											deleteChat(chat.id);
										}}
									>
										<svg
											xmlns="http://www.w3.org/2000/svg"
											fill="none"
											viewBox="0 0 24 24"
											stroke-width="1.5"
											stroke="currentColor"
											class="w-4 h-4"
										>
											<path
												stroke-linecap="round"
												stroke-linejoin="round"
												d="M14.74 9l-.346 9m-4.788 0L9.26 9m9.968-3.21c.342.052.682.107 1.022.166m-1.022-.165L18.16 19.673a2.25 2.25 0 01-2.244 2.077H8.084a2.25 2.25 0 01-2.244-2.077L4.772 5.79m14.456 0a48.108 48.108 0 00-3.478-.397m-12 .562c.34-.059.68-.114 1.022-.165m0 0a48.11 48.11 0 013.478-.397m7.5 0v-.916c0-1.18-.91-2.164-2.09-2.201a51.964 51.964 0 00-3.32 0c-1.18.037-2.09 1.022-2.09 2.201v.916m7.5 0a48.667 48.667 0 00-7.5 0"
											/>
										</svg>
									</button>
								</div>
							{/if}
						</div>
					{/if}
				</div>
304
305
306
			{/each}
		</div>

Timothy J. Baek's avatar
Timothy J. Baek committed
307
		<div class="px-2.5">
Timothy J. Baek's avatar
Timothy J. Baek committed
308
			<hr class=" border-gray-800 mb-2 w-full" />
309
310

			<div class="flex flex-col">
311
312
313
				<div class="flex">
					<input bind:this={importFileInputElement} bind:files={importFiles} type="file" hidden />
					<button
Timothy J. Baek's avatar
Timothy J. Baek committed
314
						class=" flex rounded-md py-3 px-3.5 w-full hover:bg-gray-900 transition"
315
316
317
318
319
						on:click={() => {
							importFileInputElement.click();
							// importChatHistory();
						}}
					>
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
						<div class=" self-center mr-3">
							<svg
								xmlns="http://www.w3.org/2000/svg"
								fill="none"
								viewBox="0 0 24 24"
								stroke-width="1.5"
								stroke="currentColor"
								class="w-5 h-5"
							>
								<path
									stroke-linecap="round"
									stroke-linejoin="round"
									d="M19.5 14.25v-2.625a3.375 3.375 0 00-3.375-3.375h-1.5A1.125 1.125 0 0113.5 7.125v-1.5a3.375 3.375 0 00-3.375-3.375H8.25m6.75 12l-3-3m0 0l-3 3m3-3v6m-1.5-15H5.625c-.621 0-1.125.504-1.125 1.125v17.25c0 .621.504 1.125 1.125 1.125h12.75c.621 0 1.125-.504 1.125-1.125V11.25a9 9 0 00-9-9z"
								/>
							</svg>
						</div>
						<div class=" self-center">Import</div>
					</button>
338
					<button
Timothy J. Baek's avatar
Timothy J. Baek committed
339
						class=" flex rounded-md py-3 px-3.5 w-full hover:bg-gray-900 transition"
340
341
342
343
						on:click={() => {
							exportChatHistory();
						}}
					>
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
						<div class=" self-center mr-3">
							<svg
								xmlns="http://www.w3.org/2000/svg"
								fill="none"
								viewBox="0 0 24 24"
								stroke-width="1.5"
								stroke="currentColor"
								class="w-5 h-5"
							>
								<path
									stroke-linecap="round"
									stroke-linejoin="round"
									d="M19.5 14.25v-2.625a3.375 3.375 0 00-3.375-3.375h-1.5A1.125 1.125 0 0113.5 7.125v-1.5a3.375 3.375 0 00-3.375-3.375H8.25m.75 12l3 3m0 0l3-3m-3 3v-6m-1.5-9H5.625c-.621 0-1.125.504-1.125 1.125v17.25c0 .621.504 1.125 1.125 1.125h12.75c.621 0 1.125-.504 1.125-1.125V11.25a9 9 0 00-9-9z"
								/>
							</svg>
						</div>
						<div class=" self-center">Export</div>
					</button>
362
				</div>
363
				<button
Timothy J. Baek's avatar
Timothy J. Baek committed
364
					class=" flex rounded-md py-3 px-3.5 w-full hover:bg-gray-900 transition"
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
					on:click={() => {
						deleteChatHistory();
					}}
				>
					<div class=" self-center mr-3">
						<svg
							xmlns="http://www.w3.org/2000/svg"
							fill="none"
							viewBox="0 0 24 24"
							stroke-width="1.5"
							stroke="currentColor"
							class="w-5 h-5"
						>
							<path
								stroke-linecap="round"
								stroke-linejoin="round"
								d="M14.74 9l-.346 9m-4.788 0L9.26 9m9.968-3.21c.342.052.682.107 1.022.166m-1.022-.165L18.16 19.673a2.25 2.25 0 01-2.244 2.077H8.084a2.25 2.25 0 01-2.244-2.077L4.772 5.79m14.456 0a48.108 48.108 0 00-3.478-.397m-12 .562c.34-.059.68-.114 1.022-.165m0 0a48.11 48.11 0 013.478-.397m7.5 0v-.916c0-1.18-.91-2.164-2.09-2.201a51.964 51.964 0 00-3.32 0c-1.18.037-2.09 1.022-2.09 2.201v.916m7.5 0a48.667 48.667 0 00-7.5 0"
							/>
						</svg>
					</div>
					<div class=" self-center">Clear conversations</div>
				</button>
387
388
389
390

				{#if $user !== undefined}
					<button
						class=" flex rounded-md py-3 px-3.5 w-full hover:bg-gray-900 transition"
Timothy J. Baek's avatar
Timothy J. Baek committed
391
392
						on:click={() => {
							showDropdown = !showDropdown;
393
394
395
396
						}}
						on:focusout={() => {
							setTimeout(() => {
								showDropdown = false;
Timothy J. Baek's avatar
Timothy J. Baek committed
397
							}, 150);
398
399
400
						}}
					>
						<div class=" self-center mr-3">
Timothy J. Baek's avatar
Timothy J. Baek committed
401
402
403
404
405
							<img
								src={$user.profile_image_url}
								class=" max-w-[30px] object-cover rounded-full"
								alt="User profile"
							/>
406
407
408
409
410
411
412
						</div>
						<div class=" self-center font-semibold">{$user.name}</div>
					</button>

					{#if showDropdown}
						<div
							id="dropdownDots"
Timothy J. Baek's avatar
Timothy J. Baek committed
413
							class="absolute z-10 bottom-[70px] 4.5rem rounded-lg shadow w-[240px] bg-gray-900"
414
						>
415
							<div class="py-2 w-full">
Timothy J. Baek's avatar
Timothy J. Baek committed
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
								{#if $user.role === 'admin'}
									<button
										class="flex py-2.5 px-3.5 w-full hover:bg-gray-800 transition"
										on:click={() => {
											goto('/admin');
										}}
									>
										<div class=" self-center mr-3">
											<svg
												xmlns="http://www.w3.org/2000/svg"
												fill="none"
												viewBox="0 0 24 24"
												stroke-width="1.5"
												stroke="currentColor"
												class="w-5 h-5"
											>
												<path
													stroke-linecap="round"
													stroke-linejoin="round"
													d="M17.982 18.725A7.488 7.488 0 0012 15.75a7.488 7.488 0 00-5.982 2.975m11.963 0a9 9 0 10-11.963 0m11.963 0A8.966 8.966 0 0112 21a8.966 8.966 0 01-5.982-2.275M15 9.75a3 3 0 11-6 0 3 3 0 016 0z"
												/>
											</svg>
										</div>
										<div class=" self-center font-medium">Admin Panel</div>
									</button>
								{/if}

443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
								<button
									class="flex py-2.5 px-3.5 w-full hover:bg-gray-800 transition"
									on:click={() => {
										openSettings();
									}}
								>
									<div class=" self-center mr-3">
										<svg
											xmlns="http://www.w3.org/2000/svg"
											fill="none"
											viewBox="0 0 24 24"
											stroke-width="1.5"
											stroke="currentColor"
											class="w-5 h-5"
										>
											<path
												stroke-linecap="round"
												stroke-linejoin="round"
												d="M10.343 3.94c.09-.542.56-.94 1.11-.94h1.093c.55 0 1.02.398 1.11.94l.149.894c.07.424.384.764.78.93.398.164.855.142 1.205-.108l.737-.527a1.125 1.125 0 011.45.12l.773.774c.39.389.44 1.002.12 1.45l-.527.737c-.25.35-.272.806-.107 1.204.165.397.505.71.93.78l.893.15c.543.09.94.56.94 1.109v1.094c0 .55-.397 1.02-.94 1.11l-.893.149c-.425.07-.765.383-.93.78-.165.398-.143.854.107 1.204l.527.738c.32.447.269 1.06-.12 1.45l-.774.773a1.125 1.125 0 01-1.449.12l-.738-.527c-.35-.25-.806-.272-1.203-.107-.397.165-.71.505-.781.929l-.149.894c-.09.542-.56.94-1.11.94h-1.094c-.55 0-1.019-.398-1.11-.94l-.148-.894c-.071-.424-.384-.764-.781-.93-.398-.164-.854-.142-1.204.108l-.738.527c-.447.32-1.06.269-1.45-.12l-.773-.774a1.125 1.125 0 01-.12-1.45l.527-.737c.25-.35.273-.806.108-1.204-.165-.397-.505-.71-.93-.78l-.894-.15c-.542-.09-.94-.56-.94-1.109v-1.094c0-.55.398-1.02.94-1.11l.894-.149c.424-.07.765-.383.93-.78.165-.398.143-.854-.107-1.204l-.527-.738a1.125 1.125 0 01.12-1.45l.773-.773a1.125 1.125 0 011.45-.12l.737.527c.35.25.807.272 1.204.107.397-.165.71-.505.78-.929l.15-.894z"
											/>
											<path
												stroke-linecap="round"
												stroke-linejoin="round"
												d="M15 12a3 3 0 11-6 0 3 3 0 016 0z"
											/>
										</svg>
									</div>
									<div class=" self-center font-medium">Settings</div>
								</button>
							</div>

Timothy J. Baek's avatar
Timothy J. Baek committed
474
							<hr class=" border-gray-700 m-0 p-0" />
475
476
477
478
479
480

							<div class="py-2 w-full">
								<button
									class="flex py-2.5 px-3.5 w-full hover:bg-gray-800 transition"
									on:click={() => {
										localStorage.removeItem('token');
Timothy J. Baek's avatar
Timothy J. Baek committed
481
										location.href = '/auth';
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
									}}
								>
									<div class=" self-center mr-3">
										<svg
											xmlns="http://www.w3.org/2000/svg"
											viewBox="0 0 20 20"
											fill="currentColor"
											class="w-5 h-5"
										>
											<path
												fill-rule="evenodd"
												d="M3 4.25A2.25 2.25 0 015.25 2h5.5A2.25 2.25 0 0113 4.25v2a.75.75 0 01-1.5 0v-2a.75.75 0 00-.75-.75h-5.5a.75.75 0 00-.75.75v11.5c0 .414.336.75.75.75h5.5a.75.75 0 00.75-.75v-2a.75.75 0 011.5 0v2A2.25 2.25 0 0110.75 18h-5.5A2.25 2.25 0 013 15.75V4.25z"
												clip-rule="evenodd"
											/>
											<path
												fill-rule="evenodd"
												d="M6 10a.75.75 0 01.75-.75h9.546l-1.048-.943a.75.75 0 111.004-1.114l2.5 2.25a.75.75 0 010 1.114l-2.5 2.25a.75.75 0 11-1.004-1.114l1.048-.943H6.75A.75.75 0 016 10z"
												clip-rule="evenodd"
											/>
										</svg>
									</div>
									<div class=" self-center font-medium">Sign Out</div>
								</button>
							</div>
						</div>
					{/if}
				{:else}
					<button
						class=" flex rounded-md py-3 px-3.5 w-full hover:bg-gray-900 transition"
						on:click={() => {
							openSettings();
						}}
					>
						<div class=" self-center mr-3">
							<svg
								xmlns="http://www.w3.org/2000/svg"
								fill="none"
								viewBox="0 0 24 24"
								stroke-width="1.5"
								stroke="currentColor"
								class="w-5 h-5"
							>
								<path
									stroke-linecap="round"
									stroke-linejoin="round"
									d="M10.343 3.94c.09-.542.56-.94 1.11-.94h1.093c.55 0 1.02.398 1.11.94l.149.894c.07.424.384.764.78.93.398.164.855.142 1.205-.108l.737-.527a1.125 1.125 0 011.45.12l.773.774c.39.389.44 1.002.12 1.45l-.527.737c-.25.35-.272.806-.107 1.204.165.397.505.71.93.78l.893.15c.543.09.94.56.94 1.109v1.094c0 .55-.397 1.02-.94 1.11l-.893.149c-.425.07-.765.383-.93.78-.165.398-.143.854.107 1.204l.527.738c.32.447.269 1.06-.12 1.45l-.774.773a1.125 1.125 0 01-1.449.12l-.738-.527c-.35-.25-.806-.272-1.203-.107-.397.165-.71.505-.781.929l-.149.894c-.09.542-.56.94-1.11.94h-1.094c-.55 0-1.019-.398-1.11-.94l-.148-.894c-.071-.424-.384-.764-.781-.93-.398-.164-.854-.142-1.204.108l-.738.527c-.447.32-1.06.269-1.45-.12l-.773-.774a1.125 1.125 0 01-.12-1.45l.527-.737c.25-.35.273-.806.108-1.204-.165-.397-.505-.71-.93-.78l-.894-.15c-.542-.09-.94-.56-.94-1.109v-1.094c0-.55.398-1.02.94-1.11l.894-.149c.424-.07.765-.383.93-.78.165-.398.143-.854-.107-1.204l-.527-.738a1.125 1.125 0 01.12-1.45l.773-.773a1.125 1.125 0 011.45-.12l.737.527c.35.25.807.272 1.204.107.397-.165.71-.505.78-.929l.15-.894z"
								/>
								<path
									stroke-linecap="round"
									stroke-linejoin="round"
									d="M15 12a3 3 0 11-6 0 3 3 0 016 0z"
								/>
							</svg>
						</div>
						<div class=" self-center font-medium">Settings</div>
					</button>
				{/if}
539
			</div>
Timothy J. Baek's avatar
Timothy J. Baek committed
540
541
		</div>
	</div>
Timothy J. Baek's avatar
Timothy J. Baek committed
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570

	<div
		class="fixed left-0 top-[50dvh] z-40 -translate-y-1/2 transition-transform translate-x-[255px] md:translate-x-[260px] rotate-0"
	>
		<button
			class=" group"
			on:click={() => {
				show = !show;
			}}
			><span class="" data-state="closed"
				><div
					class="flex h-[72px] w-8 items-center justify-center opacity-20 group-hover:opacity-100 transition"
				>
					<div class="flex h-6 w-6 flex-col items-center">
						<div
							class="h-3 w-1 rounded-full bg-[#0f0f0f] dark:bg-white rotate-0 translate-y-[0.15rem] {show
								? 'group-hover:rotate-[15deg]'
								: 'group-hover:rotate-[-15deg]'}"
						/>
						<div
							class="h-3 w-1 rounded-full bg-[#0f0f0f] dark:bg-white rotate-0 translate-y-[-0.15rem] {show
								? 'group-hover:rotate-[-15deg]'
								: 'group-hover:rotate-[15deg]'}"
						/>
					</div>
				</div>
			</span>
		</button>
	</div>
Timothy J. Baek's avatar
Timothy J. Baek committed
571
</div>