fix: added ui for managing theme and tiers

This commit is contained in:
Damien Ostler 2024-06-08 00:26:23 -04:00
parent 4d86b8aeed
commit a9968ccb03
19 changed files with 1476 additions and 274 deletions

41
app/admin/page.tsx Normal file
View File

@ -0,0 +1,41 @@
"use client";
import { createClient } from "@/utils/supabase/client";
import React, { useState, useEffect } from 'react';
import { useRouter } from 'next/navigation';
function PageComponent() {
const supabase = createClient();
const getData = async () => {
}
useEffect(() => {
getData();
}, []);
const router = useRouter();
return (
<div className="w-full text-white flex justify-center items-center animate-in">
<div className="w-2/3 lg:w-1/3 rounded-md bg-primary p-12 mt-32 shadow-lg opacity-90 backdrop-blur-lg">
<div className="w-full flex justify-center">
<span className="text-2xl pb-4">System Settings</span>
</div>
<div className="flex justify-center ">
<button onClick={()=>{ router.push("/admin/tiers") }} className="bg-secondary hover:bg-secondary-dark rounded p-2 mr-1 w-full">Tiers Management</button>
<button onClick={()=>{ router.push("/gallery/admin") }} className="ml-1 bg-secondary hover:bg-secondary-dark rounded p-2 w-full">Gallery Management</button>
</div>
<div className="flex justify-center pt-2">
<button onClick={()=>{ router.push("/admin/theme") }} className="mr-1 bg-secondary hover:bg-secondary-dark rounded p-2 mr-1 w-full">Theme Settings</button>
<button className="bg-secondary hover:bg-secondary-dark rounded p-2 ml-1 w-full">User Management</button>
</div>
<div className="flex justify-center pt-2">
<button className="bg-secondary hover:bg-secondary-dark rounded p-2 w-full mr-1">Payment/Payout Settings</button>
<button className="bg-secondary hover:bg-secondary-dark rounded p-2 w-full ml-1">Comissions Settings</button>
</div>
</div>
</div>
);
}
export default PageComponent;

474
app/admin/theme/page.tsx Normal file
View File

@ -0,0 +1,474 @@
"use client";
import { createClient } from "@/utils/supabase/client";
import React, { useState, useEffect } from 'react';
import { useRouter } from 'next/navigation';
function PageComponent() {
const router = useRouter();
const supabase = createClient();
const [primary, setPrimary] = useState('#201240');
const [primaryLight, setPrimaryLight] = useState('#403260');
const [primaryDark, setPrimaryDark] = useState('#100120');
const [secondary, setSecondary] = useState('#4F3D70');
const [secondaryLight, setSecondaryLight] = useState('#6F5D90');
const [secondaryDark, setSecondaryDark] = useState('#2F1D50');
const [error, setError] = useState('#862117');
const [errorLight, setErrorLight] = useState('#C44C4C');
const [errorDark, setErrorDark] = useState('#5C0D0D');
const [changed, setChanged] = useState(false);
const [success, setSuccess] = useState('#00C9A6');
const [successLight, setSuccessLight] = useState('#20E9C6');
const [successDark, setSuccessDark] = useState('#00A986');
const [warning, setWarning] = useState('#E17558');
const [warningLight, setWarningLight] = useState('#E39578');
const [warningDark, setWarningDark] = useState('#C15538');
const [info, setInfo] = useState('#222140');
const [infoLight, setInfoLight] = useState('#424260');
const [infoDark, setInfoDark] = useState('#020120');
const [saving, setSaving] = useState(false);
const getData = async () => {
var primaryConfig = await getColorConfig('primary');
setPrimary(primaryConfig.value);
var primaryLightConfig = await getColorConfig('primary-light');
setPrimaryLight(primaryLightConfig.value);
var primaryDarkConfig = await getColorConfig('primary-dark');
setPrimaryDark(primaryDarkConfig.value);
var secondaryConfig = await getColorConfig('secondary');
setSecondary(secondaryConfig.value);
var secondaryLightConfig = await getColorConfig('secondary-light');
setSecondaryLight(secondaryLightConfig.value);
var secondaryDarkConfig = await getColorConfig('secondary-dark');
setSecondaryDark(secondaryDarkConfig.value);
var errorConfig = await getColorConfig('error');
setError(errorConfig.value);
var errorLightConfig = await getColorConfig('error-light');
setErrorLight(errorLightConfig.value);
var errorDarkConfig = await getColorConfig('error-dark');
setErrorDark(errorDarkConfig.value);
var successConfig = await getColorConfig('success');
setSuccess(successConfig.value);
var successLightConfig = await getColorConfig('success-light');
setSuccessLight(successLightConfig.value);
var successDarkConfig = await getColorConfig('success-dark');
setSuccessDark(successDarkConfig.value);
var warningConfig = await getColorConfig('warning');
setWarning(warningConfig.value);
var warningLightConfig = await getColorConfig('warning-light');
setWarningLight(warningLightConfig.value);
var warningDarkConfig = await getColorConfig('warning-dark');
setWarningDark(warningDarkConfig.value);
var infoConfig = await getColorConfig('info');
setInfo(infoConfig.value);
var infoLightConfig = await getColorConfig('info-light');
setInfoLight(infoLightConfig.value);
var infoDarkConfig = await getColorConfig('info-dark');
setInfoDark(infoDarkConfig.value);
}
const getColorConfig = async (name: string) => {
try {
const response = await fetch(`/api/admin/interface-configs?name=${name}`, {
method: 'GET',
headers: {
'Content-Type': 'application/json',
},
});
if (!response.ok) {
throw new Error('Failed to call GET request');
}
const data = await response.json();
return data;
} catch (error) {
console.error(error);
throw new Error('Failed to call GET request');
}
}
const setColorConfig = async (name: string, value:string) => {
try {
const response = await fetch(`/api/admin/interface-configs`, {
method: 'PUT',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({ name, value }),
});
if (!response.ok) {
throw new Error('Failed to call GET request');
}
const data = await response.json();
return data;
} catch (error) {
console.error(error);
throw new Error('Failed to call GET request');
}
}
const save = async () => {
setSaving(true);
await Promise.all([
setColorConfig('primary', primary),
setColorConfig('primary-light', primaryLight),
setColorConfig('primary-dark', primaryDark),
setColorConfig('secondary', secondary),
setColorConfig('secondary-light', secondaryLight),
setColorConfig('secondary-dark', secondaryDark),
setColorConfig('error', error),
setColorConfig('error-light', errorLight),
setColorConfig('error-dark', errorDark),
setColorConfig('success', success),
setColorConfig('success-light', successLight),
setColorConfig('success-dark', successDark),
setColorConfig('warning', warning),
setColorConfig('warning-light', warningLight),
setColorConfig('warning-dark', warningDark),
setColorConfig('info', info),
setColorConfig('info-light', infoLight),
setColorConfig('info-dark', infoDark)
]);
window.location.reload();
}
useEffect(() => {
getData();
}, []);
const colorChange = async ()=>{
setChanged(true)
document.documentElement.style.setProperty(`--color-primary`, primary);
document.documentElement.style.setProperty(`--color-primary-light`, primaryLight);
document.documentElement.style.setProperty(`--color-primary-dark`, primaryDark);
document.documentElement.style.setProperty(`--color-secondary`, secondary);
document.documentElement.style.setProperty(`--color-secondary-light`, secondaryLight);
document.documentElement.style.setProperty(`--color-secondary-dark`, secondaryDark);
document.documentElement.style.setProperty(`--color-error`, error);
document.documentElement.style.setProperty(`--color-error-light`, errorLight);
document.documentElement.style.setProperty(`--color-error-dark`, errorDark);
document.documentElement.style.setProperty(`--color-success`, success);
document.documentElement.style.setProperty(`--color-success-light`, successLight);
document.documentElement.style.setProperty(`--color-success-dark`, successDark);
document.documentElement.style.setProperty(`--color-warning`, warning);
document.documentElement.style.setProperty(`--color-warning-light`, warningLight);
document.documentElement.style.setProperty(`--color-warning-dark`, warningDark);
document.documentElement.style.setProperty(`--color-info`, info);
document.documentElement.style.setProperty(`--color-info-light`, infoLight);
document.documentElement.style.setProperty(`--color-info-dark`, infoDark);
}
return (
<div className="w-5/6 h-1/2 text-white lg:flex justify-center items-center animate-in overflow-y-hidden">
<div className=" w-5/6 md:w-4/6 lg:w-3/6 xl:w-2/6 rounded-md bg-primary opacity-90 p-12 m-1 mt-24 shadow-lg backdrop-blur">
<div className="w-full relative">
<span className="text-2xl pb-4">Color Settings</span>
<button onClick={()=>{router.push("/admin")}} className={`float-right bg-error hover:bg-error-light ml-2 rounded p-2`}>
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" strokeWidth={1.5} stroke="currentColor"
className="md:hidden size-6">
<path strokeLinecap="round" strokeLinejoin="round" d="M9 15 3 9m0 0 6-6M3 9h12a6 6 0 0 1 0 12h-3" />
</svg>
<span className="hidden md:block">Back</span>
</button>
<button onClick={save} disabled={!changed}
className={`float-right ${changed ? "bg-success hover:bg-success-light" : "bg-success-dark"} rounded p-2`}>
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" strokeWidth={1.5} stroke="currentColor"
className="md:hidden size-6">
<path strokeLinecap="round" strokeLinejoin="round" d="m4.5 12.75 6 6 9-13.5" />
</svg>
<span className="hidden md:block">{saving?"Saving...":"Save"}</span>
</button>
</div>
<div className="w-full relative">
<label htmlFor="primaryInput">Primary Color</label>
<div className="flex">
<input
value={primary}
required
type="text"
className="w-full rounded-md rounded-r-none bg-info-bright p-2 text-black shadow-lg"
onChange={(e) => { setPrimary(e.target.value); colorChange(); }}
placeholder="Choose the primary color"
/>
<input
value={primary}
onChange={(e) => { setPrimary(e.target.value); colorChange(); }}
required
type="color"
className="w-10 h-10 rounded-r p-1"
/>
</div>
</div>
<div className="w-full relative">
<label htmlFor="primaryInput">Primary Light Color</label>
<div className="flex">
<input
value={primaryLight}
required
type="text"
className="w-full rounded-md rounded-r-none bg-info-bright p-2 text-black shadow-lg"
onChange={(e) => { setPrimaryLight(e.target.value); colorChange(); }}
placeholder="Choose the primary color"
/>
<input
value={primaryLight}
onChange={(e) => { setPrimaryLight(e.target.value); colorChange(); }}
required
type="color"
className="w-10 h-10 rounded-r p-1"
/>
</div>
</div>
<div className="w-full relative">
<label htmlFor="primaryInput">Primary Dark Color</label>
<div className="flex">
<input
value={primaryDark}
required
type="text"
className="w-full rounded-md rounded-r-none bg-info-bright p-2 text-black shadow-lg"
onChange={(e) => { setPrimaryDark(e.target.value); colorChange(); }}
placeholder="Choose the primary color"
/>
<input
value={primaryDark}
onChange={(e) => { setPrimaryDark(e.target.value); colorChange(); }}
required
type="color"
className="w-10 h-10 rounded-r p-1"
/>
</div>
</div>
<div className="w-full relative">
<label htmlFor="primaryInput">Secondary Color</label>
<div className="flex">
<input
value={secondary}
required
type="text"
className="w-full rounded-md rounded-r-none bg-info-bright p-2 text-black shadow-lg"
onChange={(e) => { setSecondary(e.target.value); colorChange(); }}
placeholder="Choose the primary color"
/>
<input
value={secondary}
onChange={(e) => { setSecondary(e.target.value); colorChange(); }}
required
type="color"
className="w-10 h-10 rounded-r p-1"
/>
</div>
</div>
<div className="w-full relative">
<label htmlFor="primaryInput">Secondary Dark Color</label>
<div className="flex">
<input
value={secondaryDark}
required
type="text"
className="w-full rounded-md rounded-r-none bg-info-bright p-2 text-black shadow-lg"
onChange={(e) => { setSecondaryDark(e.target.value); colorChange(); }}
placeholder="Choose the primary color"
/>
<input
value={secondaryDark}
onChange={(e) => { setSecondaryDark(e.target.value); colorChange(); }}
required
type="color"
className="w-10 h-10 rounded-r p-1"
/>
</div>
</div>
<div className="w-full relative">
<label htmlFor="primaryInput">Secondary Light Color</label>
<div className="flex">
<input
value={secondaryLight}
required
type="text"
className="w-full rounded-md rounded-r-none bg-info-bright p-2 text-black shadow-lg"
onChange={(e) => { setSecondaryLight(e.target.value); colorChange(); }}
placeholder="Choose the primary color"
/>
<input
value={secondaryLight}
onChange={(e) => { setSecondaryLight(e.target.value); colorChange(); }}
required
type="color"
className="w-10 h-10 rounded-r p-1"
/>
</div>
</div>
<div className="w-full relative">
<label htmlFor="primaryInput">Error Color</label>
<div className="flex">
<input
value={error}
required
type="text"
className="w-full rounded-md rounded-r-none bg-info-bright p-2 text-black shadow-lg"
onChange={(e) => { setError(e.target.value); colorChange(); }}
placeholder="Choose the primary color"
/>
<input
value={error}
onChange={(e) => { setError(e.target.value); colorChange(); }}
required
type="color"
className="w-10 h-10 rounded-r p-1"
/>
</div>
</div>
<div className="w-full relative">
<label htmlFor="primaryInput">Error Dark Color</label>
<div className="flex">
<input
value={errorDark}
required
type="text"
className="w-full rounded-md rounded-r-none bg-info-bright p-2 text-black shadow-lg"
onChange={(e) => { setErrorDark(e.target.value); colorChange(); }}
placeholder="Choose the primary color"
/>
<input
value={errorDark}
onChange={(e) => { setErrorDark(e.target.value); colorChange(); }}
required
type="color"
className="w-10 h-10 rounded-r p-1"
/>
</div>
</div>
<div className="w-full relative">
<label htmlFor="primaryInput">Error Light Color</label>
<div className="flex">
<input
value={errorLight}
required
type="text"
className="w-full rounded-md rounded-r-none bg-info-bright p-2 text-black shadow-lg"
onChange={(e) => { setErrorLight(e.target.value); colorChange(); }}
placeholder="Choose the primary color"
/>
<input
value={errorLight}
onChange={(e) => { setErrorLight(e.target.value); colorChange(); }}
required
type="color"
className="w-10 h-10 rounded-r p-1"
/>
</div>
</div>
<div className="w-full relative">
<label htmlFor="primaryInput">Success Color</label>
<div className="flex">
<input
value={success}
required
type="text"
className="w-full rounded-md rounded-r-none bg-info-bright p-2 text-black shadow-lg"
onChange={(e) => { setSuccess(e.target.value); colorChange(); }}
placeholder="Choose the primary color"
/>
<input
value={success}
onChange={(e) => { setSuccess(e.target.value); colorChange(); }}
required
type="color"
className="w-10 h-10 rounded-r p-1"
/>
</div>
</div>
<div className="w-full relative">
<label htmlFor="primaryInput">Success Dark Color</label>
<div className="flex">
<input
value={successDark}
required
type="text"
className="w-full rounded-md rounded-r-none bg-info-bright p-2 text-black shadow-lg"
onChange={(e) => { setSuccessDark(e.target.value); colorChange(); }}
placeholder="Choose the primary color"
/>
<input
value={successDark}
onChange={(e) => { setSuccessDark(e.target.value); colorChange(); }}
required
type="color"
className="w-10 h-10 rounded-r p-1"
/>
</div>
</div>
<div className="w-full relative">
<label htmlFor="primaryInput">Success Light Color</label>
<div className="flex">
<input
value={successLight}
required
type="text"
className="w-full rounded-md rounded-r-none bg-info-bright p-2 text-black shadow-lg"
onChange={(e) => { setSuccessLight(e.target.value); colorChange(); }}
placeholder="Choose the primary color"
/>
<input
value={successLight}
onChange={(e) => { setSuccessLight(e.target.value); colorChange(); }}
required
type="color"
className="w-10 h-10 rounded-r p-1"
/>
</div>
</div>
</div>
</div>
);
}
export default PageComponent;

