Files
wanderer/lib/wanderer_app_web/live/admin/admin_live.html.heex
T

349 lines
15 KiB
Plaintext

<main class="w-full h-full col-span-2 lg:col-span-1 p-4 pl-20 overflow-auto">
<div class="page-content">
<div class="container-fluid px-[0.625rem]">
<div class="grid grid-cols-1 pb-6">
<div class="md:flex items-center justify-between px-[2px]">
<h4 class="text-[18px] font-medium text-gray-800 mb-sm-0 grow dark:text-gray-100 mb-2 md:mb-0">
Administration
</h4>
<.link :if={@map_subscriptions_enabled?} phx-click="authorize">
<.icon
name="hero-key-solid"
class="w-6 h-6 text-gray-500 hover:text-gray-800 dark:text-gray-400 dark:hover:text-gray-100"
/>
</.link>
</div>
</div>
<div class="grid grid-cols-1 gap-6 md:grid-cols-2 2xl:grid-cols-4 pb-6">
<div :if={@restrict_maps_creation?} class="card dark:bg-zinc-800 dark:border-zinc-600">
<div class="card-body">
<.button class="mt-2" type="button" phx-click="create-map">
Create Map
</.button>
</div>
</div>
<div :if={@map_subscriptions_enabled?} class="card dark:bg-zinc-800 dark:border-zinc-600">
<div class="card-body">
<div class="col-span-6">
<span class="text-gray-400 dark:text-gray-400">Wanderer Balance</span>
<h4 class="my-4 font-medium text-gray-800 text-4xl dark:text-gray-100">
<span class="counter-value">
{@total_balance |> Number.to_human(units: ["", "K", "M", "B", "T", "P"])}
</span>
ISK
</h4>
</div>
</div>
</div>
<div :if={@map_subscriptions_enabled?} class="card dark:bg-zinc-800 dark:border-zinc-600">
<div class="card-body">
<div class="col-span-6">
<span class="text-gray-400 dark:text-gray-400">Update User Balance</span>
<.form :let={f} for={@form} phx-change="check-amount" phx-submit="update-balance">
<.live_select
field={f[:character_id]}
dropdown_extra_class="max-h-64 overflow-y-auto flex flex-row"
available_option_class="w-full"
debounce={250}
update_min_len={3}
options={@character_search_options}
placeholder="Search a character"
>
<:option :let={option}>
<.search_member_item option={option} />
</:option>
</.live_select>
<.live_select
field={f[:amount]}
update_min_len={0}
options={@amounts}
placeholder="Amount"
/>
<div class="modal-action">
<.button class="mt-2" type="submit">
Update Balance
</.button>
</div>
</.form>
</div>
</div>
</div>
<div class="card dark:bg-zinc-800 dark:border-zinc-600">
<div class="card-body">
<div class="col-span-6">
<span class="text-gray-400 dark:text-gray-400">Unlink Character</span>
<.form :let={f} for={@unlink_character_form} phx-submit="unlink-character">
<.live_select
field={f[:unlink_character_id]}
dropdown_extra_class="max-h-64 overflow-y-auto flex flex-row"
available_option_class="w-full"
debounce={250}
update_min_len={3}
options={@character_search_options}
placeholder="Search a character"
>
<:option :let={option}>
<.search_member_item option={option} />
</:option>
</.live_select>
<div class="modal-action">
<.button class="mt-2" type="submit">
Unlink
</.button>
</div>
</.form>
</div>
</div>
</div>
<div class="card dark:bg-zinc-800 dark:border-zinc-600">
<div class="card-body">
<span class="text-gray-400 dark:text-gray-400">EVE DB Data</span>
<.button
class="mt-2"
type="button"
phx-click="update-eve-db-data"
phx-disable-with="Updating EVE DB Data..."
>
Update EVE DB Data
</.button>
</div>
</div>
<div class="card dark:bg-zinc-800 dark:border-zinc-600">
<div class="card-body">
<div class="col-span-6">
<span class="text-gray-400 dark:text-gray-400">Invites</span>
<h4 class="my-4 font-medium text-gray-800 text-4xl dark:text-gray-100">
<.link class="btn mt-2 w-full btn-neutral rounded-none" patch={~p"/admin/invite"}>
<.icon name="hero-plus-solid" class="w-6 h-6" />
<h3 class="card-title text-center text-md">New Invite</h3>
</.link>
</h4>
<.table id="invites" rows={@invites} class="!max-h-[40vh] !overflow-y-auto">
<:col :let={invite} label="Link">
<div class="flex items-center">
<div class="w-[200px] no-wrap truncate">
{get_invite_link(@uri, invite.token)}
</div>
<.button
phx-hook="CopyToClipboard"
id="copy-to-clipboard"
class="copy-link btn btn-neutral rounded-none"
data-url={get_invite_link(@uri, invite.token)}
>
Copy
<div class="absolute w-[100px] !mr-[-170px] link-copied hidden">
Link copied
</div>
</.button>
</div>
</:col>
<:col :let={invite} label="Type">
{invite.type}
</:col>
<:col :let={invite} label="Valid Until">
<div>
<p class="mb-0 text-xs text-gray-600 dark:text-zinc-100 whitespace-nowrap">
<.local_time id={invite.id} at={invite.valid_until} />
</p>
</div>
</:col>
<:action :let={invite}>
<.button
phx-click="delete-invite"
phx-value-id={invite.id}
data={[confirm: "Please confirm to delete invite!"]}
class="hover:text-white"
>
<.icon name="hero-trash-solid" class="w-4 h-4" />
</.button>
</:action>
</.table>
</div>
</div>
</div>
<div class="card dark:bg-zinc-800 dark:border-zinc-600">
<div class="card-body">
<div class="col-span-6">
<span class="text-gray-400 dark:text-gray-400">Tracking Pools</span>
<.table
id="tracking_pools"
rows={@tracker_stats}
class="!max-h-[40vh] !overflow-y-auto"
>
<:col :let={stat} label="Pool">
<div class="w-[200px] no-wrap truncate">{stat.title}</div>
</:col>
<:col :let={stat} label="Active">
<div :if={stat.id == @active_tracking_pool}>true</div>
</:col>
<:col :let={stat} label="Count">
{stat.value}
</:col>
</.table>
</div>
</div>
</div>
</div>
<div :if={@map_subscriptions_enabled?} class="grid grid-cols-1 gap-4 lg:grid-cols-12">
<div class="col-span-12 2xl:col-span-5">
<div class="card dark:bg-zinc-800 dark:border-zinc-600">
<div class="nav-tabs border-b-tabs">
<div class="py-3">
<div class="px-3" data-simplebar="init">
<div class="simplebar-wrapper">
<div class="simplebar-height-auto-observer-wrapper">
<div class="simplebar-height-auto-observer"></div>
</div>
<div class="simplebar-mask">
<div class="simplebar-offset">
<div class="simplebar-content-wrapper">
<div class="simplebar-content" style="padding: 0px 12px;">
<.table
id="transactions"
rows={@transactions}
class="!max-h-[40vh] !overflow-y-auto"
>
<:col :let={transaction}>
<div class=" text-22">
<.icon name="hero-credit-card-solid" class="h-5 w-5" />
</div>
</:col>
<:col :let={transaction} label="Transaction">
<div>
<h5 class="mb-1 text-sm font-medium text-gray-700 dark:text-gray-100">
{transaction.reason_encoded}
</h5>
<p class="mb-0 text-xs text-gray-600 dark:text-zinc-100 whitespace-nowrap">
{transaction.date}
</p>
</div>
</:col>
<:col :let={transaction} label="Description">
{transaction.description}
</:col>
<:col :let={transaction} label="">
<div class="text-end">
<h5 class="mb-0 text-sm text-gray-500 dark:text-zinc-100">
{transaction.amount_encoded
|> Number.to_human(units: ["", "K", "M", "B", "T", "P"])}
</h5>
<p class="mb-0 text-xs text-gray-600 dark:text-zinc-100 whitespace-nowrap">
ISK
</p>
</div>
</:col>
</.table>
</div>
</div>
</div>
</div>
<div class="simplebar-placeholder"></div>
</div>
</div>
</div>
</div>
</div>
<div class="col-span-12 2xl:col-span-5 mt-6">
<div class="card dark:bg-zinc-800 dark:border-zinc-600">
<div class="nav-tabs border-b-tabs">
<div class="py-3">
<div class="px-3" data-simplebar="init">
<div class="simplebar-wrapper">
<div class="simplebar-height-auto-observer-wrapper">
<div class="simplebar-height-auto-observer"></div>
</div>
<div class="simplebar-mask">
<div class="simplebar-offset">
<div class="simplebar-content-wrapper">
<div class="simplebar-content" style="padding: 0px 12px;">
<.table
id="transactions"
rows={@active_map_subscriptions}
class="!max-h-[40vh] !overflow-y-auto"
>
<:col :let={subscription}>
<div class=" text-22">
<.icon name="hero-check-badge-solid" class="w-5 h-5" />
</div>
</:col>
<:col :let={subscription} label="Map">
{subscription.map.name}
</:col>
<:col :let={subscription} label="Active Till">
<.local_time
:if={subscription.active_till}
id={"subscription-active-till-#{subscription.id}"}
at={subscription.active_till}
>
{subscription.active_till}
</.local_time>
</:col>
<:col :let={subscription} label="Characters Limit">
{subscription.characters_limit}
</:col>
<:col :let={subscription} label="Hubs Limit">
{subscription.hubs_limit}
</:col>
<:col :let={subscription} label="Auto Renew">
{if subscription.auto_renew?, do: "Yes", else: "No"}
</:col>
</.table>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
<.modal
:if={@live_action in [:add_invite_link]}
title="New Invite"
class="!w-[500px]"
id="add_invite_link_modal"
show
on_cancel={JS.patch(~p"/admin")}
>
<.form :let={f} for={@form} phx-change="validate" phx-submit={@live_action}>
<.input
type="select"
field={f[:type]}
class="select h-8 min-h-[10px] !pt-1 !pb-1 text-sm bg-neutral-900"
wrapper_class="mt-2"
label="Type"
options={
Enum.map(@invite_types, fn invite_type -> {invite_type.label, invite_type.id} end)
}
/>
<.input
type="select"
field={f[:valid_until]}
class="select h-8 min-h-[10px] !pt-1 !pb-1 text-sm bg-neutral-900"
wrapper_class="mt-2"
label="Valid"
options={Enum.map(@valid_types, fn valid_type -> {valid_type.label, valid_type.id} end)}
/>
<!-- API Key Section with grid layout -->
<div class="modal-action">
<.button class="mt-2" type="submit" phx-disable-with="Saving...">
{(@live_action == :add_invite_link && "Add") || "Save"}
</.button>
</div>
</.form>
</.modal>
</main>