I made a best effort attempt to design the profile page according to the
current design specification.

Signed-off-by: André Jaenisch <andre.jaenisch@posteo.de>

Reviewed-on: https://codeberg.org/Anvil/Anvil/pulls/18
Co-authored-by: André Jaenisch <andre.jaenisch@posteo.de>
Co-committed-by: André Jaenisch <andre.jaenisch@posteo.de>
This commit is contained in:
André Jaenisch 2024-02-07 10:39:32 +00:00 committed by André Jaenisch
parent aea63c0b4b
commit 9bb86e84b1
5 changed files with 191 additions and 6 deletions

39
src/lib/server/ap.js Normal file
View file

@ -0,0 +1,39 @@
const loginResponse = {
id: '87bcb6de-bb70-11ee-b719-6756da82e80f',
username: 'hax0r',
acct: 'hax0r',
display_name: 'Jane Doe',
bot: false,
created_at: '2024-01-13T01:23:45.000Z',
note: '<p>Hackse for life</p>',
url: 'https://example.com/@hax0r',
avatar: 'https://avatars.example.com/hax0r',
role: { name: 'user' }
};
let username = loginResponse.username;
export const requests = {
get: (url) => {
if (url === '/profile') {
return Promise.resolve({
...loginResponse,
username
});
}
return Promise.reject(new Error('Unauthorized'));
},
post: (url, params) => {
if (url === '/login') {
username = params.account;
return Promise.resolve({
...loginResponse,
username: params.account
});
}
return Promise.reject(new Error('Invalid Login'));
}
};

View file

@ -0,0 +1,35 @@
import { fail, redirect } from '@sveltejs/kit';
import { requests } from '$lib/server/ap.js';
/** @type {import('./$types').Actions} */
export const actions = {
login: async ({ cookies, request, url }) => {
const formData = await request.formData();
const server = formData.get('server');
const account = formData.get('account');
const passphrase = formData.get('passphrase');
if (!account) {
return fail(400, { account, missing: true });
}
if (!passphrase) {
return fail(400, { account, incorrect: true });
}
try {
// TODO: Consumre response?
await requests.post('/login', { account, passphrase });
} catch (exc) {
console.error(exc);
return fail(400, { account, incorrect: true });
}
if (url.searchParams.has('redirectTo')) {
redirect(303, url.searchParams.get('redirectTo'));
}
redirect(303, '/profile');
}
};

View file

@ -1,11 +1,18 @@
<script>
/** @type {import('./$types').ActionData} */
export let form;
</script>
<div class="w-full max-w-md h-full mx-auto flex justify-center items-center py-10">
<div class="space-y-10">
<h1 class="h1 font-bold">Log in</h1>
<p>To use Anvil with your F2 account, fill in your credentials.</p>
<div class="space-y-4">
<form class="space-y-4" method="POST" action="?/login">
{#if form?.missing}<p class="error">The account field is required.</p>{/if}
{#if form?.incorrect}<p class="error">Account or password wrong.</p>{/if}
<label class="label">
<span>F2 server</span>
<select class="select" title="F2 server" value="1">
<select class="select" title="F2 server" name="server">
<option value="1">fig.fr33domlover.site</option>
<option value="2">grape.fr33domlover.site</option>
<option value="3">walnut.fr33domlover.site</option>
@ -13,16 +20,16 @@
</label>
<label class="label">
<span>Account name</span>
<input class="input" title="Account name" type="text" placeholder="alice" />
<input class="input" name="account" type="text" value={form?.account ?? ''} />
</label>
<label class="label">
<span>Passphrase</span>
<input class="input" title="Passphrase" type="password" placeholder="psswrd" />
<input class="input" name="passphrase" type="password" placeholder="password" />
</label>
<div class="text-right">
<a href="/" class="btn btn-bg-initial">Reset passphrase</a>
</div>
<a href="/" class="w-full btn variant-filled-primary">Log in</a>
</div>
<button type="submit" class="w-full btn variant-filled-primary"> Log in </button>
</form>
</div>
</div>

View file

@ -0,0 +1,19 @@
import { requests } from '$lib/server/ap.js';
/** @type {import('./$types').PageServerLoad} */
export async function load({ params }) {
const locale = 'en-US';
const profile = await requests.get('/profile');
return {
server: {
name: 'F2'
},
user: {
...profile,
created_at_formatted: new Intl.DateTimeFormat(locale).format(new Date(profile.created_at)),
created_with: 'Anvil',
instance: 'example.com'
}
};
}

View file

@ -0,0 +1,85 @@
<script>
import { Avatar } from '@skeletonlabs/skeleton';
/** @type {import('./$types').PageData} */
export let data;
</script>
<section class="w-full mx-auto flex px-8 pt-8">
<!-- Profile header -->
<div>
<Avatar
src={data.user.avatar}
width="w-32"
rounded="rounded-full"
initials={data.user.display_name}
/>
</div>
<!-- Board -->
<div class="flex flex-1 flex-col pl-8">
<div class="self-end">
<span
>created <date datetime={data.user.created_at}>{@html data.user.created_at_formatted}</date
></span
>
<button type="button" class="underline">block</button>
or
<button type="button" class="underline">report</button>
</div>
<!-- Top Row -->
<div class="flex mt-2">
<!-- Board -->
<div class="flex flex-col flex-1 gap-2">
<div class="flex items-end">
<h1 class="h1 font-semibold text-4xl leading-tight">
<span class="sr-only">Profile for </span>
{@html data.user.display_name}
</h1>
<p class="leading-normal my-1">(she/her)</p>
</div>
<span class="leading-tight">
{@html data.user.username}@{@html data.user.instance}
</span>
</div>
<!-- Interaction Links -->
<button type="button" class="btn-icon border rounded-none self-start"></button>
</div>
</div>
</section>
<section class="w-full h-full mx-auto flex mt-8 px-8">
<!-- Board -->
<div class="flex flex-1 flex-col px-4">
<div class="space-y-6">
<h2 class="h2 font-semibold leading-tight text-base px-4">Projects</h2>
<p class="px-4">
No projects added yet.
<a class="anchor" href="#">Add a project</a>
or
<a class="anchor" href="#">import a project</a>.
</p>
</div>
</div>
<!-- History -->
<div class="flex flex-1 flex-col px-4">
<div class="space-y-6">
<h2 class="h2 font-semibold leading-tight text-base">Activities</h2>
<ul>
<li class="flex flex-col border-l-2 ml-2">
<!-- Commit day -->
<span>
<!-- North Star in surface-900 -->
<span class="-ml-2 bg-[#0f161f]">✴️</span>
<span class="ml-4">Apr 23, 2023 - account set up</span>
</span>
<!-- Commits -->
<span class="ml-6 mt-8">
<span class="border box-decoration-clone px-4 py-2 leading-10">
The F2 account @{@html data.user.username}@{@html data.user.instance} was successfully
set up within {@html data.user.created_with}
</span>
</span>
</li>
</ul>
</div>
</div>
</section>