View File

@ -1,57 +1,124 @@
"use client";
import { createClient } from "@/utils/supabase/client";
import React, { useState, useEffect } from 'react';
import React, { useState, useEffect } from 'react';
import { useRouter } from 'next/navigation';
function PageComponent() {
const supabase = createClient();
const getData = async () => {
}
const supabase = createClient();
const router = useRouter();
const [name, setName] = useState<string>('');
const [price, setPrice] = useState<number>(0);
const [description, setDescription] = useState<string>('');
const [color, setColor] = useState<string>('#000000');
useEffect(() => {
getData();
}, []);
return (
<div className="w-full p-8 h-1/2 text-white lg:flex justify-center items-center animate-in">
<div className="w-full lg:w-1/3 rounded-md bg-primary opacity-90 p-12 m-1 mt-32 shadow-lg backdrop-blur">
<div className="w-full flex">
<input type="text" onChange={(e)=>{}}
className="mr-2 rounded-md bg-info-bright p-2 w-1/2 text-black shadow-lg"
placeholder="Tag Name" />
<div className="flex border border-gray-300 w-1/2 rounded-md">
<span className="flex items-center bg-gray-100 rounded-l-md border-r px-3 text-gray-500">
$
</span>
<input
placeholder="Price in USD per month"
type="number"
className="flex-1 min-w-0 bg-info-bright rounded-r-md px-3 py-2 text-black focus:outline-none focus:ring-indigo-500 focus:border-indigo-500 sm:text-sm"
/>
</div>
</div>
<div className="w-full pt-2 justify-center flex">
<textarea placeholder="Description of the tier and what the user gets from subscribing." rows={3} className="w-full rounded-md bg-info-bright p-2 w-1/2 text-black shadow-lg">
const getData = async () => {
}
</textarea>
</div>
<div className="w-full pt-2 justify-center flex">
<div className="w-1/2 relative">
<input type="text" className="w-full rounded-md bg-info-bright p-2 text-black shadow-lg" onChange={(e)=>{}} placeholder="Choose the tiers color"/>
<input id="colorInput" type="color" className="absolute right-0 top-0 w-10 h-full rounded-r p-1"/>
</div>
<button onClick={()=>{}} className="hover:scale-95 ml-2 shadow-lg w-1/2 h-10 text-center bg-success hover:bg-success-light text-white font-bold rounded flex items-center justify-center">
Create
</button>
<button onClick={()=>{}} className="hover:scale-95 shadow-lg ml-2 w-1/2 h-10 text-center bg-error-dark hover:bg-error text-white font-bold rounded flex items-center justify-center">
Back
</button>
useEffect(() => {
getData();
}, []);
const handleSubmit = async (e: React.FormEvent) => {
e.preventDefault();
const data = {
name,
price,
color,
description
};
const response = await fetch('/api/tiers', {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify(data)
});
if (response.ok) {
const responseData = await response.json();
window.location.href = "/admin/tiers";
} else {
console.log(response);
}
}
return (
<div className="w-full p-8 h-1/2 text-white lg:flex justify-center items-center animate-in">
<div className="w-full lg:w-1/3 rounded-md bg-primary opacity-90 p-12 m-1 mt-32 shadow-lg backdrop-blur">
<form onSubmit={handleSubmit}>
<div className="w-full flex">
<span className="text-2xl pb-4">Creating New Tier</span>
</div>
<div className="w-full flex">
<input
value={name}
required
type="text"
onChange={(e) => { setName(e.target.value) }}
className="mr-2 rounded-md bg-info-bright p-2 w-1/2 text-black shadow-lg"
placeholder="Tag Name"
/>
<div className="flex border border-gray-300 w-1/2 rounded-md">
<span className="flex items-center bg-gray-100 rounded-l-md border-r px-3 text-gray-500">
$
</span>
<input
value={price}
onChange={(e) => { setPrice(Number(e.target.value)) }}
required
placeholder="Price in USD per month"
type="number"
className="flex-1 min-w-0 bg-info-bright rounded-r-md px-3 py-2 text-black focus:outline-none focus:ring-indigo-500 focus:border-indigo-500 sm:text-sm"
/>
</div>
</div>
<div className="w-full pt-2 justify-center flex">
<textarea
value={description}
onChange={(e) => { setDescription(e.target.value) }}
required
placeholder="Description of the tier and what the user gets from subscribing."
rows={3}
className="w-full rounded-md bg-info-bright p-2 w-1/2 text-black shadow-lg"
></textarea>
</div>
<div className="w-full pt-2 justify-center flex">
<div className="w-1/2 relative">
<input
value={color}
required
type="text"
className="w-full rounded-md bg-info-bright p-2 text-black shadow-lg"
onChange={(e) => { setColor(e.target.value) }}
placeholder="Choose the tiers color"
/>
<input
value={color}
onChange={(e) => { setColor(e.target.value) }}
required
id="colorInput"
type="color"
className="absolute right-0 top-0 w-10 h-full rounded-r p-1"
/>
</div>
<button
type="submit"
className="hover:scale-95 ml-2 shadow-lg w-1/2 h-10 text-center bg-success hover:bg-success-light text-white font-bold rounded flex items-center justify-center"
>
Create
</button>
<button
type="button"
onClick={() => { router.push("/admin/tiers") }}
className="hover:scale-95 shadow-lg ml-2 w-1/2 h-10 text-center bg-error-dark hover:bg-error text-white font-bold rounded flex items-center justify-center"
>
Back
</button>
</div>
</form>
</div>
</div>
</div>
);
);
}
export default PageComponent;

View File

