diff src/account.html.luan @ 0:8f4df159f06b

start public repo
author Franklin Schmidt <fschmidt@gmail.com>
date Fri, 11 Jul 2025 20:57:49 -0600
parents
children
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/account.html.luan	Fri Jul 11 20:57:49 2025 -0600
@@ -0,0 +1,250 @@
+local Luan = require "luan:Luan.luan"
+local error = Luan.error
+local Html = require "luan:Html.luan"
+local html_encode = Html.encode or error()
+local Io = require "luan:Io.luan"
+local Http = require "luan:http/Http.luan"
+local Shared = require "site:/lib/Shared.luan"
+local head = Shared.head or error()
+local body_header = Shared.body_header or error()
+local footer = Shared.footer or error()
+local show_user_icons = Shared.show_user_icons or error()
+local password_input = Shared.password_input or error()
+local User = require "site:/lib/User.luan"
+local Logging = require "luan:logging/Logging.luan"
+local logger = Logging.logger "account.html"
+
+
+return function()
+	local user = User.current_required()
+	if user==nil then return end
+	local title = user.title
+	local bio = user.bio
+	local username = user.name
+	local password = user.password
+	local email = user.email
+	local mp_id = user.mp_id
+	Io.stdout = Http.response.text_writer()
+%>
+<!doctype html>
+<html lang="en">
+	<head>
+<%		head() %>
+		<title>Link My Style</title>
+		<style>
+			h1 {
+				text-align: center;
+			}
+			div[body] {
+				max-width: 600px;
+				margin-left: auto;
+				margin-right: auto;
+			}
+			@media (max-width: 700px) {
+				div[body] {
+					max-width: 90%;
+				}
+			}
+			div[body] > * {
+				margin-bottom: 64px;
+			}
+			h2 {
+				margin-top: 20px;
+				margin-bottom: 20px !important;
+			}
+			label {
+				display: block;
+			}
+			div[field] {
+				margin-bottom: 10px;
+			}
+			button[delete1] {
+				background-color: red;
+			}
+			button[delete1]:hover,
+			button[delete2]:hover {
+				background-color: #7F1B1B;
+			}
+			div[delete2] {
+				display: none;
+			}
+
+			div[pic] {
+				display: flex;
+				margin-bottom: 20px;
+			}
+			div[pic] img {
+				width: 100px;
+				height: 100px;
+				object-fit: cover;
+				border-radius: 50%;
+				background-color: grey;
+				flex-shrink: 0;
+			}
+			div[pic] div {
+				width: 100%;
+				display: flex;
+				flex-direction: column;
+				align-items: center;
+				justify-content: space-around;
+			}
+			div[pic] button {
+				width: 90%;
+			}
+
+			div[icons] div[list] {
+				display: flex;
+				gap: 5px;
+				flex-wrap: wrap;
+				margin-bottom: 8px;
+			}
+			span[icon] {
+				border: 1px solid;
+				display: flex;
+				padding-right: 4px;
+			}
+			span[icon] img {
+				display: block;
+				height: 40px;
+			}
+			span[icon] > img {
+				opacity: 0.3;
+				touch-action: none;
+			}
+		</style>
+		<script>
+			'use strict';
+
+			function delete1() {
+				let delete2 = document.querySelector('div[delete2]');
+				delete2.style.display = 'block';
+				delete2.scrollIntoViewIfNeeded(false);
+			}
+			function undelete1() {
+				document.querySelector('div[delete2]').style.display = 'none';
+			}
+			function delete2() {
+				ajax( '/delete_user.js' );
+			}
+
+			function removePic() {
+				let img = document.querySelector('div[pic] img');
+				img.src = '/images/nothing.svg';
+				let pic_uuid = document.querySelector('input[name="pic_uuid"]');
+				pic_uuid.value = 'remove';
+			}
+			function uploaded(uuid,filename) {
+				document.querySelector('input[name="pic_uuid"]').value = uuid;
+				document.querySelector('input[name="pic_filename"]').value = filename;
+				let img = document.querySelector('div[pic] img');
+				img.src = uploadcareUrl(uuid);
+			}
+			function startUpload() {
+				uploadcare.cropprOptions = {aspectRatio: 1};
+				uploadcare.upload(uploaded);
+			}
+
+			dad.onDropped = function(event) {
+				let dragging = event.original;
+				if( iDragging === indexOf(dragging.parentNode.querySelectorAll(dropSelector),dragging) )
+					return;
+				let iconId = dragging.getAttribute('icon');
+				let prev = dragging.previousElementSibling;
+				let prevId = prev && prev.getAttribute('icon');
+				ajax( '/move_icon.js?icon='+iconId+'&prev='+prevId );
+			};
+			dad.whatToDrag = function(draggable) {
+				return draggable.parentNode;
+			};
+			function dragInit() {
+				dropSelector = 'span[icon]';
+				let items = document.querySelectorAll('span[icon] > img');
+				for( let i=0; i<items.length; i++ ) {
+					let item = items[i];
+					dad.setDraggable(item);
+					dad.setDropzone(item.parentNode);
+				}
+			}
+		</script>
+	</head>
+	<body>
+	<div full>
+<%		body_header() %>
+		<h1>My Account</h1>
+		<div body>
+			<form onsubmit="ajaxForm('/save_account.js',this)" action="javascript:">
+				<h2>My information</h2>
+				<div pic>
+					<img src="<%= user.get_pic_url() or "/images/nothing.svg" %>">
+					<div>
+						<input type=hidden name="pic_uuid">
+						<input type=hidden name="pic_filename">
+						<button type=button big onclick="startUpload()">Pick an image</button>
+						<button type=button big onclick="removePic()">Remove</button>
+					</div>
+				</div>
+				<label>Profile Title</label>
+				<div field>
+					<input type=text name=title value="<%= html_encode(title or username) %>">
+				</div>
+				<label>Profile Bio</label>
+				<div field>
+					<textarea name=bio><%= html_encode(bio or "") %></textarea>
+				</div>
+				<label>Username</label>
+				<div field>
+					<input type=text required name=username placeholder="Username" value="<%= username %>">
+					<div error=username></div>
+				</div>
+				<label>Password</label>
+				<div field>
+<%					password_input(password) %>
+				</div>
+				<button type=submit big>Save</button>
+				<div error=success></div>
+			</form>
+
+<%
+%>
+			<h2 icons>Social icons</h2>
+			<div icons>
+<%				show_user_icons(user) %>
+			</div>
+
+			<form onsubmit="ajaxForm('/save_email.js',this)" action="javascript:">
+				<h2>My email</h2>
+				<label>Email</label>
+				<div field>
+					<input type=email required name=email placeholder="Email" value="<%= email %>">
+					<div error=email></div>
+				</div>
+				<button type=submit big>Change</button>
+			</form>
+
+			<form onsubmit="ajaxForm('/save_mp.js',this)" action="javascript:">
+				<h2>Custom analytics</h2>
+				<label>Mixpanel Project Token</label>
+				<div field>
+					<input type=text name=mp_id value="<%= html_encode(mp_id or "") %>">
+				</div>
+				<button type=submit big>Save</button>
+				<div error=success></div>
+			</form>
+
+			<div>
+				<h2>Delete account</h2>
+				<button type=button delete1 big onclick="delete1()">Delete account</button>
+				<div delete2>
+					<p>Are you sure that you want to delete this account?</p>
+					<button type=button delete2 small onclick="delete2()">Yes</button>
+					<button type=button small onclick="undelete1()">No</button>
+				</div>
+			</div>
+		</div>
+<%		footer() %>
+	</div>
+	</body>
+	<script> dragInit(); </script>
+</html>
+<%
+end