User details page

Closes #46
This commit is contained in:
jaina heartles 2022-12-13 00:40:04 -08:00
parent d504cef8ff
commit a230a26151
3 changed files with 137 additions and 1 deletions

View File

@ -8,12 +8,13 @@ pub const routes = .{
controllers.apiEndpoint(about),
controllers.apiEndpoint(login),
controllers.apiEndpoint(global_timeline),
controllers.apiEndpoint(cluster.overview),
controllers.apiEndpoint(user_details),
controllers.apiEndpoint(media),
controllers.apiEndpoint(static),
controllers.apiEndpoint(signup.page),
controllers.apiEndpoint(signup.with_invite),
controllers.apiEndpoint(signup.submit),
controllers.apiEndpoint(cluster.overview),
controllers.apiEndpoint(cluster.communities.create.page),
controllers.apiEndpoint(cluster.communities.create.submit),
};
@ -210,6 +211,24 @@ const global_timeline = struct {
}
};
const user_details = struct {
pub const path = "/users/:id";
pub const method = .GET;
pub const tmpl = @embedFile("./web/user.tmpl.html");
pub const Args = struct {
id: util.Uuid,
};
pub fn handler(req: anytype, res: anytype, srv: anytype) !void {
const user = try srv.getUser(req.args.id);
defer util.deepFree(srv.allocator, user);
try res.template(.ok, srv, tmpl, user);
}
};
const cluster = struct {
const overview = struct {
pub const path = "/cluster/overview";

View File

@ -0,0 +1,33 @@
<div class="user-profile">
<header>
<img class="banner" src="{#if .header_url |$url|}{$url}{/if}" />
<div>
<div class="avatar">
<img src="{.avatar_url}" />
</div>
<div class="names">
<div class="display-name">{#if .display_name |$n|}{$n}{#else}{.username}{/if}</div>
<div class="handle">@{.username}@{.host}</div>
</div>
</div>
</header>
<div class="bio">
{.bio}
</div>
<div class="profile-fields">
{#for .profile_fields |$field| =}
<div class="field">
<div class="field-name">{$field.key}</div>
<div class="field-value">{$field.value}</div>
</div>
{/for =}
<div class="field">
<div class="field-name">Joined on</div>
<div class="field-value">{.created_at}</div>
</div>
</div>
</div>

View File

@ -134,3 +134,87 @@ button:hover, a.button:hover {
background-color: var(--theme-color-highlight);
}
.user-profile img.banner {
width: 100%;
height: 24em;
object-fit: cover;
/* TODO: Center this on the image focus */
}
.user-profile {
--avatar-size: 12em;
}
.user-profile .avatar {
margin-top: calc(var(--avatar-size) * -3/5);
margin-left: calc(var(--avatar-size) / 20);
}
.user-profile .avatar img {
width: var(--avatar-size);
height: var(--avatar-size);
}
.user-profile header > div {
display: flex;
position: relative;
z-index: 1;
flex-wrap: wrap;
}
.user-profile header .names {
margin: 1em;
}
.user-profile > div {
margin-left: calc(var(--avatar-size) * 3/5);
}
.user-profile .profile-fields .field {
display: grid;
grid-template-columns: 1fr 3fr;
text-align: center;
}
.user-profile .profile-fields .field .field-name { grid-column: 1; }
.user-profile .profile-fields .field .field-value { grid-column: 2; }
@media (max-width: 720px) {
.user-profile img.banner {
height: 18em;
}
.user-profile {
--avatar-size: 10em;
}
.user-profile .profile-fields .field {
grid-template-columns: 1fr 2fr;
}
}
@media (max-width: 480px) {
.user-profile img.banner {
height: 12em;
}
.user-profile header div {
}
.user-profile header div * {
flex-basis: 100%;
text-align: center;
}
.user-profile {
--avatar-size: 8em;
}
.user-profile .avatar {
margin-left: 0px;
}
.user-profile > div {
margin-left: 0px;
}
.user-profile .bio {
text-align: center;
}
.user-profile .profile-fields .field {
grid-template-columns: 2fr 3fr;
}
}