@ -1,58 +1,53 @@
"use client";
import { createClient } from "@/utils/supabase/client";
import React, { useState, useEffect } from 'react';
import React, { useState, useEffect } from 'react';
import { useRouter } from 'next/navigation';
function PageComponent() {
const supabase = createClient();
const getData = async () => {
}
useEffect(() => {
getData();
}, []);
const fakeData = [
{
description: "Lorem ipsum dolor sit amet",
color: "#5e3573",
price: 9.99,
name: "Product 1"
},
{
description: "Consectetur adipiscing elit",
color: "#00FF00",
price: 19.99,
name: "Product 2"
},
{
description: "Sed do eiusmod tempor incididunt",
color: "#0000FF",
price: 29.99,
name: "Product 3"
const router = useRouter();
const supabase = createClient();
const [tiers, setTiers] = useState<any[]>([]);
const getData = async () => {
try {
const response = await fetch('/api/tiers');
if (response.ok) {
const data = await response.json();
console.log(data)
setTiers(data);
} else {
console.error('Failed to fetch users');
}
} catch (error) {
console.error('Error fetching users:', error);
}
}
];
// Rest of the code...
useEffect(() => {
getData();
}, []);
return (
<div className="w-2/3 p-8 h-1/2 text-white lg:flex justify-center items-center animate-in">
<div className="w-full lg:w-1/3 rounded-md bg-primary opacity-90 p-12 m-1 mt-32 shadow-lg backdrop-blur">
<div className="w-full flex justify-center">
<button className="bg-success hover:bg-success-light rounded p-2 w-full">Create New Tier</button>
</div>
<div className="w-full justify-center pt-8">
{fakeData.map((item, index) => (
<div className="w-full flex justify-center">
<div key={index} className="text-white w-full text-stroke mt-2">
<button className="py-2 w-full rounded hover:scale-105" style={{ backgroundColor: item.color }}>{item.name}</button>
return (
<div className="w-2/3 p-8 h-1/2 text-white lg:flex justify-center items-center animate-in">
<div className="w-full lg:w-1/3 rounded-md bg-primary opacity-90 p-12 m-1 mt-32 shadow-lg backdrop-blur">
<div className="w-full flex justify-center">
<span className="text-2xl pb-4">Tiers Management</span>
</div>
<div className="w-full flex justify-center">
<button onClick={() => { router.push("/admin/tiers/create") }} className="bg-success hover:bg-success-light rounded p-2 w-full">New Tier</button>
<button onClick={() => { router.push("/admin") }} className="bg-error hover:bg-error-light rounded p-2 w-full ml-2">Back</button>
</div>
<div className="w-full justify-center pt-8">
{tiers.map((item, index) => (
<div className="w-full flex justify-center">
<div key={index} className="text-white w-full text-stroke mt-2">
<button onClick={() => { router.push("/admin/tiers/view?name=" + item.name) }} className="py-2 w-full rounded hover:scale-105" style={{ backgroundColor: item.color }}>{item.name} - ${item.price}/month</button>
</div>
</div>
</div>
))}
))}
</div>
</div>
</div>
</div>
);
);
}
export default PageComponent;

View File

@ -1,127 +1,139 @@
"use client";
import { createClient } from "@/utils/supabase/client";
import React, { useState, useEffect } from 'react';
import React, { useState, useEffect } from 'react';
import { useRouter } from 'next/navigation';
function PageComponent() {
const supabase = createClient();
const getData = async () => {
}
const router = useRouter();
const supabase = createClient();
const [tier, setTier] = useState<any[]>([]);
const [users, setUsers] = useState<any[]>([]);
const [name, setName] = useState<string>('');
const [price, setPrice] = useState<number>(0);
const [description, setDescription] = useState<string>('');
const [color, setColor] = useState<string>('#000000');
const getData = async () => {
try {
const searchParams = new URLSearchParams(window.location.search);
const name = searchParams.get('name');
const response = await fetch('/api/tiers/'+name);
if (response.ok) {
const data = await response.json();
console.log(data)
setTier(data);
setName(data.name);
setPrice(data.price);
setDescription(data.description);
setColor(data.color);
} else {
console.error('Failed to fetch users');
}
} catch (error) {
console.error('Error fetching users:', error);
}
}
const handleSubmit = async (e: React.FormEvent) => {
e.preventDefault();
const data = {
newName:name,
price,
color,
description
};
const response = await fetch('/api/tiers/'+name, {
method: 'PUT',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify(data)
});
const [users, setUsers] = useState([
{ email: 'user1@example.com' },
{ email: 'user2@example.com' },
{ email: 'user3@example.com' },
{ email: 'user1@example.com' },
{ email: 'user2@example.com' },
{ email: 'user3@example.com' },
{ email: 'user1@example.com' },
{ email: 'user2@example.com' },
{ email: 'user3@example.com' },
{ email: 'user1@example.com' },
{ email: 'user2@example.com' },
{ email: 'user3@example.com' },
{ email: 'user1@example.com' },
{ email: 'user2@example.com' },
{ email: 'user3@example.com' },
{ email: 'user1@example.com' },
{ email: 'user2@example.com' },
{ email: 'user3@example.com' },
{ email: 'user1@example.com' },
{ email: 'user2@example.com' },
{ email: 'user3@example.com' },
{ email: 'user1@example.com' },
{ email: 'user2@example.com' },
{ email: 'user3@example.com' },
{ email: 'user1@example.com' },
{ email: 'user2@example.com' },
{ email: 'user3@example.com' },
{ email: 'user1@example.com' },
{ email: 'user2@example.com' },
{ email: 'user3@example.com' },
{ email: 'user1@example.com' },
{ email: 'user2@example.com' },
{ email: 'user3@example.com' },
{ email: 'user1@example.com' },
{ email: 'user2@example.com' },
{ email: 'user3@example.com' },
{ email: 'user1@example.com' },
{ email: 'user2@example.com' },
{ email: 'user3@example.com' },
{ email: 'user1@example.com' },
{ email: 'user2@example.com' },
{ email: 'user3@example.com' },
{ email: 'user1@example.com' },
{ email: 'user2@example.com' },
{ email: 'user3@example.com' },
{ email: 'user1@example.com' },
{ email: 'user2@example.com' },
{ email: 'user3@example.com' }
// Add more fake users as needed
]);
if (response.ok) {
const responseData = await response.json();
window.location.href = "/admin/tiers";
} else {
console.log(response);
}
}
useEffect(() => {
getData();
}, []);
useEffect(() => {
getData();
}, []);
return (
<div className="w-full p-8 h-1/2 text-white lg:flex justify-center items-center animate-in">
<div className="w-full lg:w-1/3 rounded-md bg-primary opacity-90 p-12 m-1 mt-32 shadow-lg backdrop-blur">
<div className="w-full flex">
<input type="text" onChange={(e)=>{}}
className="mr-2 rounded-md bg-info-bright p-2 w-1/2 text-black shadow-lg"
placeholder="Tag Name" />
<div className="flex border border-gray-300 w-1/2 rounded-md">
<span className="flex items-center bg-gray-100 rounded-l-md border-r px-3 text-gray-500">
$
</span>
<input
placeholder="Price in USD per month"
type="number"
className="flex-1 min-w-0 bg-info-bright rounded-r-md px-3 py-2 text-black focus:outline-none focus:ring-indigo-500 focus:border-indigo-500 sm:text-sm"
/>
</div>
</div>
<div className="w-full pt-2 justify-center flex">
<textarea placeholder="Description of the tier and what the user gets from subscribing." rows={3} className="w-full rounded-md bg-info-bright p-2 w-1/2 text-black shadow-lg">
</textarea>
</div>
<div className="w-full pt-2 justify-center flex">
<div className="w-1/2 relative">
<input type="text" className="w-full rounded-md bg-info-bright p-2 text-black shadow-lg" onChange={(e)=>{}} placeholder="Choose the tiers color"/>
<input id="colorInput" type="color" className="absolute right-0 top-0 w-10 h-full rounded-r p-1"/>
</div>
<div className="w-1/2 flex">
<button onClick={()=>{}} className="hover:scale-95 shadow-lg ml-2 w-1/2 h-10 text-center bg-warning hover:bg-warning-light text-white font-bold rounded flex items-center justify-center">
Update
</button>
<button onClick={()=>{}} className="hover:scale-95 shadow-lg ml-2 w-1/2 h-10 text-center bg-error hover:bg-error-light text-white font-bold rounded flex items-center justify-center">
Delete
</button>
<button onClick={()=>{}} className="hover:scale-95 shadow-lg ml-2 w-1/2 h-10 text-center bg-error-dark hover:bg-error text-white font-bold rounded flex items-center justify-center">
Back
</button>
return (
<div className="w-full p-8 h-1/2 text-white lg:flex justify-center items-center animate-in">
<div className="w-full lg:w-1/3 rounded-md bg-primary opacity-90 p-12 m-1 mt-32 shadow-lg backdrop-blur">
<form onSubmit={handleSubmit}>
<div className="w-full flex">
<span className="text-2xl pb-4">Editing Existing Tier</span>
</div>
<div className="w-full flex">
<input
value={name}
required
type="text"
onChange={(e) => { setName(e.target.value) }}
className="mr-2 rounded-md bg-info-bright p-2 w-1/2 text-black shadow-lg"
placeholder="Tag Name"
/>
<div className="flex border border-gray-300 w-1/2 rounded-md">
<span className="flex items-center bg-gray-100 rounded-l-md border-r px-3 text-gray-500">
$
</span>
<input
value={price}
onChange={(e) => { setPrice(Number(e.target.value)) }}
required
placeholder="Price in USD per month"
type="number"
className="flex-1 min-w-0 bg-info-bright rounded-r-md px-3 py-2 text-black focus:outline-none focus:ring-indigo-500 focus:border-indigo-500 sm:text-sm"
/>
</div>
</div>
<div className="w-full pt-2 justify-center flex">
<textarea
value={description}
onChange={(e) => { setDescription(e.target.value) }}
required
placeholder="Description of the tier and what the user gets from subscribing."
rows={3}
className="w-full rounded-md bg-info-bright p-2 w-1/2 text-black shadow-lg"
></textarea>
</div>
<div className="w-full pt-2 justify-center flex">
<div className="w-1/2 relative">
<input
value={color}
required
type="text"
className="w-full rounded-md bg-info-bright p-2 text-black shadow-lg"
onChange={(e) => { setColor(e.target.value) }}
placeholder="Choose the tiers color"
/>
<input
value={color}
onChange={(e) => { setColor(e.target.value) }}
required
id="colorInput"
type="color"
className="absolute right-0 top-0 w-10 h-full rounded-r p-1"
/>
</div>
<button onClick={() => { }} className="hover:scale-95 shadow-lg ml-2 w-1/2 h-10 text-center bg-warning hover:bg-warning-light text-white font-bold rounded flex items-center justify-center">
Update
</button>
<button type="button" onClick={() => { }} className="hover:scale-95 shadow-lg ml-2 w-1/2 h-10 text-center bg-error hover:bg-error-light text-white font-bold rounded flex items-center justify-center">
Delete
</button>
<button type="button" onClick={() => { router.push("/admin/tiers") }} className="hover:scale-95 shadow-lg ml-2 w-1/2 h-10 text-center bg-error-dark hover:bg-error text-white font-bold rounded flex items-center justify-center">
Back
</button>
</div>
</form>
</div>
</div>
</div>
<div className="w-full lg:w-1/3 h-96 rounded-md bg-primary opacity-90 p-6 mt-32 shadow-lg backdrop-blur no-scrollbar overflow-y-scroll">
<div className="w-full flex">
<table className="w-full">
<tbody>
{users.map((data, index) => (
<tr key={index} className="rounded hover:bg-secondary bg-secondary-dark shadow-lg">
<td className="px-4 py-2">{data.email}</td>
<td className="px-4 py-2">0 Months</td>
</tr>
))}
</tbody>
</table>
</div>
</div>
</div>
);
);
}
export default PageComponent;

View File

@ -0,0 +1,26 @@
import { NextApiRequest, NextApiResponse } from 'next';
import { createClient } from "@/utils/supabase/server";
import { NextResponse } from "next/server";
export async function PUT(request: Request) {
const body = await request.json();
console.log(body)
const supabase = createClient();
var value = body.value;
const { error } = await supabase.from('interface_configurations').update({ value }).eq('name', body.name);
console.log(error)
if (error) {
return NextResponse.error();
}
return NextResponse.json({});
}
export async function GET(request: NextApiRequest, response: NextApiResponse) {
const url = new URL(request.url as string, 'http://localhost');
const name = url.searchParams.get('name') || '';
const supabase = createClient();
const { data, error } = await supabase.from('interface_configurations').select('*').eq('name', name).single();
return NextResponse.json(data);
}

View File

@ -4,14 +4,12 @@ import { NextResponse } from "next/server";
export async function GET(request: Request) {
try {
const supabase = createClient();
const supabase = createClient();
const { data, error } = await supabase.auth.admin.listUsers();
console.log(error)
if (error) {
throw error;
}
return NextResponse.json(data);
} catch (error) {
return NextResponse.error();

View File

@ -27,7 +27,6 @@ export async function PUT(
const tier = formData.get('tier')?.toString();
const thumbnail = formData.get('thumbnail');
console.log(tier)
const { error } = await supabase.from('galleries').update({name, tags, nsfw, tier, thumbnail_file:thumbnail}).eq('name', originalName ?? '');
async function renameFolder(oldFolderName: any, newFolderName: string) {

View File

@ -0,0 +1,36 @@
import { NextResponse } from "next/server";
import { createClient } from "@/utils/supabase/server";
export async function GET(
request: Request,
{ params }: { params: { name: string } }
) {
const supabase = createClient();
const { data: tier, error: galleryError } = await supabase
.from('tiers')
.select('*')
.eq('name', params.name)
.single();
if(galleryError) {
return NextResponse.error();
}
return NextResponse.json(tier);
}
export async function PUT(
request: Request,
{ params }: { params: { name: string } }
) {
const supabase = createClient();
const { newName, price, color, description } = await request.json();
console.log(newName)
const { error } = await supabase.from('tiers')
.update({ name:newName, price, color, description }).eq('name', params.name);
if (error) {
console.error('Error updating tier:', error);
return NextResponse.error();
}
return NextResponse.json({});
}

View File

@ -23,4 +23,4 @@ export async function POST(request: Request) {
}
return NextResponse.json(data);
}

View File

@ -1,13 +1,12 @@
"use client";
import { createClient } from "@/utils/supabase/client";
import React, { useState, useEffect } from 'react';
import Search from "@/components/neroshitron/search";
import Gallery from "@/components/neroshitron/gallery";
import { useRouter } from 'next/navigation';
import Masonry from "react-masonry-css";
import SearchInput from "@/components/neroshitron/search_input";
function PageComponent() {
const router = useRouter();
const [selectedGallery, setSelectedGallery] = useState<string | null>(null);
const [filePreviews, setFilePreviews] = useState<string[]>([]);
const [name, setName] = useState<string>('');
@ -87,7 +86,7 @@ function PageComponent() {
placeholder="Gallery Name"
/>
<div className="w-1/4">
<button onClick={() => window.location.href = "/gallery/admin"} className="w-full bg-error hover:bg-error-light text-white rounded-md p-2 shadow-lg">
<button onClick={() => router.push("/gallery/admin")} className="w-full bg-error hover:bg-error-light text-white rounded-md p-2 shadow-lg">
Back
</button>
</div>

View File

@ -1,13 +1,11 @@
"use client";
import { createClient } from "@/utils/supabase/client";
import React, { useState, useEffect } from 'react';
import Search from "@/components/neroshitron/search";
import Gallery from "@/components/neroshitron/gallery";
import Masonry from "react-masonry-css";
import SearchInput from "@/components/neroshitron/search_input";
import { useRouter } from 'next/navigation';
function PageComponent() {
const router = useRouter();
const supabase = createClient();
const user = supabase.auth.getUser();
const [tags, setTags] = useState<any[]>([]);
@ -62,18 +60,13 @@ function PageComponent() {
getData();
}, [tagsState, newTagName]);
const data = [
{ id: 1, name: "Item 1", imageCount: 5, tier: "Tier 1" },
{ id: 2, name: "Item 2", imageCount: 10, tier: "Tier 2" },
{ id: 3, name: "Item 3", imageCount: 8, tier: "Tier 1" },
];
return (
<div className="w-full p-8 h-max text-white lg:flex justify-center items-center animate-in">
<div className="w-full h-max lg:w-1/3 rounded-md bg-primary opacity-90 p-12 m-1 mt-32 shadow-lg backdrop-blur">
<div className="w-full flex">
<input value={newTagName} type="text" onChange={(e)=>{setNewTagName(e.target.value)}} className="hover:scale-105 focus:scale-105 mb-8 mr-2 rounded-md bg-info-bright p-2 w-1/2 text-black shadow-lg" placeholder="Tag Name" />
<button onClick={createTag} className="hover:scale-95 ml-2 shadow-lg w-1/2 h-10 text-center bg-success hover:bg-success-light text-white font-bold rounded flex items-center justify-center">
<input value={newTagName} type="text" onChange={(e)=>{setNewTagName(e.target.value)}} className=" mb-8 mr-2 rounded-md bg-info-bright p-2 w-1/2 text-black shadow-lg" placeholder="Tag Name" />
<button onClick={createTag} className=" ml-2 shadow-lg w-1/2 h-10 text-center bg-success hover:bg-success-light text-white font-bold rounded flex items-center justify-center">
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" strokeWidth={1.5} stroke="currentColor" className="lg:hidden size-6">
<path strokeLinecap="round" strokeLinejoin="round" d="M12 4.5v15m7.5-7.5h-15" />
</svg>
@ -83,7 +76,7 @@ function PageComponent() {
</button>
</div>
<div className="w-full flex">
<input type="text" value={tagSearch} onChange={(e)=>{setTagSearch(e.target.value)}} className="hover:scale-105 focus:scale-105 mb-8 shadow-lg mr-2 rounded-md bg-info-bright p-2 w-full text-black" placeholder="Search all tags by name" />
<input type="text" value={tagSearch} onChange={(e)=>{setTagSearch(e.target.value)}} className=" mb-8 shadow-lg mr-2 rounded-md bg-info-bright p-2 w-full text-black" placeholder="Search all tags by name" />
</div>
<div className="w-full h-96 overflow-y-scroll no-scrollbar">
<table className="w-full bg-primary-light rounded">
@ -94,7 +87,7 @@ function PageComponent() {
<tr key={item.name} className="hover:bg-secondary-dark animate-in shadow">
<td className="px-4 py-2">{item.name}</td>
<td className="px-4 py-2">
<button onClick={()=>{deleteTag(item.name)}} className="hover:scale-95 bg-error shadow-lg hover:bg-error-light text-white font-bold py-2 px-4 rounded float-right">
<button onClick={()=>{deleteTag(item.name)}} className=" bg-error shadow-lg hover:bg-error-light text-white font-bold py-2 px-4 rounded float-right">
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" strokeWidth={1.5} stroke="currentColor" className="size-6">
<path strokeLinecap="round" strokeLinejoin="round" d="m14.74 9-.346 9m-4.788 0L9.26 9m9.968-3.21c.342.052.682.107 1.022.166m-1.022-.165L18.16 19.673a2.25 2.25 0 0 1-2.244 2.077H8.084a2.25 2.25 0 0 1-2.244-2.077L4.772 5.79m14.456 0a48.108 48.108 0 0 0-3.478-.397m-12 .562c.34-.059.68-.114 1.022-.165m0 0a48.11 48.11 0 0 1 3.478-.397m7.5 0v-.916c0-1.18-.91-2.164-2.09-2.201a51.964 51.964 0 0 0-3.32 0c-1.18.037-2.09 1.022-2.09 2.201v.916m7.5 0a48.667 48.667 0 0 0-7.5 0" />
</svg>
@ -107,22 +100,22 @@ function PageComponent() {
</table>
</div>
</div>
<div className="w-full h-max lg:w-1/2 rounded-md bg-primary opacity-90 backdrop-blur-lg p-12 shadow-lg">
<div className="w-full fixed flex pb-2 z-20">
<div className="w-4/6">
<div className="w-full h-max lg:w-1/2 rounded-md bg-primary opacity-90 backdrop-blur-lg p-4 shadow-lg">
<div className="w-full pb-2 flex">
<div className="fixed w-4/5 z-20">
<SearchInput
startingTags={[]}
placeholderTags={[
{ value: "tags", label: "❗️ click here to add tags to search" }
]} nsfwButtonEnabled={false} searchChanged={(search) => { setSearchState(search) }} nsfwChanged={(nsfw) => { setNsfwState(nsfw) }} tagsChanged={(tags) => { setTagsState(tags) }} />
</div>
<a href="/gallery/admin/create" className="w-1/6 hover:scale-95 ml-2 p-2 shadow-lg h-10 text-center bg-success hover:bg-success-light text-white font-bold rounded flex items-center justify-center">
<button onClick={()=>{router.push("/gallery/admin/create")}} className="right-0 mr-2 mt-2 fixed w-1/6 ml-2 p-2 shadow-lg h-10 text-center bg-success hover:bg-success-light text-white font-bold rounded flex items-center justify-center">
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" strokeWidth={1.5} stroke="currentColor" className="xl:hidden size-6">
<path strokeLinecap="round" strokeLinejoin="round" d="M12 4.5v15m7.5-7.5h-15" />
</svg>
<span className="xl:block hidden">New Gallery</span>
</a>
</button>
</div>
<div className="w-full h-96 overflow-y-scroll no-scrollbar">
<table className="w-full mt-20 bg-primary-light rounded">
@ -134,7 +127,7 @@ function PageComponent() {
<td className="px-4 py-2">{item.imageCount}</td>
<td className="px-4 py-2">{item.tier}</td>
<td className="px-4 py-2">
<button onClick={()=>{ window.location.href=`/gallery/admin/view?id=${encodeURIComponent(item.name)}`}} className="bg-secondary hover:scale-95 shadow-lg hover:bg-secondary-light text-white font-bold py-2 px-4 rounded float-right">
<button onClick={()=>{ router.push(`/gallery/admin/view?id=${encodeURIComponent(item.name)}`)}} className="bg-secondary shadow-lg hover:bg-secondary-light text-white font-bold py-2 px-4 rounded float-right">
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" strokeWidth={1.5} stroke="currentColor" className="size-6">
<path strokeLinecap="round" strokeLinejoin="round" d="M19.5 14.25v-2.625a3.375 3.375 0 0 0-3.375-3.375h-1.5A1.125 1.125 0 0 1 13.5 7.125v-1.5a3.375 3.375 0 0 0-3.375-3.375H8.25m5.231 13.481L15 17.25m-4.5-15H5.625c-.621 0-1.125.504-1.125 1.125v16.5c0 .621.504 1.125 1.125 1.125h12.75c.621 0 1.125-.504 1.125-1.125V11.25a9 9 0 0 0-9-9Zm3.75 11.625a2.625 2.625 0 1 1-5.25 0 2.625 2.625 0 0 1 5.25 0Z" />
</svg>

View File

@ -1,9 +1,8 @@
"use client";
import { createClient } from "@/utils/supabase/client";
import React, { useState, useEffect } from 'react';
import Search from "@/components/neroshitron/search";
import { useRouter } from 'next/navigation';
import Gallery from "@/components/neroshitron/gallery";
import Masonry from "react-masonry-css";
import SearchInput from "@/components/neroshitron/search_input";
import GalleryThumbnail from "@/components/neroshitron/gallery_thumbnail";
@ -20,6 +19,7 @@ function PageComponent() {
const [thumbnail, setThumbnail] = useState<string>();
const [fileNames, setFileNames] = useState<string[]>([]);
const [selectedTags, setSelectedTags] = useState<string[]>([]);
const router = useRouter();
const [open, setOpen] = useState<boolean>(false);
@ -97,7 +97,7 @@ function PageComponent() {
console.log(response)
}
if(originalName != galleryName){
window.location.href=`/gallery/admin/view?id=${galleryName}`
router.push(`/gallery/admin/view?id=${galleryName}`)
}
else{
window.location.reload();
@ -115,7 +115,7 @@ function PageComponent() {
});
if (response.ok) {
const data = await response.json();
window.location.href = "/gallery/admin";
router.push("/gallery/admin");
} else {
console.log(response)
}
@ -161,7 +161,7 @@ function PageComponent() {
</div>
<div className="w-1/6">
<button
onClick={() => (window.location.href = "/gallery/admin")}
onClick={() => (router.push("/gallery/admin"))}
className="w-full bg-error-dark hover:bg-error text-white rounded-md p-2 ml-2 flex items-center justify-center"
>
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" strokeWidth={1.5}

View File

@ -79,3 +79,33 @@
transform: translateY(0);
}
}
button:disabled {
filter: grayscale(50%);
}
:root {
--color-primary: #201240;
--color-primary-light: #403260;
--color-primary-dark: #100120;
--color-secondary: #4F3D70;
--color-secondary-light: #6F5D90;
--color-secondary-dark: #2F1D50;
--color-error: #862117;
--color-error-light: #C44C4C;
--color-error-dark: #5C0D0D;
--color-success: #00C9A6;
--color-success-light: #20E9C6;
--color-success-dark: #00A986;
--color-warning: #E17558;
--color-warning-light: #E39578;
--color-warning-dark: #C15538;
--color-info: #222140;
--color-info-light: #424260;
--color-info-dark: #020120;
}

View File

@ -1,9 +1,11 @@
import { GeistSans } from "geist/font/sans";
import "./globals.css";
import { createClient } from "@/utils/supabase/client";
import NavigationBar from "@/components/neroshitron/navigation_bar";
import { SpeedInsights } from "@vercel/speed-insights/next"
import { Analytics } from "@vercel/analytics/react"
import RightHandLayoutImage from "@/components/neroshitron/right_hand_layout_image";
import Theme from "@/components/theme";
const defaultUrl = process.env.VERCEL_URL
? `https://${process.env.VERCEL_URL}`
: "http://localhost:3000";
@ -14,6 +16,10 @@ export const metadata = {
description: "The fastest way to build apps with Next.js and Supabase",
};
const supabase = createClient();
export default function RootLayout({
children,
}: {
@ -22,6 +28,7 @@ export default function RootLayout({
return (
<html lang="en" className={GeistSans.className}>
<body className="bg-background text-foreground">
<Theme/>
<RightHandLayoutImage/>
<div className="w-full fixed z-30 text-white white">
<NavigationBar/>

View File

@ -48,7 +48,7 @@ export default async function AuthButton() {
return (
<div className="flex justify-center items-center pt-2 ">
<nav className="w-auto bg-primary-dark bg-opacity-40 flex justify-center z-10 h-16 animate-in rounded-md shadow-lg" style={{ backdropFilter: 'blur(10px)' }}>
<nav className="w-auto bg-primary bg-opacity-40 flex justify-center z-10 h-16 animate-in rounded-md shadow-lg" style={{ backdropFilter: 'blur(10px)' }}>
<div className="w-auto flex justify-between items-center p-3 text-sm">
<div className="flex items-center gap-2 z-10">
@ -58,7 +58,7 @@ export default async function AuthButton() {
<>
<Link
href="/gallery/admin/"
className={`py-2 px-3 w-38 text-center flex rounded-md no-underline ${currentPage!="gallery" ? 'bg-secondary hover:bg-secondary-light' : 'bg-secondary hover:bg-secondary-light'}`}
className={`py-2 px-3 w-38 text-center flex rounded-md no-underline bg-secondary hover:bg-secondary-light`}
>
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" strokeWidth={1.5} stroke="currentColor" className="lg:hidden size-6">
<path strokeLinecap="round" strokeLinejoin="round" d="M11.42 15.17 17.25 21A2.652 2.652 0 0 0 21 17.25l-5.877-5.877M11.42 15.17l2.496-3.03c.317-.384.74-.626 1.208-.766M11.42 15.17l-4.655 5.653a2.548 2.548 0 1 1-3.586-3.586l6.837-5.63m5.108-.233c.55-.164 1.163-.188 1.743-.14a4.5 4.5 0 0 0 4.486-6.336l-3.276 3.277a3.004 3.004 0 0 1-2.25-2.25l3.276-3.276a4.5 4.5 0 0 0-6.336 4.486c.091 1.076-.071 2.264-.904 2.95l-.102.085m-1.745 1.437L5.909 7.5H4.5L2.25 3.75l1.5-1.5L7.5 4.5v1.409l4.26 4.26m-1.745 1.437 1.745-1.437m6.615 8.206L15.75 15.75M4.867 19.125h.008v.008h-.008v-.008Z" />
@ -67,7 +67,7 @@ export default async function AuthButton() {
</Link>
<Link
href="/admin/"
className={`py-2 px-3 w-38 text-center flex rounded-md no-underline ${currentPage!="gallery" ? 'bg-secondary hover:bg-secondary-light' : 'bg-secondary hover:bg-secondary-light'}`}
className={`py-2 px-3 w-38 text-center flex rounded-md no-underline bg-secondary hover:bg-secondary-light`}
>
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" strokeWidth={1.5} stroke="currentColor" className="lg:hidden size-6">
<path strokeLinecap="round" strokeLinejoin="round" d="M9.594 3.94c.09-.542.56-.94 1.11-.94h2.593c.55 0 1.02.398 1.11.94l.213 1.281c.063.374.313.686.645.87.074.04.147.083.22.127.325.196.72.257 1.075.124l1.217-.456a1.125 1.125 0 0 1 1.37.49l1.296 2.247a1.125 1.125 0 0 1-.26 1.431l-1.003.827c-.293.241-.438.613-.43.992a7.723 7.723 0 0 1 0 .255c-.008.378.137.75.43.991l1.004.827c.424.35.534.955.26 1.43l-1.298 2.247a1.125 1.125 0 0 1-1.369.491l-1.217-.456c-.355-.133-.75-.072-1.076.124a6.47 6.47 0 0 1-.22.128c-.331.183-.581.495-.644.869l-.213 1.281c-.09.543-.56.94-1.11.94h-2.594c-.55 0-1.019-.398-1.11-.94l-.213-1.281c-.062-.374-.312-.686-.644-.87a6.52 6.52 0 0 1-.22-.127c-.325-.196-.72-.257-1.076-.124l-1.217.456a1.125 1.125 0 0 1-1.369-.49l-1.297-2.247a1.125 1.125 0 0 1 .26-1.431l1.004-.827c.292-.24.437-.613.43-.991a6.932 6.932 0 0 1 0-.255c.007-.38-.138-.751-.43-.992l-1.004-.827a1.125 1.125 0 0 1-.26-1.43l1.297-2.247a1.125 1.125 0 0 1 1.37-.491l1.216.456c.356.133.751.072 1.076-.124.072-.044.146-.086.22-.128.332-.183.582-.495.644-.869l.214-1.28Z" />

37
components/theme.tsx Normal file
View File

@ -0,0 +1,37 @@
"use client";
import { useEffect, useState } from 'react';
import { createClient } from '@/utils/supabase/client';
interface GalleryThumbnailProps {}
const ThemeProvider = ({}: GalleryThumbnailProps) => {
const [data, setData] = useState<any[]>([]); // State to store the fetched data
const getData = async () => {
const supabase = createClient();
const { data, error } = await supabase.from('interface_configurations').select('*');
if (error) {
console.error('Error fetching data:', error);
} else {
setData(data || []);
}
};
useEffect(() => {
getData();
}, []);
useEffect(() => {
// Update variables when data changes
for (const config of data) {
if (config.type === 'color') {
document.documentElement.style.setProperty(`--color-${config.name}`, config.value);
}
}
}, [data]);
return <></>;
};
export default ThemeProvider;

503
docs/.$diagrams.drawio.bkp Normal file
View File

@ -0,0 +1,503 @@
<mxfile host="Electron" modified="2024-06-04T04:27:05.636Z" agent="Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) draw.io/24.2.5 Chrome/120.0.6099.109 Electron/28.1.0 Safari/537.36" etag="x7V6P6bjO-UHE86F-Cl3" version="24.2.5" type="device">
<diagram name="Page-1" id="F3YAVjulPUqdYhbqfjdd">
<mxGraphModel dx="1877" dy="2420" grid="1" gridSize="10" guides="1" tooltips="1" connect="1" arrows="1" fold="1" page="1" pageScale="1" pageWidth="850" pageHeight="1100" math="0" shadow="0">
<root>
<mxCell id="0" />
<mxCell id="1" parent="0" />
<mxCell id="9zziB1Dtd-V9IfowJO3V-28" value="&lt;h1&gt;Database Design&lt;/h1&gt;" style="text;html=1;align=center;verticalAlign=middle;whiteSpace=wrap;rounded=0;" parent="1" vertex="1">
<mxGeometry x="332.5" y="-70" width="390" height="10" as="geometry" />
</mxCell>
<mxCell id="9zziB1Dtd-V9IfowJO3V-29" value="&lt;h1&gt;UX Flow&lt;/h1&gt;" style="text;html=1;align=center;verticalAlign=middle;whiteSpace=wrap;rounded=0;" parent="1" vertex="1">
<mxGeometry x="30" y="620" width="175" height="30" as="geometry" />
</mxCell>
<mxCell id="9zziB1Dtd-V9IfowJO3V-37" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;" parent="1" source="9zziB1Dtd-V9IfowJO3V-33" target="9zziB1Dtd-V9IfowJO3V-36" edge="1">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="9zziB1Dtd-V9IfowJO3V-33" value="Actor" style="shape=umlActor;verticalLabelPosition=bottom;verticalAlign=top;html=1;outlineConnect=0;" parent="1" vertex="1">
<mxGeometry x="35" y="690" width="30" height="60" as="geometry" />
</mxCell>
<mxCell id="9zziB1Dtd-V9IfowJO3V-39" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;" parent="1" source="9zziB1Dtd-V9IfowJO3V-36" target="9zziB1Dtd-V9IfowJO3V-38" edge="1">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="9zziB1Dtd-V9IfowJO3V-36" value="Open Site" style="whiteSpace=wrap;html=1;verticalAlign=top;" parent="1" vertex="1">
<mxGeometry x="105" y="705" width="120" height="30" as="geometry" />
</mxCell>
<mxCell id="9zziB1Dtd-V9IfowJO3V-42" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;" parent="1" source="9zziB1Dtd-V9IfowJO3V-38" target="9zziB1Dtd-V9IfowJO3V-41" edge="1">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="9zziB1Dtd-V9IfowJO3V-43" value="No" style="edgeLabel;html=1;align=center;verticalAlign=middle;resizable=0;points=[];" parent="9zziB1Dtd-V9IfowJO3V-42" vertex="1" connectable="0">
<mxGeometry x="0.2533" y="2" relative="1" as="geometry">
<mxPoint x="2" as="offset" />
</mxGeometry>
</mxCell>
<mxCell id="9zziB1Dtd-V9IfowJO3V-48" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;" parent="1" source="9zziB1Dtd-V9IfowJO3V-38" target="9zziB1Dtd-V9IfowJO3V-47" edge="1">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="9zziB1Dtd-V9IfowJO3V-72" value="Yes" style="edgeLabel;html=1;align=center;verticalAlign=middle;resizable=0;points=[];" parent="9zziB1Dtd-V9IfowJO3V-48" vertex="1" connectable="0">
<mxGeometry x="-0.2273" relative="1" as="geometry">
<mxPoint as="offset" />
</mxGeometry>
</mxCell>
<mxCell id="9zziB1Dtd-V9IfowJO3V-73" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=0;exitY=1;exitDx=0;exitDy=0;entryX=1;entryY=0.5;entryDx=0;entryDy=0;" parent="1" source="9zziB1Dtd-V9IfowJO3V-38" target="9zziB1Dtd-V9IfowJO3V-71" edge="1">
<mxGeometry relative="1" as="geometry">
<Array as="points">
<mxPoint x="265" y="740" />
<mxPoint x="265" y="795" />
</Array>
</mxGeometry>
</mxCell>
<mxCell id="9zziB1Dtd-V9IfowJO3V-74" value="Yes" style="edgeLabel;html=1;align=center;verticalAlign=middle;resizable=0;points=[];" parent="9zziB1Dtd-V9IfowJO3V-73" vertex="1" connectable="0">
<mxGeometry x="0.0411" y="1" relative="1" as="geometry">
<mxPoint as="offset" />
</mxGeometry>
</mxCell>
<mxCell id="9zziB1Dtd-V9IfowJO3V-82" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=0.5;exitY=1;exitDx=0;exitDy=0;entryX=0.5;entryY=0;entryDx=0;entryDy=0;" parent="1" source="9zziB1Dtd-V9IfowJO3V-38" target="9zziB1Dtd-V9IfowJO3V-81" edge="1">
<mxGeometry relative="1" as="geometry">
<Array as="points">
<mxPoint x="305" y="890" />
<mxPoint x="93" y="890" />
<mxPoint x="93" y="940" />
</Array>
</mxGeometry>
</mxCell>
<mxCell id="9zziB1Dtd-V9IfowJO3V-83" value="Yes" style="edgeLabel;html=1;align=center;verticalAlign=middle;resizable=0;points=[];" parent="9zziB1Dtd-V9IfowJO3V-82" vertex="1" connectable="0">
<mxGeometry x="-0.8649" y="-1" relative="1" as="geometry">
<mxPoint as="offset" />
</mxGeometry>
</mxCell>
<mxCell id="9zziB1Dtd-V9IfowJO3V-92" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=1;exitY=1;exitDx=0;exitDy=0;entryX=0.5;entryY=0;entryDx=0;entryDy=0;" parent="1" source="9zziB1Dtd-V9IfowJO3V-38" target="9zziB1Dtd-V9IfowJO3V-91" edge="1">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="9zziB1Dtd-V9IfowJO3V-93" value="Yes" style="edgeLabel;html=1;align=center;verticalAlign=middle;resizable=0;points=[];" parent="9zziB1Dtd-V9IfowJO3V-92" vertex="1" connectable="0">
<mxGeometry x="-0.6335" y="-2" relative="1" as="geometry">
<mxPoint as="offset" />
</mxGeometry>
</mxCell>
<mxCell id="9zziB1Dtd-V9IfowJO3V-38" value="&lt;br&gt;Logged&lt;br&gt;In" style="rhombus;whiteSpace=wrap;html=1;verticalAlign=top;" parent="1" vertex="1">
<mxGeometry x="265" y="680" width="80" height="80" as="geometry" />
</mxCell>
<mxCell id="9zziB1Dtd-V9IfowJO3V-46" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;" parent="1" source="9zziB1Dtd-V9IfowJO3V-41" target="9zziB1Dtd-V9IfowJO3V-45" edge="1">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="9zziB1Dtd-V9IfowJO3V-41" value="Login/Signup Page" style="whiteSpace=wrap;html=1;verticalAlign=top;fillColor=#a20025;strokeColor=#6F0000;fontColor=#ffffff;" parent="1" vertex="1">
<mxGeometry x="245" y="620" width="120" height="30" as="geometry" />
</mxCell>
<mxCell id="9zziB1Dtd-V9IfowJO3V-49" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=1;exitY=0.5;exitDx=0;exitDy=0;entryX=0.5;entryY=0;entryDx=0;entryDy=0;dashed=1;" parent="1" source="9zziB1Dtd-V9IfowJO3V-45" target="9zziB1Dtd-V9IfowJO3V-47" edge="1">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="9zziB1Dtd-V9IfowJO3V-50" value="Click Activation&lt;br&gt;Email Link" style="edgeLabel;html=1;align=center;verticalAlign=middle;resizable=0;points=[];" parent="9zziB1Dtd-V9IfowJO3V-49" vertex="1" connectable="0">
<mxGeometry x="0.1683" y="1" relative="1" as="geometry">
<mxPoint as="offset" />
</mxGeometry>
</mxCell>
<mxCell id="9zziB1Dtd-V9IfowJO3V-45" value="Send Confirmation Email" style="whiteSpace=wrap;html=1;verticalAlign=top;fillColor=#a20025;strokeColor=#6F0000;fontColor=#ffffff;" parent="1" vertex="1">
<mxGeometry x="235" y="560" width="140" height="30" as="geometry" />
</mxCell>
<mxCell id="9zziB1Dtd-V9IfowJO3V-52" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=1;exitY=0.5;exitDx=0;exitDy=0;" parent="1" source="9zziB1Dtd-V9IfowJO3V-47" target="9zziB1Dtd-V9IfowJO3V-51" edge="1">
<mxGeometry relative="1" as="geometry">
<mxPoint x="540" y="716.31" as="sourcePoint" />
</mxGeometry>
</mxCell>
<mxCell id="9zziB1Dtd-V9IfowJO3V-47" value="Gallery Page" style="whiteSpace=wrap;html=1;verticalAlign=top;fillColor=#1ba1e2;strokeColor=#006EAF;fontColor=#ffffff;" parent="1" vertex="1">
<mxGeometry x="440" y="705" width="120" height="30" as="geometry" />
</mxCell>
<mxCell id="9zziB1Dtd-V9IfowJO3V-54" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;" parent="1" source="9zziB1Dtd-V9IfowJO3V-51" target="9zziB1Dtd-V9IfowJO3V-53" edge="1">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="9zziB1Dtd-V9IfowJO3V-51" value="Search By Title &amp;amp;&lt;br&gt;Filter By Tag" style="whiteSpace=wrap;html=1;verticalAlign=top;fillColor=#1ba1e2;strokeColor=#006EAF;fontColor=#ffffff;" parent="1" vertex="1">
<mxGeometry x="642" y="698.02" width="120" height="45" as="geometry" />
</mxCell>
<mxCell id="9zziB1Dtd-V9IfowJO3V-55" value="Refine Search" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=0.5;exitY=0;exitDx=0;exitDy=0;entryX=0.5;entryY=0;entryDx=0;entryDy=0;" parent="1" source="9zziB1Dtd-V9IfowJO3V-53" target="9zziB1Dtd-V9IfowJO3V-51" edge="1">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="9zziB1Dtd-V9IfowJO3V-57" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;" parent="1" source="9zziB1Dtd-V9IfowJO3V-53" target="9zziB1Dtd-V9IfowJO3V-56" edge="1">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="9zziB1Dtd-V9IfowJO3V-53" value="Browse Galleries" style="whiteSpace=wrap;html=1;verticalAlign=top;fillColor=#1ba1e2;strokeColor=#006EAF;fontColor=#ffffff;" parent="1" vertex="1">
<mxGeometry x="802" y="704.27" width="120" height="32.5" as="geometry" />
</mxCell>
<mxCell id="9zziB1Dtd-V9IfowJO3V-59" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;" parent="1" source="9zziB1Dtd-V9IfowJO3V-56" target="9zziB1Dtd-V9IfowJO3V-58" edge="1">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="9zziB1Dtd-V9IfowJO3V-56" value="Open Gallery" style="whiteSpace=wrap;html=1;verticalAlign=top;fillColor=#1ba1e2;strokeColor=#006EAF;fontColor=#ffffff;" parent="1" vertex="1">
<mxGeometry x="802" y="780.52" width="120" height="32.5" as="geometry" />
</mxCell>
<mxCell id="9zziB1Dtd-V9IfowJO3V-61" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;" parent="1" source="9zziB1Dtd-V9IfowJO3V-58" target="9zziB1Dtd-V9IfowJO3V-60" edge="1">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="9zziB1Dtd-V9IfowJO3V-63" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;entryX=0.5;entryY=0;entryDx=0;entryDy=0;exitX=0;exitY=0.5;exitDx=0;exitDy=0;" parent="1" source="9zziB1Dtd-V9IfowJO3V-58" target="9zziB1Dtd-V9IfowJO3V-62" edge="1">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="9zziB1Dtd-V9IfowJO3V-65" value="Directional&lt;br&gt;Buttons" style="edgeLabel;html=1;align=center;verticalAlign=middle;resizable=0;points=[];" parent="9zziB1Dtd-V9IfowJO3V-63" vertex="1" connectable="0">
<mxGeometry x="0.1714" relative="1" as="geometry">
<mxPoint as="offset" />
</mxGeometry>
</mxCell>
<mxCell id="9zziB1Dtd-V9IfowJO3V-69" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=0;exitY=0.25;exitDx=0;exitDy=0;entryX=0.75;entryY=1;entryDx=0;entryDy=0;" parent="1" source="9zziB1Dtd-V9IfowJO3V-58" target="9zziB1Dtd-V9IfowJO3V-68" edge="1">
<mxGeometry relative="1" as="geometry">
<Array as="points">
<mxPoint x="742" y="850.52" />
<mxPoint x="742" y="840.52" />
<mxPoint x="732" y="840.52" />
</Array>
</mxGeometry>
</mxCell>
<mxCell id="9zziB1Dtd-V9IfowJO3V-58" value="Enlarge Image &amp;amp;&amp;nbsp;&lt;br&gt;Pan/Zoom" style="whiteSpace=wrap;html=1;verticalAlign=top;fillColor=#1ba1e2;strokeColor=#006EAF;fontColor=#ffffff;" parent="1" vertex="1">
<mxGeometry x="802" y="840.52" width="120" height="40" as="geometry" />
</mxCell>
<mxCell id="9zziB1Dtd-V9IfowJO3V-60" value="Download Image" style="whiteSpace=wrap;html=1;verticalAlign=top;fillColor=#1ba1e2;strokeColor=#006EAF;fontColor=#ffffff;" parent="1" vertex="1">
<mxGeometry x="802" y="900.52" width="120" height="30" as="geometry" />
</mxCell>
<mxCell id="9zziB1Dtd-V9IfowJO3V-64" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=0.5;exitY=1;exitDx=0;exitDy=0;entryX=0;entryY=0.75;entryDx=0;entryDy=0;" parent="1" source="9zziB1Dtd-V9IfowJO3V-62" target="9zziB1Dtd-V9IfowJO3V-58" edge="1">
<mxGeometry relative="1" as="geometry">
<Array as="points">
<mxPoint x="672" y="960.52" />
<mxPoint x="782" y="960.52" />
<mxPoint x="782" y="870.52" />
</Array>
</mxGeometry>
</mxCell>
<mxCell id="9zziB1Dtd-V9IfowJO3V-62" value="Next/Previous&lt;br&gt;Image" style="whiteSpace=wrap;html=1;verticalAlign=top;fillColor=#1ba1e2;strokeColor=#006EAF;fontColor=#ffffff;" parent="1" vertex="1">
<mxGeometry x="612" y="890.52" width="120" height="40" as="geometry" />
</mxCell>
<mxCell id="9zziB1Dtd-V9IfowJO3V-70" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=1;exitY=0.25;exitDx=0;exitDy=0;entryX=0;entryY=0.5;entryDx=0;entryDy=0;" parent="1" source="9zziB1Dtd-V9IfowJO3V-68" target="9zziB1Dtd-V9IfowJO3V-56" edge="1">
<mxGeometry relative="1" as="geometry">
<mxPoint x="762" y="797.39" as="sourcePoint" />
<mxPoint x="792" y="796.14" as="targetPoint" />
<Array as="points">
<mxPoint x="762" y="796.52" />
</Array>
</mxGeometry>
</mxCell>
<mxCell id="9zziB1Dtd-V9IfowJO3V-68" value="Close Image" style="whiteSpace=wrap;html=1;verticalAlign=top;fillColor=#1ba1e2;strokeColor=#006EAF;fontColor=#ffffff;" parent="1" vertex="1">
<mxGeometry x="642" y="787.52" width="120" height="30" as="geometry" />
</mxCell>
<mxCell id="9zziB1Dtd-V9IfowJO3V-76" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;" parent="1" source="9zziB1Dtd-V9IfowJO3V-71" target="9zziB1Dtd-V9IfowJO3V-75" edge="1">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="9zziB1Dtd-V9IfowJO3V-78" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;" parent="1" source="9zziB1Dtd-V9IfowJO3V-71" target="9zziB1Dtd-V9IfowJO3V-77" edge="1">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="9zziB1Dtd-V9IfowJO3V-71" value="Livestream Page" style="whiteSpace=wrap;html=1;verticalAlign=top;fillColor=#d80073;strokeColor=#A50040;fontColor=#ffffff;" parent="1" vertex="1">
<mxGeometry x="125" y="780" width="120" height="30" as="geometry" />
</mxCell>
<mxCell id="9zziB1Dtd-V9IfowJO3V-75" value="Watch Stream" style="whiteSpace=wrap;html=1;verticalAlign=top;fillColor=#d80073;strokeColor=#A50040;fontColor=#ffffff;" parent="1" vertex="1">
<mxGeometry x="125" y="840" width="120" height="30" as="geometry" />
</mxCell>
<mxCell id="9zziB1Dtd-V9IfowJO3V-77" value="Chat" style="whiteSpace=wrap;html=1;verticalAlign=top;fillColor=#d80073;strokeColor=#A50040;fontColor=#ffffff;" parent="1" vertex="1">
<mxGeometry x="12.5" y="780" width="75" height="30" as="geometry" />
</mxCell>
<mxCell id="9zziB1Dtd-V9IfowJO3V-85" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;fillColor=#d5e8d4;strokeColor=#82b366;" parent="1" source="9zziB1Dtd-V9IfowJO3V-81" target="9zziB1Dtd-V9IfowJO3V-84" edge="1">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="9zziB1Dtd-V9IfowJO3V-87" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;fillColor=#d5e8d4;strokeColor=#82b366;" parent="1" source="9zziB1Dtd-V9IfowJO3V-81" target="9zziB1Dtd-V9IfowJO3V-86" edge="1">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="9zziB1Dtd-V9IfowJO3V-81" value="Subscriptions Page" style="rounded=0;whiteSpace=wrap;html=1;fillColor=#6a00ff;strokeColor=#3700CC;fontColor=#ffffff;" parent="1" vertex="1">
<mxGeometry x="32.5" y="940" width="120" height="30" as="geometry" />
</mxCell>
<mxCell id="9zziB1Dtd-V9IfowJO3V-84" value="View Current Tier" style="rounded=0;whiteSpace=wrap;html=1;fillColor=#6a00ff;strokeColor=#3700CC;fontColor=#ffffff;" parent="1" vertex="1">
<mxGeometry x="32.5" y="990" width="120" height="30" as="geometry" />
</mxCell>
<mxCell id="9zziB1Dtd-V9IfowJO3V-89" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;fillColor=#d5e8d4;strokeColor=#82b366;" parent="1" source="9zziB1Dtd-V9IfowJO3V-86" target="9zziB1Dtd-V9IfowJO3V-88" edge="1">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="9zziB1Dtd-V9IfowJO3V-86" value="View Available Tiers" style="rounded=0;whiteSpace=wrap;html=1;fillColor=#6a00ff;strokeColor=#3700CC;fontColor=#ffffff;" parent="1" vertex="1">
<mxGeometry x="187.5" y="940" width="120" height="30" as="geometry" />
</mxCell>
<mxCell id="9zziB1Dtd-V9IfowJO3V-90" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;fillColor=#d5e8d4;strokeColor=#82b366;" parent="1" source="9zziB1Dtd-V9IfowJO3V-88" target="9zziB1Dtd-V9IfowJO3V-84" edge="1">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="9zziB1Dtd-V9IfowJO3V-88" value="Upgrade Tier" style="rounded=0;whiteSpace=wrap;html=1;fillColor=#6a00ff;strokeColor=#3700CC;fontColor=#ffffff;" parent="1" vertex="1">
<mxGeometry x="187.5" y="990" width="120" height="30" as="geometry" />
</mxCell>
<mxCell id="9zziB1Dtd-V9IfowJO3V-95" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;" parent="1" source="9zziB1Dtd-V9IfowJO3V-91" target="9zziB1Dtd-V9IfowJO3V-94" edge="1">
<mxGeometry relative="1" as="geometry">
<Array as="points">
<mxPoint x="410" y="810" />
<mxPoint x="360" y="810" />
</Array>
</mxGeometry>
</mxCell>
<mxCell id="9zziB1Dtd-V9IfowJO3V-100" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;" parent="1" source="9zziB1Dtd-V9IfowJO3V-91" target="9zziB1Dtd-V9IfowJO3V-99" edge="1">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="9zziB1Dtd-V9IfowJO3V-91" value="Commissions Page" style="rounded=0;whiteSpace=wrap;html=1;fillColor=#60a917;strokeColor=#2D7600;fontColor=#ffffff;" parent="1" vertex="1">
<mxGeometry x="350" y="770" width="120" height="27.48" as="geometry" />
</mxCell>
<mxCell id="9zziB1Dtd-V9IfowJO3V-97" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;" parent="1" source="9zziB1Dtd-V9IfowJO3V-94" target="9zziB1Dtd-V9IfowJO3V-96" edge="1">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="9zziB1Dtd-V9IfowJO3V-98" value="Yes" style="edgeLabel;html=1;align=center;verticalAlign=middle;resizable=0;points=[];" parent="9zziB1Dtd-V9IfowJO3V-97" vertex="1" connectable="0">
<mxGeometry x="-0.6109" relative="1" as="geometry">
<mxPoint x="20" y="2" as="offset" />
</mxGeometry>
</mxCell>
<mxCell id="9zziB1Dtd-V9IfowJO3V-105" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;entryX=0;entryY=0;entryDx=0;entryDy=0;" parent="1" source="9zziB1Dtd-V9IfowJO3V-94" target="9zziB1Dtd-V9IfowJO3V-110" edge="1">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="9zziB1Dtd-V9IfowJO3V-106" value="No" style="edgeLabel;html=1;align=center;verticalAlign=middle;resizable=0;points=[];" parent="9zziB1Dtd-V9IfowJO3V-105" vertex="1" connectable="0">
<mxGeometry x="-0.1779" y="-2" relative="1" as="geometry">
<mxPoint y="-2" as="offset" />
</mxGeometry>
</mxCell>
<mxCell id="9zziB1Dtd-V9IfowJO3V-94" value="Has Existing&lt;br&gt;Commission" style="rhombus;whiteSpace=wrap;html=1;rounded=0;fillColor=#60a917;strokeColor=#2D7600;fontColor=#ffffff;" parent="1" vertex="1">
<mxGeometry x="310" y="830.52" width="100" height="100" as="geometry" />
</mxCell>
<mxCell id="9zziB1Dtd-V9IfowJO3V-101" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=1;exitY=0.5;exitDx=0;exitDy=0;entryX=0.75;entryY=1;entryDx=0;entryDy=0;" parent="1" source="9zziB1Dtd-V9IfowJO3V-96" target="9zziB1Dtd-V9IfowJO3V-99" edge="1">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="9zziB1Dtd-V9IfowJO3V-96" value="View Existing&lt;br&gt;Commission Status" style="whiteSpace=wrap;html=1;rounded=0;fillColor=#60a917;strokeColor=#2D7600;fontColor=#ffffff;" parent="1" vertex="1">
<mxGeometry x="350" y="970" width="120" height="60" as="geometry" />
</mxCell>
<mxCell id="9zziB1Dtd-V9IfowJO3V-99" value="View All Commissions" style="rounded=0;whiteSpace=wrap;html=1;fillColor=#60a917;strokeColor=#2D7600;fontColor=#ffffff;" parent="1" vertex="1">
<mxGeometry x="500" y="770" width="130" height="27.48" as="geometry" />
</mxCell>
<mxCell id="9zziB1Dtd-V9IfowJO3V-109" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=0.75;exitY=1;exitDx=0;exitDy=0;entryX=1;entryY=0.25;entryDx=0;entryDy=0;" parent="1" source="9zziB1Dtd-V9IfowJO3V-104" target="9zziB1Dtd-V9IfowJO3V-96" edge="1">
<mxGeometry relative="1" as="geometry">
<Array as="points">
<mxPoint x="560" y="985" />
</Array>
</mxGeometry>
</mxCell>
<mxCell id="9zziB1Dtd-V9IfowJO3V-104" value="Request New&lt;br&gt;Commission" style="whiteSpace=wrap;html=1;fillColor=#60a917;strokeColor=#2D7600;rounded=0;fontColor=#ffffff;" parent="1" vertex="1">
<mxGeometry x="470" y="817.52" width="120" height="39.48" as="geometry" />
</mxCell>
<mxCell id="9zziB1Dtd-V9IfowJO3V-111" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=0;exitY=1;exitDx=0;exitDy=0;entryX=0.75;entryY=0;entryDx=0;entryDy=0;" parent="1" source="9zziB1Dtd-V9IfowJO3V-110" target="9zziB1Dtd-V9IfowJO3V-96" edge="1">
<mxGeometry relative="1" as="geometry">
<Array as="points">
<mxPoint x="440" y="930" />
</Array>
</mxGeometry>
</mxCell>
<mxCell id="9zziB1Dtd-V9IfowJO3V-112" value="No" style="edgeLabel;html=1;align=center;verticalAlign=middle;resizable=0;points=[];" parent="9zziB1Dtd-V9IfowJO3V-111" vertex="1" connectable="0">
<mxGeometry x="0.0044" relative="1" as="geometry">
<mxPoint y="5" as="offset" />
</mxGeometry>
</mxCell>
<mxCell id="9zziB1Dtd-V9IfowJO3V-113" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=1;exitY=0;exitDx=0;exitDy=0;entryX=0.5;entryY=1;entryDx=0;entryDy=0;" parent="1" source="9zziB1Dtd-V9IfowJO3V-110" target="9zziB1Dtd-V9IfowJO3V-104" edge="1">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="9zziB1Dtd-V9IfowJO3V-114" value="Yes" style="edgeLabel;html=1;align=center;verticalAlign=middle;resizable=0;points=[];" parent="9zziB1Dtd-V9IfowJO3V-113" vertex="1" connectable="0">
<mxGeometry x="-0.5043" y="1" relative="1" as="geometry">
<mxPoint x="3" y="-1" as="offset" />
</mxGeometry>
</mxCell>
<mxCell id="9zziB1Dtd-V9IfowJO3V-110" value="Requests&lt;br&gt;Open" style="rhombus;whiteSpace=wrap;html=1;rounded=0;fillColor=#60a917;strokeColor=#2D7600;fontColor=#ffffff;" parent="1" vertex="1">
<mxGeometry x="440" y="860.52" width="79.48" height="79.48" as="geometry" />
</mxCell>
<mxCell id="1AZqCnQGpeGdDfHHl4o8-5" value="public.tags" style="swimlane;fontStyle=0;childLayout=stackLayout;horizontal=1;startSize=30;horizontalStack=0;resizeParent=1;resizeParentMax=0;resizeLast=0;collapsible=1;marginBottom=0;whiteSpace=wrap;html=1;fillColor=#1ba1e2;fontColor=#ffffff;strokeColor=#006EAF;" vertex="1" parent="1">
<mxGeometry x="207.5" y="440" width="140" height="60" as="geometry" />
</mxCell>
<mxCell id="1AZqCnQGpeGdDfHHl4o8-6" value="name" style="text;strokeColor=none;fillColor=none;align=left;verticalAlign=middle;spacingLeft=4;spacingRight=4;overflow=hidden;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;rotatable=0;whiteSpace=wrap;html=1;" vertex="1" parent="1AZqCnQGpeGdDfHHl4o8-5">
<mxGeometry y="30" width="140" height="30" as="geometry" />
</mxCell>
<mxCell id="1AZqCnQGpeGdDfHHl4o8-9" value="public.admins" style="swimlane;fontStyle=0;childLayout=stackLayout;horizontal=1;startSize=30;horizontalStack=0;resizeParent=1;resizeParentMax=0;resizeLast=0;collapsible=1;marginBottom=0;whiteSpace=wrap;html=1;fillColor=#1ba1e2;fontColor=#ffffff;strokeColor=#006EAF;" vertex="1" parent="1">
<mxGeometry x="243" y="60" width="175" height="120" as="geometry" />
</mxCell>
<mxCell id="1AZqCnQGpeGdDfHHl4o8-10" value="PK FK Unique uuid user_id" style="text;strokeColor=none;fillColor=none;align=left;verticalAlign=middle;spacingLeft=4;spacingRight=4;overflow=hidden;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;rotatable=0;whiteSpace=wrap;html=1;" vertex="1" parent="1AZqCnQGpeGdDfHHl4o8-9">
<mxGeometry y="30" width="175" height="30" as="geometry" />
</mxCell>
<mxCell id="1AZqCnQGpeGdDfHHl4o8-11" value="assigned_date:date" style="text;strokeColor=none;fillColor=none;align=left;verticalAlign=middle;spacingLeft=4;spacingRight=4;overflow=hidden;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;rotatable=0;whiteSpace=wrap;html=1;" vertex="1" parent="1AZqCnQGpeGdDfHHl4o8-9">
<mxGeometry y="60" width="175" height="30" as="geometry" />
</mxCell>
<mxCell id="1AZqCnQGpeGdDfHHl4o8-12" value="assigner_id:uuid?" style="text;strokeColor=none;fillColor=none;align=left;verticalAlign=middle;spacingLeft=4;spacingRight=4;overflow=hidden;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;rotatable=0;whiteSpace=wrap;html=1;" vertex="1" parent="1AZqCnQGpeGdDfHHl4o8-9">
<mxGeometry y="90" width="175" height="30" as="geometry" />
</mxCell>
<mxCell id="1AZqCnQGpeGdDfHHl4o8-17" value="auth.users" style="swimlane;fontStyle=0;childLayout=stackLayout;horizontal=1;startSize=30;horizontalStack=0;resizeParent=1;resizeParentMax=0;resizeLast=0;collapsible=1;marginBottom=0;whiteSpace=wrap;html=1;fillColor=#0050ef;fontColor=#ffffff;strokeColor=#001DBC;" vertex="1" parent="1">
<mxGeometry x="10" y="120" width="140" height="60" as="geometry" />
</mxCell>
<mxCell id="1AZqCnQGpeGdDfHHl4o8-18" value="id" style="text;strokeColor=none;fillColor=none;align=left;verticalAlign=middle;spacingLeft=4;spacingRight=4;overflow=hidden;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;rotatable=0;whiteSpace=wrap;html=1;" vertex="1" parent="1AZqCnQGpeGdDfHHl4o8-17">
<mxGeometry y="30" width="140" height="30" as="geometry" />
</mxCell>
<mxCell id="1AZqCnQGpeGdDfHHl4o8-21" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=1;exitY=0.5;exitDx=0;exitDy=0;entryX=0;entryY=0.5;entryDx=0;entryDy=0;fillColor=#0050ef;strokeColor=#001DBC;" edge="1" parent="1" source="1AZqCnQGpeGdDfHHl4o8-18" target="1AZqCnQGpeGdDfHHl4o8-10">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="1AZqCnQGpeGdDfHHl4o8-22" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=1;exitY=0.5;exitDx=0;exitDy=0;entryX=0;entryY=0.5;entryDx=0;entryDy=0;fillColor=#0050ef;strokeColor=#001DBC;" edge="1" parent="1" source="1AZqCnQGpeGdDfHHl4o8-18" target="1AZqCnQGpeGdDfHHl4o8-14">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="1AZqCnQGpeGdDfHHl4o8-23" value="public.tier" style="swimlane;fontStyle=0;childLayout=stackLayout;horizontal=1;startSize=30;horizontalStack=0;resizeParent=1;resizeParentMax=0;resizeLast=0;collapsible=1;marginBottom=0;whiteSpace=wrap;html=1;fillColor=#a20025;fontColor=#ffffff;strokeColor=#6F0000;" vertex="1" parent="1">
<mxGeometry x="32.5" y="290" width="140" height="120" as="geometry" />
</mxCell>
<mxCell id="1AZqCnQGpeGdDfHHl4o8-24" value="PK name:text" style="text;strokeColor=none;fillColor=none;align=left;verticalAlign=middle;spacingLeft=4;spacingRight=4;overflow=hidden;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;rotatable=0;whiteSpace=wrap;html=1;" vertex="1" parent="1AZqCnQGpeGdDfHHl4o8-23">
<mxGeometry y="30" width="140" height="30" as="geometry" />
</mxCell>
<mxCell id="1AZqCnQGpeGdDfHHl4o8-25" value="price:decimal" style="text;strokeColor=none;fillColor=none;align=left;verticalAlign=middle;spacingLeft=4;spacingRight=4;overflow=hidden;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;rotatable=0;whiteSpace=wrap;html=1;" vertex="1" parent="1AZqCnQGpeGdDfHHl4o8-23">
<mxGeometry y="60" width="140" height="30" as="geometry" />
</mxCell>
<mxCell id="1AZqCnQGpeGdDfHHl4o8-26" value="stripe_product_id:string" style="text;strokeColor=none;fillColor=none;align=left;verticalAlign=middle;spacingLeft=4;spacingRight=4;overflow=hidden;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;rotatable=0;whiteSpace=wrap;html=1;" vertex="1" parent="1AZqCnQGpeGdDfHHl4o8-23">
<mxGeometry y="90" width="140" height="30" as="geometry" />
</mxCell>
<mxCell id="1AZqCnQGpeGdDfHHl4o8-29" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=1;exitY=0.5;exitDx=0;exitDy=0;entryX=0;entryY=0.5;entryDx=0;entryDy=0;fillColor=#a20025;strokeColor=#6F0000;" edge="1" parent="1" source="1AZqCnQGpeGdDfHHl4o8-24" target="1AZqCnQGpeGdDfHHl4o8-15">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="1AZqCnQGpeGdDfHHl4o8-34" value="public.galleries" style="swimlane;fontStyle=0;childLayout=stackLayout;horizontal=1;startSize=30;horizontalStack=0;resizeParent=1;resizeParentMax=0;resizeLast=0;collapsible=1;marginBottom=0;whiteSpace=wrap;html=1;fillColor=#1ba1e2;fontColor=#ffffff;strokeColor=#006EAF;" vertex="1" parent="1">
<mxGeometry x="497.5" y="320" width="140" height="180" as="geometry" />
</mxCell>
<mxCell id="1AZqCnQGpeGdDfHHl4o8-35" value="PK string name" style="text;strokeColor=none;fillColor=none;align=left;verticalAlign=middle;spacingLeft=4;spacingRight=4;overflow=hidden;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;rotatable=0;whiteSpace=wrap;html=1;" vertex="1" parent="1AZqCnQGpeGdDfHHl4o8-34">
<mxGeometry y="30" width="140" height="30" as="geometry" />
</mxCell>
<mxCell id="1AZqCnQGpeGdDfHHl4o8-37" value="FK tier string" style="text;strokeColor=none;fillColor=none;align=left;verticalAlign=middle;spacingLeft=4;spacingRight=4;overflow=hidden;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;rotatable=0;whiteSpace=wrap;html=1;" vertex="1" parent="1AZqCnQGpeGdDfHHl4o8-34">
<mxGeometry y="60" width="140" height="30" as="geometry" />
</mxCell>
<mxCell id="1AZqCnQGpeGdDfHHl4o8-38" value="string thumbnail_file" style="text;strokeColor=none;fillColor=none;align=left;verticalAlign=middle;spacingLeft=4;spacingRight=4;overflow=hidden;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;rotatable=0;whiteSpace=wrap;html=1;" vertex="1" parent="1AZqCnQGpeGdDfHHl4o8-34">
<mxGeometry y="90" width="140" height="30" as="geometry" />
</mxCell>
<mxCell id="1AZqCnQGpeGdDfHHl4o8-41" value="bool nsfw" style="text;strokeColor=none;fillColor=none;align=left;verticalAlign=middle;spacingLeft=4;spacingRight=4;overflow=hidden;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;rotatable=0;whiteSpace=wrap;html=1;" vertex="1" parent="1AZqCnQGpeGdDfHHl4o8-34">
<mxGeometry y="120" width="140" height="30" as="geometry" />
</mxCell>
<mxCell id="1AZqCnQGpeGdDfHHl4o8-39" value="text[] tags" style="text;strokeColor=none;fillColor=none;align=left;verticalAlign=middle;spacingLeft=4;spacingRight=4;overflow=hidden;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;rotatable=0;whiteSpace=wrap;html=1;" vertex="1" parent="1AZqCnQGpeGdDfHHl4o8-34">
<mxGeometry y="150" width="140" height="30" as="geometry" />
</mxCell>
<mxCell id="1AZqCnQGpeGdDfHHl4o8-42" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=1;exitY=0.5;exitDx=0;exitDy=0;entryX=0;entryY=0.5;entryDx=0;entryDy=0;fillColor=#a20025;strokeColor=#6F0000;" edge="1" parent="1" source="1AZqCnQGpeGdDfHHl4o8-24" target="1AZqCnQGpeGdDfHHl4o8-37">
<mxGeometry relative="1" as="geometry">
<Array as="points">
<mxPoint x="207.5" y="335" />
<mxPoint x="207.5" y="395" />
</Array>
</mxGeometry>
</mxCell>
<mxCell id="1AZqCnQGpeGdDfHHl4o8-43" value="public.skibs" style="swimlane;fontStyle=0;childLayout=stackLayout;horizontal=1;startSize=30;horizontalStack=0;resizeParent=1;resizeParentMax=0;resizeLast=0;collapsible=1;marginBottom=0;whiteSpace=wrap;html=1;fillColor=#1ba1e2;fontColor=#ffffff;strokeColor=#006EAF;" vertex="1" parent="1">
<mxGeometry x="499.5" width="140" height="300" as="geometry" />
</mxCell>
<mxCell id="1AZqCnQGpeGdDfHHl4o8-44" value="PK AI id:&amp;nbsp;int8" style="text;strokeColor=none;fillColor=none;align=left;verticalAlign=middle;spacingLeft=4;spacingRight=4;overflow=hidden;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;rotatable=0;whiteSpace=wrap;html=1;" vertex="1" parent="1AZqCnQGpeGdDfHHl4o8-43">
<mxGeometry y="30" width="140" height="30" as="geometry" />
</mxCell>
<mxCell id="1AZqCnQGpeGdDfHHl4o8-46" value="amount:decimal" style="text;strokeColor=none;fillColor=none;align=left;verticalAlign=middle;spacingLeft=4;spacingRight=4;overflow=hidden;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;rotatable=0;whiteSpace=wrap;html=1;" vertex="1" parent="1AZqCnQGpeGdDfHHl4o8-43">
<mxGeometry y="60" width="140" height="30" as="geometry" />
</mxCell>
<mxCell id="1AZqCnQGpeGdDfHHl4o8-49" value="user_id:uuid" style="text;strokeColor=none;fillColor=none;align=left;verticalAlign=middle;spacingLeft=4;spacingRight=4;overflow=hidden;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;rotatable=0;whiteSpace=wrap;html=1;" vertex="1" parent="1AZqCnQGpeGdDfHHl4o8-43">
<mxGeometry y="90" width="140" height="30" as="geometry" />
</mxCell>
<mxCell id="1AZqCnQGpeGdDfHHl4o8-50" value="request_date:date" style="text;strokeColor=none;fillColor=none;align=left;verticalAlign=middle;spacingLeft=4;spacingRight=4;overflow=hidden;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;rotatable=0;whiteSpace=wrap;html=1;" vertex="1" parent="1AZqCnQGpeGdDfHHl4o8-43">
<mxGeometry y="120" width="140" height="30" as="geometry" />
</mxCell>
<mxCell id="1AZqCnQGpeGdDfHHl4o8-51" value="accepted:bool?" style="text;strokeColor=none;fillColor=none;align=left;verticalAlign=middle;spacingLeft=4;spacingRight=4;overflow=hidden;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;rotatable=0;whiteSpace=wrap;html=1;" vertex="1" parent="1AZqCnQGpeGdDfHHl4o8-43">
<mxGeometry y="150" width="140" height="30" as="geometry" />
</mxCell>
<mxCell id="1AZqCnQGpeGdDfHHl4o8-58" value="processed_date:date?" style="text;strokeColor=none;fillColor=none;align=left;verticalAlign=middle;spacingLeft=4;spacingRight=4;overflow=hidden;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;rotatable=0;whiteSpace=wrap;html=1;" vertex="1" parent="1AZqCnQGpeGdDfHHl4o8-43">
<mxGeometry y="180" width="140" height="30" as="geometry" />
</mxCell>
<mxCell id="1AZqCnQGpeGdDfHHl4o8-52" value="payment_url:string" style="text;strokeColor=none;fillColor=none;align=left;verticalAlign=middle;spacingLeft=4;spacingRight=4;overflow=hidden;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;rotatable=0;whiteSpace=wrap;html=1;" vertex="1" parent="1AZqCnQGpeGdDfHHl4o8-43">
<mxGeometry y="210" width="140" height="30" as="geometry" />
</mxCell>
<mxCell id="1AZqCnQGpeGdDfHHl4o8-57" value="paidDate:date?" style="text;strokeColor=none;fillColor=none;align=left;verticalAlign=middle;spacingLeft=4;spacingRight=4;overflow=hidden;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;rotatable=0;whiteSpace=wrap;html=1;" vertex="1" parent="1AZqCnQGpeGdDfHHl4o8-43">
<mxGeometry y="240" width="140" height="30" as="geometry" />
</mxCell>
<mxCell id="1AZqCnQGpeGdDfHHl4o8-59" value="completedDate:date?" style="text;strokeColor=none;fillColor=none;align=left;verticalAlign=middle;spacingLeft=4;spacingRight=4;overflow=hidden;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;rotatable=0;whiteSpace=wrap;html=1;" vertex="1" parent="1AZqCnQGpeGdDfHHl4o8-43">
<mxGeometry y="270" width="140" height="30" as="geometry" />
</mxCell>
<mxCell id="1AZqCnQGpeGdDfHHl4o8-48" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=1;exitY=0.5;exitDx=0;exitDy=0;entryX=0;entryY=0.5;entryDx=0;entryDy=0;dashed=1;startArrow=classic;startFill=1;fillColor=#1ba1e2;strokeColor=#006EAF;" edge="1" parent="1" source="1AZqCnQGpeGdDfHHl4o8-6" target="1AZqCnQGpeGdDfHHl4o8-39">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="1AZqCnQGpeGdDfHHl4o8-56" value="No FK Relationship" style="edgeLabel;html=1;align=center;verticalAlign=middle;resizable=0;points=[];fontColor=#FFFFFF;labelBackgroundColor=none;" vertex="1" connectable="0" parent="1AZqCnQGpeGdDfHHl4o8-48">
<mxGeometry x="-0.0082" y="2" relative="1" as="geometry">
<mxPoint as="offset" />
</mxGeometry>
</mxCell>
<mxCell id="1AZqCnQGpeGdDfHHl4o8-13" value="public.user_subscriptions" style="swimlane;fontStyle=0;childLayout=stackLayout;horizontal=1;startSize=30;horizontalStack=0;resizeParent=1;resizeParentMax=0;resizeLast=0;collapsible=1;marginBottom=0;whiteSpace=wrap;html=1;fillColor=#1ba1e2;fontColor=#ffffff;strokeColor=#006EAF;" vertex="1" parent="1">
<mxGeometry x="243" y="203" width="175" height="180" as="geometry" />
</mxCell>
<mxCell id="1AZqCnQGpeGdDfHHl4o8-14" value="PK FK Unique user_id:uuid" style="text;strokeColor=none;fillColor=none;align=left;verticalAlign=middle;spacingLeft=4;spacingRight=4;overflow=hidden;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;rotatable=0;whiteSpace=wrap;html=1;" vertex="1" parent="1AZqCnQGpeGdDfHHl4o8-13">
<mxGeometry y="30" width="175" height="30" as="geometry" />
</mxCell>
<mxCell id="1AZqCnQGpeGdDfHHl4o8-15" value="FK tier:text" style="text;strokeColor=none;fillColor=none;align=left;verticalAlign=middle;spacingLeft=4;spacingRight=4;overflow=hidden;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;rotatable=0;whiteSpace=wrap;html=1;" vertex="1" parent="1AZqCnQGpeGdDfHHl4o8-13">
<mxGeometry y="60" width="175" height="30" as="geometry" />
</mxCell>
<mxCell id="1AZqCnQGpeGdDfHHl4o8-54" value="active:bool" style="text;strokeColor=none;fillColor=none;align=left;verticalAlign=middle;spacingLeft=4;spacingRight=4;overflow=hidden;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;rotatable=0;whiteSpace=wrap;html=1;" vertex="1" parent="1AZqCnQGpeGdDfHHl4o8-13">
<mxGeometry y="90" width="175" height="30" as="geometry" />
</mxCell>
<mxCell id="1AZqCnQGpeGdDfHHl4o8-53" value="last_paid_date:date" style="text;strokeColor=none;fillColor=none;align=left;verticalAlign=middle;spacingLeft=4;spacingRight=4;overflow=hidden;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;rotatable=0;whiteSpace=wrap;html=1;" vertex="1" parent="1AZqCnQGpeGdDfHHl4o8-13">
<mxGeometry y="120" width="175" height="30" as="geometry" />
</mxCell>
<mxCell id="1AZqCnQGpeGdDfHHl4o8-47" value="start_date:date" style="text;strokeColor=none;fillColor=none;align=left;verticalAlign=middle;spacingLeft=4;spacingRight=4;overflow=hidden;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;rotatable=0;whiteSpace=wrap;html=1;" vertex="1" parent="1AZqCnQGpeGdDfHHl4o8-13">
<mxGeometry y="150" width="175" height="30" as="geometry" />
</mxCell>
<mxCell id="1AZqCnQGpeGdDfHHl4o8-55" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=1;exitY=0.5;exitDx=0;exitDy=0;entryX=0;entryY=0.5;entryDx=0;entryDy=0;fillColor=#0050ef;strokeColor=#001DBC;" edge="1" parent="1" source="1AZqCnQGpeGdDfHHl4o8-18" target="1AZqCnQGpeGdDfHHl4o8-49">
<mxGeometry relative="1" as="geometry">
<Array as="points">
<mxPoint x="197.5" y="165" />
<mxPoint x="197.5" y="30" />
<mxPoint x="447.5" y="30" />
<mxPoint x="447.5" y="105" />
</Array>
</mxGeometry>
</mxCell>
<mxCell id="1AZqCnQGpeGdDfHHl4o8-60" value="public.commissions" style="swimlane;fontStyle=0;childLayout=stackLayout;horizontal=1;startSize=30;horizontalStack=0;resizeParent=1;resizeParentMax=0;resizeLast=0;collapsible=1;marginBottom=0;whiteSpace=wrap;html=1;fillColor=#1ba1e2;fontColor=#ffffff;strokeColor=#006EAF;" vertex="1" parent="1">
<mxGeometry x="697.5" y="30" width="170" height="330" as="geometry" />
</mxCell>
<mxCell id="1AZqCnQGpeGdDfHHl4o8-61" value="PK AI id:&amp;nbsp;int8" style="text;strokeColor=none;fillColor=none;align=left;verticalAlign=middle;spacingLeft=4;spacingRight=4;overflow=hidden;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;rotatable=0;whiteSpace=wrap;html=1;" vertex="1" parent="1AZqCnQGpeGdDfHHl4o8-60">
<mxGeometry y="30" width="170" height="30" as="geometry" />
</mxCell>
<mxCell id="1AZqCnQGpeGdDfHHl4o8-62" value="amount:decimal" style="text;strokeColor=none;fillColor=none;align=left;verticalAlign=middle;spacingLeft=4;spacingRight=4;overflow=hidden;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;rotatable=0;whiteSpace=wrap;html=1;" vertex="1" parent="1AZqCnQGpeGdDfHHl4o8-60">
<mxGeometry y="60" width="170" height="30" as="geometry" />
</mxCell>
<mxCell id="1AZqCnQGpeGdDfHHl4o8-63" value="user_id:uuid" style="text;strokeColor=none;fillColor=none;align=left;verticalAlign=middle;spacingLeft=4;spacingRight=4;overflow=hidden;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;rotatable=0;whiteSpace=wrap;html=1;" vertex="1" parent="1AZqCnQGpeGdDfHHl4o8-60">
<mxGeometry y="90" width="170" height="30" as="geometry" />
</mxCell>
<mxCell id="1AZqCnQGpeGdDfHHl4o8-64" value="request_date:date" style="text;strokeColor=none;fillColor=none;align=left;verticalAlign=middle;spacingLeft=4;spacingRight=4;overflow=hidden;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;rotatable=0;whiteSpace=wrap;html=1;" vertex="1" parent="1AZqCnQGpeGdDfHHl4o8-60">
<mxGeometry y="120" width="170" height="30" as="geometry" />
</mxCell>
<mxCell id="1AZqCnQGpeGdDfHHl4o8-65" value="accepted:bool?" style="text;strokeColor=none;fillColor=none;align=left;verticalAlign=middle;spacingLeft=4;spacingRight=4;overflow=hidden;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;rotatable=0;whiteSpace=wrap;html=1;" vertex="1" parent="1AZqCnQGpeGdDfHHl4o8-60">
<mxGeometry y="150" width="170" height="30" as="geometry" />
</mxCell>
<mxCell id="1AZqCnQGpeGdDfHHl4o8-66" value="processed_date:date?" style="text;strokeColor=none;fillColor=none;align=left;verticalAlign=middle;spacingLeft=4;spacingRight=4;overflow=hidden;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;rotatable=0;whiteSpace=wrap;html=1;" vertex="1" parent="1AZqCnQGpeGdDfHHl4o8-60">
<mxGeometry y="180" width="170" height="30" as="geometry" />
</mxCell>
<mxCell id="1AZqCnQGpeGdDfHHl4o8-67" value="hours:number" style="text;strokeColor=none;fillColor=none;align=left;verticalAlign=middle;spacingLeft=4;spacingRight=4;overflow=hidden;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;rotatable=0;whiteSpace=wrap;html=1;" vertex="1" parent="1AZqCnQGpeGdDfHHl4o8-60">
<mxGeometry y="210" width="170" height="30" as="geometry" />
</mxCell>
<mxCell id="1AZqCnQGpeGdDfHHl4o8-70" value="pending_approval:bool false" style="text;strokeColor=none;fillColor=none;align=left;verticalAlign=middle;spacingLeft=4;spacingRight=4;overflow=hidden;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;rotatable=0;whiteSpace=wrap;html=1;" vertex="1" parent="1AZqCnQGpeGdDfHHl4o8-60">
<mxGeometry y="240" width="170" height="30" as="geometry" />
</mxCell>
<mxCell id="1AZqCnQGpeGdDfHHl4o8-68" value="paidDate:date?" style="text;strokeColor=none;fillColor=none;align=left;verticalAlign=middle;spacingLeft=4;spacingRight=4;overflow=hidden;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;rotatable=0;whiteSpace=wrap;html=1;" vertex="1" parent="1AZqCnQGpeGdDfHHl4o8-60">
<mxGeometry y="270" width="170" height="30" as="geometry" />
</mxCell>
<mxCell id="1AZqCnQGpeGdDfHHl4o8-69" value="completedDate:date?" style="text;strokeColor=none;fillColor=none;align=left;verticalAlign=middle;spacingLeft=4;spacingRight=4;overflow=hidden;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;rotatable=0;whiteSpace=wrap;html=1;" vertex="1" parent="1AZqCnQGpeGdDfHHl4o8-60">
<mxGeometry y="300" width="170" height="30" as="geometry" />
</mxCell>
<mxCell id="1AZqCnQGpeGdDfHHl4o8-71" value="public.comission_messages" style="swimlane;fontStyle=0;childLayout=stackLayout;horizontal=1;startSize=30;horizontalStack=0;resizeParent=1;resizeParentMax=0;resizeLast=0;collapsible=1;marginBottom=0;whiteSpace=wrap;html=1;fillColor=#1ba1e2;fontColor=#ffffff;strokeColor=#006EAF;" vertex="1" parent="1">
<mxGeometry x="957.5" y="180" width="210" height="120" as="geometry" />
</mxCell>
<mxCell id="1AZqCnQGpeGdDfHHl4o8-72" value="PK AI id:int8" style="text;strokeColor=none;fillColor=none;align=left;verticalAlign=middle;spacingLeft=4;spacingRight=4;overflow=hidden;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;rotatable=0;whiteSpace=wrap;html=1;" vertex="1" parent="1AZqCnQGpeGdDfHHl4o8-71">
<mxGeometry y="30" width="210" height="30" as="geometry" />
</mxCell>
<mxCell id="1AZqCnQGpeGdDfHHl4o8-73" value="FK comission_id:int8" style="text;strokeColor=none;fillColor=none;align=left;verticalAlign=middle;spacingLeft=4;spacingRight=4;overflow=hidden;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;rotatable=0;whiteSpace=wrap;html=1;" vertex="1" parent="1AZqCnQGpeGdDfHHl4o8-71">
<mxGeometry y="60" width="210" height="30" as="geometry" />
</mxCell>
<mxCell id="1AZqCnQGpeGdDfHHl4o8-74" value="FK sender_id:uuid" style="text;strokeColor=none;fillColor=none;align=left;verticalAlign=middle;spacingLeft=4;spacingRight=4;overflow=hidden;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;rotatable=0;whiteSpace=wrap;html=1;" vertex="1" parent="1AZqCnQGpeGdDfHHl4o8-71">
<mxGeometry y="90" width="210" height="30" as="geometry" />
</mxCell>
<mxCell id="1AZqCnQGpeGdDfHHl4o8-79" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=1;exitY=0.5;exitDx=0;exitDy=0;entryX=0;entryY=0.5;entryDx=0;entryDy=0;fillColor=#0050ef;strokeColor=#001DBC;" edge="1" parent="1" source="1AZqCnQGpeGdDfHHl4o8-18" target="1AZqCnQGpeGdDfHHl4o8-63">
<mxGeometry relative="1" as="geometry">
<Array as="points">
<mxPoint x="197.5" y="165" />
<mxPoint x="197.5" y="30" />
<mxPoint x="447.5" y="30" />
<mxPoint x="447.5" y="-30" />
<mxPoint x="667.5" y="-30" />
<mxPoint x="667.5" y="135" />
</Array>
</mxGeometry>
</mxCell>
<mxCell id="1AZqCnQGpeGdDfHHl4o8-80" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=1;exitY=0.5;exitDx=0;exitDy=0;entryX=0;entryY=0.5;entryDx=0;entryDy=0;fillColor=#1ba1e2;strokeColor=#006EAF;" edge="1" parent="1" source="1AZqCnQGpeGdDfHHl4o8-61" target="1AZqCnQGpeGdDfHHl4o8-73">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="1AZqCnQGpeGdDfHHl4o8-81" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=1;exitY=0.5;exitDx=0;exitDy=0;entryX=0;entryY=0.5;entryDx=0;entryDy=0;fillColor=#0050ef;strokeColor=#001DBC;" edge="1" parent="1" source="1AZqCnQGpeGdDfHHl4o8-18" target="1AZqCnQGpeGdDfHHl4o8-74">
<mxGeometry relative="1" as="geometry">
<Array as="points">
<mxPoint x="197.5" y="165" />
<mxPoint x="197.5" y="30" />
<mxPoint x="447.5" y="30" />
<mxPoint x="447.5" y="-30" />
<mxPoint x="667.5" y="-30" />
<mxPoint x="667.5" y="400" />
<mxPoint x="897.5" y="400" />
<mxPoint x="897.5" y="285" />
</Array>
</mxGeometry>
</mxCell>
</root>
</mxGraphModel>
</diagram>
</mxfile>

View File

@ -19,39 +19,24 @@ module.exports = {
// 'pink-glow': '0 0 4px #524FFD, 0 0 4px #524FFD, 0 0 4px #524FFD, 0 0 4px #524FFD',
},
colors: {
'primary': '#201240',
'primary-light': '#403260',
'primary-dark': '#100120',
'secondary': '#4F3D70',
'secondary-light': '#6F5D90',
'secondary-dark': '#2F1D50',
'free': '#04396F',
'free-light': '#04396F',
'free-dark': '#001A35',
'tier1': '#006197',
'tier1-light': '#006197',
'tier1-dark': '#003D5E',
'tier2': '#008BB3',
'tier2-light': '#4AC8E1',
'tier2-dark': '#005F7A',
'tier3': '#00B5C0',
'tier3-light': '#6CE2E8',
'tier3-dark': '#008B94',
'error': '#862117',
'error-light': '#C44C4C',
'error-dark': '#5C0D0D',
'success': '#00C9A6',
'success-light': '#20E9C6',
'success-dark': '#00A986',
'warning': '#E17558',
'warning-light': '#E39578',
'warning-dark': '#C15538',
'info': '#222140',
'info-light': '#424260',
'info-dark': '#020120',
'neutral': '#78639A',
'neutral-light': '#9883BA',
'neutral-dark': '#58427A',
'primary': 'var(--color-primary)',
'primary-light': 'var(--color-primary-light)',
'primary-dark': 'var(--color-primary-dark)',
'secondary': 'var(--color-secondary)',
'secondary-light': 'var(--color-secondary-light)',
'secondary-dark': 'var(--color-secondary-dark)',
'error': 'var(--color-error)',
'error-light': 'var(--color-error-light)',
'error-dark': 'var(--color-error-dark)',
'success': 'var(--color-success)',
'success-light': 'var(--color-success-light)',
'success-dark': 'var(--color-success-dark)',
'warning': 'var(--color-warning)',
'warning-light': 'var(--color-warning-light)',
'warning-dark': 'var(--color-warning-dark)',
'info': 'var(--color-info)',
'info-light': 'var(--color-info-light)',
'info-dark': 'var(--color-info-dark)',
},
},
},