feat/admin: finished home page ui

This commit is contained in:
Kentai Radiquum 2025-02-18 16:56:55 +05:00
parent a80947d892
commit 5e3116d46f
Signed by: Radiquum
GPG key ID: 858E8EE696525EED
4 changed files with 406 additions and 14 deletions

View file

@ -13,6 +13,7 @@ import firebase_admin
from firebase_admin import firestore, credentials from firebase_admin import firestore, credentials
from firebase_admin import exceptions as FB_EXCEPTION from firebase_admin import exceptions as FB_EXCEPTION
from google.api_core import exceptions as GOOGLE_EXCEPTION from google.api_core import exceptions as GOOGLE_EXCEPTION
from datetime import datetime
load_dotenv() load_dotenv()
UPLOAD_FOLDER = "./temp" UPLOAD_FOLDER = "./temp"
@ -36,12 +37,33 @@ db = firestore.client()
@app.route("/") @app.route("/")
def Home(): def Home():
from urllib.request import urlopen objects = []
print(urlopen("https://www.howsmyssl.com/a/check").read()) tag = request.args.get('tag')
# objects = s3.list_objects(Bucket=os.getenv("AWS_BUCKET"))['Contents'] if tag:
# return render_template("Index.html", objects=objects) db_objects = (
return render_template("Index.html", page_title="Home") db.collection(os.getenv("PREFIX"))
.where("tags", "array_contains", tag)
.order_by("date", direction=firestore.Query.DESCENDING)
.stream()
)
else:
db_objects = (
db.collection(os.getenv("PREFIX"))
.order_by("date", direction=firestore.Query.DESCENDING)
.stream()
)
for object in db_objects:
name = object.id
img = f"{object.id.split(".")[0]}/{object.id}"
obj = object.to_dict()
date = datetime.fromtimestamp(float(float(str(obj['date'])[:10]))).strftime("%d/%m/%Y")
objects.append({"name": name, "img": img, **obj, "date": date})
return render_template("Index.html", objects=objects, page_title="Home")
@app.route("/upload/") @app.route("/upload/")
@ -138,7 +160,11 @@ def ApiUpload():
}, },
request.files["file"].filename, request.files["file"].filename,
) )
except (FB_EXCEPTION.ConflictError, FB_EXCEPTION.AlreadyExistsError, GOOGLE_EXCEPTION.AlreadyExists) as e: except (
FB_EXCEPTION.ConflictError,
FB_EXCEPTION.AlreadyExistsError,
GOOGLE_EXCEPTION.AlreadyExists,
) as e:
Image.close() Image.close()
os.remove(os.path.join(app.config["UPLOAD_FOLDER"], filename)) os.remove(os.path.join(app.config["UPLOAD_FOLDER"], filename))
return Response( return Response(

View file

@ -1197,6 +1197,12 @@
.me-2 { .me-2 {
margin-inline-end: calc(var(--spacing) * 2); margin-inline-end: calc(var(--spacing) * 2);
} }
.-mt-1 {
margin-top: calc(var(--spacing) * -1);
}
.mt-1 {
margin-top: calc(var(--spacing) * 1);
}
.mt-2 { .mt-2 {
margin-top: calc(var(--spacing) * 2); margin-top: calc(var(--spacing) * 2);
} }
@ -1586,6 +1592,9 @@
.inline-flex { .inline-flex {
display: inline-flex; display: inline-flex;
} }
.list-item {
display: list-item;
}
.table { .table {
display: table; display: table;
} }
@ -1601,9 +1610,15 @@
.h-8 { .h-8 {
height: calc(var(--spacing) * 8); height: calc(var(--spacing) * 8);
} }
.h-32 {
height: calc(var(--spacing) * 32);
}
.h-64 { .h-64 {
height: calc(var(--spacing) * 64); height: calc(var(--spacing) * 64);
} }
.h-128 {
height: calc(var(--spacing) * 128);
}
.h-\[calc\(100\%-1rem\)\] { .h-\[calc\(100\%-1rem\)\] {
height: calc(100% - 1rem); height: calc(100% - 1rem);
} }
@ -1613,6 +1628,9 @@
.max-h-full { .max-h-full {
max-height: 100%; max-height: 100%;
} }
.min-h-32 {
min-height: calc(var(--spacing) * 32);
}
.datatable-table { .datatable-table {
.datatable-wrapper & { .datatable-wrapper & {
width: 100%; width: 100%;
@ -1696,6 +1714,9 @@
text-align: center; text-align: center;
} }
} }
.w-1 {
width: calc(var(--spacing) * 1);
}
.w-1\/2 { .w-1\/2 {
width: calc(1/2 * 100%); width: calc(1/2 * 100%);
} }
@ -1711,6 +1732,9 @@
.w-8 { .w-8 {
width: calc(var(--spacing) * 8); width: calc(var(--spacing) * 8);
} }
.w-32 {
width: calc(var(--spacing) * 32);
}
.w-64 { .w-64 {
width: calc(var(--spacing) * 64); width: calc(var(--spacing) * 64);
} }
@ -1723,6 +1747,9 @@
.max-w-2xl { .max-w-2xl {
max-width: var(--container-2xl); max-width: var(--container-2xl);
} }
.max-w-32 {
max-width: calc(var(--spacing) * 32);
}
.datatable-input { .datatable-input {
.datatable-wrapper .datatable-search & { .datatable-wrapper .datatable-search & {
color: var(--color-gray-900); color: var(--color-gray-900);
@ -1791,6 +1818,9 @@
.flex-shrink { .flex-shrink {
flex-shrink: 1; flex-shrink: 1;
} }
.border-collapse {
border-collapse: collapse;
}
.-translate-x-full { .-translate-x-full {
--tw-translate-x: -100%; --tw-translate-x: -100%;
translate: var(--tw-translate-x) var(--tw-translate-y); translate: var(--tw-translate-x) var(--tw-translate-y);
@ -1835,9 +1865,18 @@
.resize-none { .resize-none {
resize: none; resize: none;
} }
.grid-cols-2 {
grid-template-columns: repeat(2, minmax(0, 1fr));
}
.grid-cols-3 {
grid-template-columns: repeat(3, minmax(0, 1fr));
}
.grid-cols-4 { .grid-cols-4 {
grid-template-columns: repeat(4, minmax(0, 1fr)); grid-template-columns: repeat(4, minmax(0, 1fr));
} }
.grid-cols-6 {
grid-template-columns: repeat(6, minmax(0, 1fr));
}
.grid-cols-7 { .grid-cols-7 {
grid-template-columns: repeat(7, minmax(0, 1fr)); grid-template-columns: repeat(7, minmax(0, 1fr));
} }
@ -1868,15 +1907,18 @@
.justify-start { .justify-start {
justify-content: flex-start; justify-content: flex-start;
} }
.gap-1 {
gap: calc(var(--spacing) * 1);
}
.gap-2 { .gap-2 {
gap: calc(var(--spacing) * 2); gap: calc(var(--spacing) * 2);
} }
.gap-3 {
gap: calc(var(--spacing) * 3);
}
.gap-4 { .gap-4 {
gap: calc(var(--spacing) * 4); gap: calc(var(--spacing) * 4);
} }
.gap-8 {
gap: calc(var(--spacing) * 8);
}
.space-y-6 { .space-y-6 {
:where(& > :not(:last-child)) { :where(& > :not(:last-child)) {
--tw-space-y-reverse: 0; --tw-space-y-reverse: 0;
@ -1950,6 +1992,14 @@
border-bottom-style: var(--tw-border-style); border-bottom-style: var(--tw-border-style);
border-bottom-width: 1px; border-bottom-width: 1px;
} }
.border-l {
border-left-style: var(--tw-border-style);
border-left-width: 1px;
}
.border-l-2 {
border-left-style: var(--tw-border-style);
border-left-width: 2px;
}
.border-dashed { .border-dashed {
--tw-border-style: dashed; --tw-border-style: dashed;
border-style: dashed; border-style: dashed;
@ -2102,12 +2152,18 @@
.border-gray-300 { .border-gray-300 {
border-color: var(--color-gray-300); border-color: var(--color-gray-300);
} }
.border-gray-500 {
border-color: var(--color-gray-500);
}
.border-gray-600 { .border-gray-600 {
border-color: var(--color-gray-600); border-color: var(--color-gray-600);
} }
.border-gray-700 { .border-gray-700 {
border-color: var(--color-gray-700); border-color: var(--color-gray-700);
} }
.border-gray-800 {
border-color: var(--color-gray-800);
}
.apexcharts-active { .apexcharts-active {
.apexcharts-canvas .apexcharts-tooltip-series-group& .apexcharts-tooltip-y-group { .apexcharts-canvas .apexcharts-tooltip-series-group& .apexcharts-tooltip-y-group {
padding: 0 !important; padding: 0 !important;
@ -2146,6 +2202,18 @@
padding-top: 0.75rem !important; padding-top: 0.75rem !important;
} }
} }
.bg-black {
background-color: var(--color-black);
}
.bg-black\/25 {
background-color: color-mix(in oklab, var(--color-black) 25%, transparent);
}
.bg-black\/50 {
background-color: color-mix(in oklab, var(--color-black) 50%, transparent);
}
.bg-black\/75 {
background-color: color-mix(in oklab, var(--color-black) 75%, transparent);
}
.bg-blue-700 { .bg-blue-700 {
background-color: var(--color-blue-700); background-color: var(--color-blue-700);
} }
@ -2167,12 +2235,24 @@
.bg-gray-800 { .bg-gray-800 {
background-color: var(--color-gray-800); background-color: var(--color-gray-800);
} }
.bg-gray-900 {
background-color: var(--color-gray-900);
}
.bg-gray-900\/50 { .bg-gray-900\/50 {
background-color: color-mix(in oklab, var(--color-gray-900) 50%, transparent); background-color: color-mix(in oklab, var(--color-gray-900) 50%, transparent);
} }
.bg-red-700 { .bg-red-700 {
background-color: var(--color-red-700); background-color: var(--color-red-700);
} }
.bg-slate-500 {
background-color: var(--color-slate-500);
}
.bg-slate-700 {
background-color: var(--color-slate-700);
}
.bg-slate-800 {
background-color: var(--color-slate-800);
}
.bg-slate-900 { .bg-slate-900 {
background-color: var(--color-slate-900); background-color: var(--color-slate-900);
} }
@ -2198,6 +2278,45 @@
background-color: var(--color-gray-700); background-color: var(--color-gray-700);
} }
} }
.bg-gradient-to-t {
--tw-gradient-position: to top in oklab;
background-image: linear-gradient(var(--tw-gradient-stops));
}
.from-black {
--tw-gradient-from: var(--color-black);
--tw-gradient-stops: var(--tw-gradient-via-stops, var(--tw-gradient-position), var(--tw-gradient-from) var(--tw-gradient-from-position), var(--tw-gradient-to) var(--tw-gradient-to-position));
}
.from-black\/75 {
--tw-gradient-from: color-mix(in oklab, var(--color-black) 75%, transparent);
--tw-gradient-stops: var(--tw-gradient-via-stops, var(--tw-gradient-position), var(--tw-gradient-from) var(--tw-gradient-from-position), var(--tw-gradient-to) var(--tw-gradient-to-position));
}
.from-black\/80 {
--tw-gradient-from: color-mix(in oklab, var(--color-black) 80%, transparent);
--tw-gradient-stops: var(--tw-gradient-via-stops, var(--tw-gradient-position), var(--tw-gradient-from) var(--tw-gradient-from-position), var(--tw-gradient-to) var(--tw-gradient-to-position));
}
.from-black\/90 {
--tw-gradient-from: color-mix(in oklab, var(--color-black) 90%, transparent);
--tw-gradient-stops: var(--tw-gradient-via-stops, var(--tw-gradient-position), var(--tw-gradient-from) var(--tw-gradient-from-position), var(--tw-gradient-to) var(--tw-gradient-to-position));
}
.to-transparent {
--tw-gradient-to: transparent;
--tw-gradient-stops: var(--tw-gradient-via-stops, var(--tw-gradient-position), var(--tw-gradient-from) var(--tw-gradient-from-position), var(--tw-gradient-to) var(--tw-gradient-to-position));
}
.to-25\% {
--tw-gradient-to-position: 25%;
}
.to-80\% {
--tw-gradient-to-position: 80%;
}
.to-90\% {
--tw-gradient-to-position: 90%;
}
.to-95\% {
--tw-gradient-to-position: 95%;
}
.to-100\% {
--tw-gradient-to-position: 100%;
}
.apexcharts-text { .apexcharts-text {
.apexcharts-datalabels-group &.apexcharts-datalabel-value { .apexcharts-datalabels-group &.apexcharts-datalabel-value {
fill: var(--color-gray-900) !important; fill: var(--color-gray-900) !important;
@ -2281,6 +2400,12 @@
.object-contain { .object-contain {
object-fit: contain; object-fit: contain;
} }
.object-cover {
object-fit: cover;
}
.object-scale-down {
object-fit: scale-down;
}
.apexcharts-legend { .apexcharts-legend {
.apexcharts-canvas & { .apexcharts-canvas & {
padding: 0 !important; padding: 0 !important;
@ -2312,12 +2437,18 @@
.p-8 { .p-8 {
padding: calc(var(--spacing) * 8); padding: calc(var(--spacing) * 8);
} }
.p-\[\;r<EFBFBD>\] {
padding: ;r<EFBFBD>;
}
.px-2 { .px-2 {
padding-inline: calc(var(--spacing) * 2); padding-inline: calc(var(--spacing) * 2);
} }
.px-5 { .px-5 {
padding-inline: calc(var(--spacing) * 5); padding-inline: calc(var(--spacing) * 5);
} }
.py-1 {
padding-block: calc(var(--spacing) * 1);
}
.py-2 { .py-2 {
padding-block: calc(var(--spacing) * 2); padding-block: calc(var(--spacing) * 2);
} }
@ -2336,6 +2467,18 @@
.pt-5 { .pt-5 {
padding-top: calc(var(--spacing) * 5); padding-top: calc(var(--spacing) * 5);
} }
.pt-8 {
padding-top: calc(var(--spacing) * 8);
}
.pt-12 {
padding-top: calc(var(--spacing) * 12);
}
.pt-16 {
padding-top: calc(var(--spacing) * 16);
}
.pt-24 {
padding-top: calc(var(--spacing) * 24);
}
.search-filtering-row { .search-filtering-row {
.datatable-wrapper .datatable-container thead tr& th { .datatable-wrapper .datatable-container thead tr& th {
padding-top: 0; padding-top: 0;
@ -2507,9 +2650,24 @@
color: white; color: white;
} }
} }
.text-blue-200 {
color: var(--color-blue-200);
}
.text-blue-300 {
color: var(--color-blue-300);
}
.text-blue-400 {
color: var(--color-blue-400);
}
.text-blue-500 {
color: var(--color-blue-500);
}
.text-blue-600 { .text-blue-600 {
color: var(--color-blue-600); color: var(--color-blue-600);
} }
.text-gray-200 {
color: var(--color-gray-200);
}
.text-gray-300 { .text-gray-300 {
color: var(--color-gray-300); color: var(--color-gray-300);
} }
@ -2534,6 +2692,9 @@
.uppercase { .uppercase {
text-transform: uppercase; text-transform: uppercase;
} }
.underline {
text-decoration-line: underline;
}
.opacity-0 { .opacity-0 {
opacity: 0%; opacity: 0%;
} }
@ -2621,6 +2782,13 @@
} }
} }
} }
.hover\:bg-gray-500 {
&:hover {
@media (hover: hover) {
background-color: var(--color-gray-500);
}
}
}
.hover\:bg-gray-600 { .hover\:bg-gray-600 {
&:hover { &:hover {
@media (hover: hover) { @media (hover: hover) {
@ -2642,6 +2810,20 @@
} }
} }
} }
.hover\:text-blue-400 {
&:hover {
@media (hover: hover) {
color: var(--color-blue-400);
}
}
}
.hover\:text-blue-500 {
&:hover {
@media (hover: hover) {
color: var(--color-blue-500);
}
}
}
.hover\:text-blue-600 { .hover\:text-blue-600 {
&:hover { &:hover {
@media (hover: hover) { @media (hover: hover) {
@ -2670,6 +2852,20 @@
} }
} }
} }
.hover\:text-white {
&:hover {
@media (hover: hover) {
color: var(--color-white);
}
}
}
.hover\:underline {
&:hover {
@media (hover: hover) {
text-decoration-line: underline;
}
}
}
.focus\:z-10 { .focus\:z-10 {
&:focus { &:focus {
z-index: 10; z-index: 10;
@ -2707,6 +2903,11 @@
--tw-ring-color: var(--color-gray-200); --tw-ring-color: var(--color-gray-200);
} }
} }
.focus\:ring-gray-800 {
&:focus {
--tw-ring-color: var(--color-gray-800);
}
}
.focus\:ring-red-300 { .focus\:ring-red-300 {
&:focus { &:focus {
--tw-ring-color: var(--color-red-300); --tw-ring-color: var(--color-red-300);
@ -3407,6 +3608,48 @@
inherits: false; inherits: false;
initial-value: solid; initial-value: solid;
} }
@property --tw-gradient-position {
syntax: "*";
inherits: false;
}
@property --tw-gradient-from {
syntax: "<color>";
inherits: false;
initial-value: #0000;
}
@property --tw-gradient-via {
syntax: "<color>";
inherits: false;
initial-value: #0000;
}
@property --tw-gradient-to {
syntax: "<color>";
inherits: false;
initial-value: #0000;
}
@property --tw-gradient-stops {
syntax: "*";
inherits: false;
}
@property --tw-gradient-via-stops {
syntax: "*";
inherits: false;
}
@property --tw-gradient-from-position {
syntax: "<length-percentage>";
inherits: false;
initial-value: 0%;
}
@property --tw-gradient-via-position {
syntax: "<length-percentage>";
inherits: false;
initial-value: 50%;
}
@property --tw-gradient-to-position {
syntax: "<length-percentage>";
inherits: false;
initial-value: 100%;
}
@property --tw-leading { @property --tw-leading {
syntax: "*"; syntax: "*";
inherits: false; inherits: false;

View file

@ -1,12 +1,135 @@
{% extends 'base.html' %} {% extends 'base.html' %}
{% block content %} {% block content %}
<div class="flex gap-1 mb-4">
<button type="button" id="list-view-btn"
class="border focus:ring-4 focus:outline-none font-medium rounded-lg text-sm p-2.5 text-center inline-flex items-center me-2 border-gray-500 text-gray-500 hover:text-white focus:ring-gray-800 hover:bg-gray-500">
<svg class="w-6 h-6 text-white" aria-hidden="true" xmlns="http://www.w3.org/2000/svg" width="24" height="24"
fill="none" viewBox="0 0 24 24">
<path stroke="currentColor" stroke-linecap="round" stroke-width="2"
d="M9 8h10M9 12h10M9 16h10M4.99 8H5m-.02 4h.01m0 4H5" />
</svg>
<span class="sr-only">List View</span>
</button>
<button type="button" id="grid-view-btn"
class="border focus:ring-4 focus:outline-none font-medium rounded-lg text-sm p-2.5 text-center inline-flex items-center me-2 border-gray-500 text-gray-500 hover:text-white focus:ring-gray-800 hover:bg-gray-500">
<svg class="w-6 h-6 text-white" aria-hidden="true" xmlns="http://www.w3.org/2000/svg" width="24" height="24"
fill="currentColor" viewBox="0 0 24 24">
<path fill-rule="evenodd"
d="M4.857 3A1.857 1.857 0 0 0 3 4.857v4.286C3 10.169 3.831 11 4.857 11h4.286A1.857 1.857 0 0 0 11 9.143V4.857A1.857 1.857 0 0 0 9.143 3H4.857Zm10 0A1.857 1.857 0 0 0 13 4.857v4.286c0 1.026.831 1.857 1.857 1.857h4.286A1.857 1.857 0 0 0 21 9.143V4.857A1.857 1.857 0 0 0 19.143 3h-4.286Zm-10 10A1.857 1.857 0 0 0 3 14.857v4.286C3 20.169 3.831 21 4.857 21h4.286A1.857 1.857 0 0 0 11 19.143v-4.286A1.857 1.857 0 0 0 9.143 13H4.857Zm10 0A1.857 1.857 0 0 0 13 14.857v4.286c0 1.026.831 1.857 1.857 1.857h4.286A1.857 1.857 0 0 0 21 19.143v-4.286A1.857 1.857 0 0 0 19.143 13h-4.286Z"
clip-rule="evenodd" />
</svg>
<span class="sr-only">Grid View</span>
</button>
</div>
<div class="flex-col gap-4 hidden" id="list-view">
{% for object in objects %}
<div class="flex gap-4 rounded-lg bg-slate-800 p-2 w-full min-h-32 items-start">
<a href="/edit/{{ object.name }}" class="hover:underline">
<img src="https://s3.tebi.io/radiquum-photos/{{ object.img }}" alt=""
class="max-w-32 rounded-lg object-scale-down" />
</a>
<div class="flex flex-col gap-2">
<a href="/edit/{{ object.name }}" class="hover:underline">
<div>
<p class="text-sm text-gray-400">{{ object.date }}</p>
<p class="text-xl -mt-1">{{ object.name }}</p>
<p class="text-sm text-gray-400">{{ object.width }} x {{ object.height }}</p>
</div>
</a>
<p>{{ object.alt or "WARNING: NO ALT!" }}</p>
{% if object.urls %}
<div class="flex gap-3 flex-wrap">
<p>urls:</p>
{% for url in object.urls %}
<a href="{{ url.value }}" class="text-blue-300 hover:text-blue-500 hover:underline">{{ url.name }}</a>
{% endfor %}
</div>
{% endif %}
{% if object.tags %}
<div class="flex gap-1 flex-wrap">
{% for tag in object.tags %}
<a href="{{ url_for('Home') }}?tag={{ tag }}" class="hover:underline">
<div class="bg-slate-900 rounded-lg px-2 py-1">
#{{ tag }}
</div>
</a>
{% endfor %}
</div>
{% endif %}
</div>
</div>
{% endfor %}
</div>
<div class="gap-4 hidden grid-cols-3" id="grid-view">
{% for object in objects %}
<div class="w-full h-128 bg-slate-800 p-2 relative">
<a href="/edit/{{ object.name }}">
<img class="absolute w-full h-full inset-0 object-cover"
src="https://s3.tebi.io/radiquum-photos/{{ object.img }}" alt="" />
</a>
<div
class="absolute bottom-0 left-0 w-full px-2 pb-2 pt-16 bg-gradient-to-t from-black/90 to-transparent to-95%">
<div>
<p class="text-xl -mt-1">{{ object.name }}</p>
<div class="flex gap-2 text-gray-300 text-sm">
<p>{{ object.date }}</p>
<p>{{ object.width }} x {{ object.height }}</p>
</div>
{% if object.urls %}
<div class="flex gap-2 flex-wrap">
<p>urls:</p>
{% for url in object.urls %}
<a href="{{ url.value }}" class="text-blue-300 hover:text-blue-500 hover:underline">{{ url.name
}}</a>
{% endfor %}
</div>
{% endif %}
{% if object.tags %}
<div class="flex gap-2 flex-wrap">
{% for tag in object.tags %}
<a href="{{ url_for('Home') }}?tag={{ tag }}" class="hover:underline">#{{ tag }}</a>
{% endfor %}
</div>
{% endif %}
</div>
</div>
</div>
{% endfor %}
</div>
<!-- {% for object in objects %} <script>
<img src="https://s3.tebi.io/radiquum-photos/{{ object['Key'] }}" />
<p>{{ object['Key'] }}</p> const listView = document.getElementById('list-view')
{% endfor %} --> const gridView = document.getElementById('grid-view')
const listViewBtn = document.getElementById('list-view-btn')
const gridViewBtn = document.getElementById('grid-view-btn')
let view = localStorage.getItem('view') || 'list'
if (view === 'list') {
listView.classList.remove('hidden')
listView.classList.add('flex')
} else if (view === 'grid') {
gridView.classList.remove('hidden')
gridView.classList.add('grid')
}
listViewBtn.addEventListener('click', () => {
listView.classList.remove('hidden')
listView.classList.add('flex')
gridView.classList.add('hidden')
localStorage.setItem('view', 'list')
})
gridViewBtn.addEventListener('click', () => {
gridView.classList.remove('hidden')
gridView.classList.add('grid')
listView.classList.add('hidden')
localStorage.setItem('view', 'grid')
})
</script>
{% endblock %} {% endblock %}

View file

@ -94,7 +94,7 @@
tagInp.addEventListener('input', (e) => { tagInp.addEventListener('input', (e) => {
if (e.target.value.includes(',')) { if (e.target.value.includes(',')) {
const tag = e.target.value.split(',')[0].trim().replaceAll(" ", "_").toLowerCase(); const tag = e.target.value.split(',')[0].trim().replaceAll(" ", "_").toLowerCase();
if (tags.includes(tag)) { if (tags.includes(tag) || !tag) {
tagInp.value = ''; tagInp.value = '';
return; return;
}; };