{% extends "layout.html" %}
{% import "card.html" as card %}
{% import "icons.html" as icons %}
{% block content %}
<div class="container my-4">
<div class="mb-4 space-y-0.5">
<h2 id="title" class="text-2xl font-bold tracking-tight">
{{ team.name }}
</h2>
<p class="text-muted-foreground">
Manage and view your team. View
<a
hx-boost="true"
hx-select="#screen"
hx-target="#screen"
hx-swap="outerHTML"
href="/team/{{ team.id }}"
class="underline"
>public profile</a
>.
</p>
</div>
<div class="grid lg:grid-cols-2 gap-6">
<div class="flex flex-col gap-6">
{% call card.root() %}
{% call card.header() %}
{% call card.title() %}
Members
{% endcall %}
{% call card.description() %}
Invite and view members on your team
{% endcall %}
{% endcall %}
{% call card.content() %}
{% with x=team_invite_url %}
{% endwith %}
<h4 class="text-sm">Invite Link</h4>
<p class="mb-2 text-sm text-muted-foreground">
Send this invite link to your team members
</p>
<div class="flex mb-4 gap-2">
{% include "team-token.html" %}
<button
class="px-4 py-2 border border-input bg-background hover:bg-accent hover:text-accent-foreground inline-flex items-center justify-center rounded-md text-sm font-medium whitespace-nowrap ring-offset-background transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50"
onclick="copyInviteTokenToClipboard()"
title="Copy invite token to clipboard"
>
{{ icons.copy() }}
</button>
{% if user.is_team_owner %}
<button
hx-post="/team/roll-token"
hx-target="#team-token"
hx-swap="outerHTML"
class="px-4 py-2 border border-input bg-background hover:bg-accent hover:text-accent-foreground inline-flex items-center justify-center rounded-md text-sm font-medium whitespace-nowrap ring-offset-background transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50"
title="Roll a new invite token"
>
{{ icons.roll() }}
</button>
{% endif %}
<script>
function copyInviteTokenToClipboard() {
navigator.clipboard
.writeText(document.querySelector("#team-token").value)
.then(
() => {
rhombus.toast.success(
"Copied invite token to clipboard",
);
},
() => {
rhombus.toast.error(
"Failed to copy invite token to clipboard",
);
},
);
}
</script>
</div>
{% with x=team, y=max_players, z=lang %}
{% endwith %}
{% include "team-members.html" %}
{% endcall %}
{% endcall %}
{% call card.root() %}
{% call card.header() %}
{% call card.title() %}
Standing
{% endcall %}
{% call card.description() %}
Your team's standing in the competition
{% endcall %}
{% endcall %}
{% call card.content() %}
{% with x=divisions, y=standings %}
{% endwith %}
{% include "standing-table.html" %}
{% endcall %}
{% endcall %}
{% call card.root() %}
{% call card.header() %}
{% call card.title() %}
Divisions
{% endcall %}
{% call card.description() %}
Join your team to eligible divisions
{% endcall %}
{% endcall %}
{% call card.content() %}
{% with a=divisions, b=user, c=num_joined_divisions, d=team %}
{% endwith %}
{% include "team-divisions.html" %}
{% endcall %}
{% endcall %}
{% if user.is_team_owner %}
{% call card.root() %}
{% call card.header() %}
{% call card.title() %}
Settings
{% endcall %}
{% call card.description() %}
Change settings about your team (owner only)
{% endcall %}
{% endcall %}
{% call card.content() %}
<h4 class="text-sm">Change name</h4>
<p class="text-sm text-muted-foreground mb-2">
Must be between 3 and 30 characters. May only be changed every
30 minutes.
</p>
<input
type="text"
name="name"
value="{{ team.name }}"
class="bg-background border p-2 rounded-md w-full focus-visible:outline-none"
hx-post="/team/name"
hx-target="next"
/>
<div></div>
{% endcall %}
{% endcall %}
{% endif %}
</div>
<div>
{% call card.root() %}
{% call card.header() %}
{% call card.title() %}
Solves
{% endcall %}
{% call card.description() %}
Challenges your team has solved
{% endcall %}
{% endcall %}
{% call card.content() %}
{% with x=lang %}
{% endwith %}
{% if team.solves | length > 0 %}
<ol class="flex flex-col gap-2">
{% for challenge_id, solve in team.solves | dictsort(by="value", reverse=true) %}
{% with challenge=challenges[challenge_id], solver=team.users[solve.user_id], category=categories[challenge.category_id] %}
<li class="flex items-center justify-between">
<div>
<a
hx-boost="true"
hx-select="#screen"
hx-target="#screen"
hx-swap="outerHTML"
href="/challenges#{{ challenge.name }}"
class="font-bold"
title="Go to challenge"
>
<span style="color: {{ category.color }}"
>{{ category.name }} /
</span>
{{ challenge.name }}
</a>
<span class="text-muted-foreground">
/ {{ challenge.division_points[0].points }} points /
<span title="{{ solve.solved_at }}">
{% with diff=timediff(solve.solved_at, now) %}
{{ t("time-difference", years=diff.years, days=diff.days, hours=diff.hours, minutes=diff.minutes, seconds=diff.seconds) }}
{%- endwith -%}
</span>
</span>
</div>
<a
hx-boost="true"
hx-select="#screen"
hx-target="#screen"
hx-swap="outerHTML"
href="/user/{{ solve.user_id }}"
class="flex items-center gap-2"
title="Go to public user profile"
>
<span>{{ solver.name }}</span>
<img
class="size-8 rounded-full"
src="{{ solver.avatar_url }}"
/>
</a>
</li>
{% endwith %}
{% endfor %}
</ol>
{% else %}
<p>Your team has not solved any challenges yet!</p>
{% endif %}
{% endcall %}
{% endcall %}
</div>
</div>
</div>
<script>
document.addEventListener("DOMContentLoaded", () => {
document
.querySelectorAll('input[type="checkbox"][unchecked]')
.forEach((el) => {
el.checked = false;
});
document
.querySelectorAll('input[type="checkbox"][checked]')
.forEach((el) => {
el.checked = true;
});
});
</script>
{% endblock %}