mirror of
https://github.com/phishingclub/phishingclub.git
synced 2026-07-10 06:08:42 +02:00
Major UI update:
Improved dark mode Added company banner and moved change company Changed campaign trends, and now requires 2 campaigns atleast Menu collapses if open and link clicked Changed calendar event type indicator Changed mobile menu Changed campaign event timeline and event cards Various UI changes Signed-off-by: Ronni Skansing <rskansing@gmail.com>
This commit is contained in:
@@ -243,9 +243,7 @@
|
||||
</script>
|
||||
|
||||
{#if visible}
|
||||
<div
|
||||
class="fixed top-0 left-0 w-full h-full bg-cta-blue dark:bg-gray-900 opacity-20 blur-xl transition-colors duration-200"
|
||||
/>
|
||||
<div class="fixed top-0 left-0 w-full h-full opacity-[0.5]" />
|
||||
<div
|
||||
class="fixed top-0 left-0 w-full h-full flex justify-center items-center backdrop-blur-sm z-20"
|
||||
role="dialog"
|
||||
@@ -259,7 +257,7 @@
|
||||
>
|
||||
<!-- Header -->
|
||||
<div
|
||||
class="bg-red-700 dark:bg-red-800 text-white rounded-t-md py-4 px-8 flex items-center justify-between flex-shrink-0 transition-colors duration-200"
|
||||
class="bg-red-700 dark:bg-red-700/90 text-white rounded-t-md py-4 px-8 flex items-center justify-between flex-shrink-0 transition-colors duration-200"
|
||||
>
|
||||
<div class="flex items-center">
|
||||
<svg
|
||||
@@ -293,7 +291,7 @@
|
||||
<div class="px-8 py-6">
|
||||
<div
|
||||
id="alert-description"
|
||||
class="text-gray-600 dark:text-gray-300 transition-colors duration-200"
|
||||
class="text-gray-600 dark:text-gray-400 transition-colors duration-200"
|
||||
>
|
||||
{#if $$slots.default}
|
||||
<slot />
|
||||
@@ -317,13 +315,13 @@
|
||||
|
||||
<!-- Footer -->
|
||||
<div
|
||||
class="py-4 row-span-2 col-start-1 col-span-3 border-t-2 border-gray-200 dark:border-gray-600 w-full flex flex-row justify-center items-center sm:justify-center md:justify-center lg:justify-end xl:justify-end 2xl:justify-end px-8 bg-gray-50 dark:bg-gray-700 rounded-b-md transition-colors duration-200"
|
||||
class="py-4 row-span-2 col-start-1 col-span-3 border-t-2 border-gray-200 dark:border-gray-700/60 w-full flex flex-row justify-center items-center sm:justify-center md:justify-center lg:justify-end xl:justify-end 2xl:justify-end px-8 bg-gray-50 dark:bg-gray-800/40 rounded-b-md transition-colors duration-200"
|
||||
>
|
||||
{#if !noCancel}
|
||||
<button
|
||||
type="reset"
|
||||
on:click={close}
|
||||
class="bg-slate-400 hover:bg-slate-300 dark:bg-gray-600 dark:hover:bg-gray-500 text-sm mr-2 uppercase font-bold px-4 py-2 text-white rounded-md transition-colors duration-200"
|
||||
class="bg-slate-400 hover:bg-slate-300 dark:bg-gray-700/80 dark:hover:bg-gray-600/80 text-sm mr-2 uppercase font-bold px-4 py-2 text-white rounded-md transition-colors duration-200"
|
||||
>
|
||||
{cancel}
|
||||
</button>
|
||||
|
||||
@@ -46,7 +46,7 @@
|
||||
SCHEDULED: '#62aded', // campaign-scheduled
|
||||
ACTIVE: '#5557f6', // campaign-active
|
||||
COMPLETED: '#4cb5b5', // message-read - much more muted than bright green
|
||||
SELF_MANAGED: '#9F7AEA' // purple
|
||||
SELF_MANAGED: '#7C3AED' // darker purple
|
||||
};
|
||||
|
||||
function sortCampaignsByPriority(campaigns, day) {
|
||||
@@ -308,19 +308,19 @@
|
||||
</script>
|
||||
|
||||
<div
|
||||
class="w-full bg-white dark:bg-gray-800 rounded-lg shadow-sm p-4 border border-gray-200 dark:border-gray-700 transition-colors duration-200"
|
||||
class="w-full bg-white dark:bg-gray-900/80 rounded-lg shadow-sm p-4 border border-gray-200 dark:border-gray-700/60 transition-colors duration-200"
|
||||
>
|
||||
<div class="space-y-4 max-w-5xl mx-auto min-h-[600px]">
|
||||
<!-- Navigation Controls -->
|
||||
<div class="flex justify-center items-center">
|
||||
<button
|
||||
class="p-2 rounded hover:bg-gray-100 dark:hover:bg-gray-700 mx-4 transition-colors duration-200"
|
||||
class="p-2 rounded hover:bg-gray-100 dark:hover:bg-gray-800/60 mx-4 transition-colors duration-200"
|
||||
on:click={previousMonth}
|
||||
disabled={isLoadingNewMonth}
|
||||
>
|
||||
<svg
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
class="h-5 w-5 text-gray-600 dark:text-gray-300"
|
||||
class="h-5 w-5 text-gray-600 dark:text-gray-400"
|
||||
fill="none"
|
||||
viewBox="0 0 24 24"
|
||||
stroke="currentColor"
|
||||
@@ -334,18 +334,18 @@
|
||||
</svg>
|
||||
</button>
|
||||
|
||||
<h2 class="text-lg font-semibold text-gray-900 dark:text-white">
|
||||
<h2 class="text-lg font-semibold text-gray-900 dark:text-gray-300">
|
||||
{format(currentMonth, 'MMMM yyyy')}
|
||||
</h2>
|
||||
|
||||
<button
|
||||
class="p-2 rounded hover:bg-gray-100 dark:hover:bg-gray-700 mx-4 transition-colors duration-200"
|
||||
class="p-2 rounded hover:bg-gray-100 dark:hover:bg-gray-800/60 mx-4 transition-colors duration-200"
|
||||
on:click={nextMonth}
|
||||
disabled={isLoadingNewMonth}
|
||||
>
|
||||
<svg
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
class="h-5 w-5 text-gray-600 dark:text-gray-300"
|
||||
class="h-5 w-5 text-gray-600 dark:text-gray-400"
|
||||
fill="none"
|
||||
viewBox="0 0 24 24"
|
||||
stroke="currentColor"
|
||||
@@ -367,7 +367,7 @@
|
||||
style="background-color: {item.color}; opacity: {activeFilters[item.key] ? '1' : '0.3'}"
|
||||
></div>
|
||||
<span
|
||||
class="transition-opacity duration-200 text-gray-700 dark:text-gray-300"
|
||||
class="transition-opacity duration-200 text-gray-700 dark:text-gray-400"
|
||||
style="opacity: {activeFilters[item.key] ? '1' : '0.5'}">{item.label}</span
|
||||
>
|
||||
</button>
|
||||
@@ -379,7 +379,7 @@
|
||||
<!-- Day headers -->
|
||||
<div class="grid grid-cols-7 text-center mb-1">
|
||||
{#each ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'] as day}
|
||||
<div class="text-sm font-medium text-gray-600 dark:text-gray-300">{day}</div>
|
||||
<div class="text-sm font-medium text-gray-600 dark:text-gray-400">{day}</div>
|
||||
{/each}
|
||||
</div>
|
||||
|
||||
@@ -388,9 +388,9 @@
|
||||
<div class="min-h-[450px] flex items-center justify-center">
|
||||
<div class="flex items-center space-x-2">
|
||||
<div
|
||||
class="animate-spin rounded-full h-6 w-6 border-b-2 border-blue-600 dark:border-blue-400"
|
||||
class="animate-spin rounded-full h-6 w-6 border-b-2 border-blue-600 dark:border-highlight-blue/80"
|
||||
></div>
|
||||
<span class="text-gray-600 dark:text-gray-300">Loading calendar...</span>
|
||||
<span class="text-gray-600 dark:text-gray-400">Loading calendar...</span>
|
||||
</div>
|
||||
</div>
|
||||
{:else}
|
||||
@@ -400,19 +400,19 @@
|
||||
{#each week as day}
|
||||
<div
|
||||
class="calendar-day relative border rounded-md overflow-hidden {scrollBarClassesHorizontal} {day.isToday
|
||||
? 'border-gray-700 dark:border-gray-400 bg-gray-50 dark:bg-gray-700'
|
||||
: 'border-gray-200 dark:border-gray-600'}
|
||||
? 'border-gray-700 dark:border-gray-500 bg-gray-50 dark:bg-gray-800/60'
|
||||
: 'border-gray-200 dark:border-gray-700/60'}
|
||||
{day.isCurrentMonth
|
||||
? 'bg-white dark:bg-gray-800'
|
||||
: 'bg-gray-50 dark:bg-gray-700'} transition-colors duration-200"
|
||||
? 'bg-white dark:bg-gray-900/60'
|
||||
: 'bg-gray-50 dark:bg-gray-800/40'} transition-colors duration-200"
|
||||
>
|
||||
<!-- Date number -->
|
||||
<div
|
||||
class="text-sm p-1 {day.isToday
|
||||
? 'font-bold text-gray-800 dark:text-white'
|
||||
? 'font-bold text-gray-800 dark:text-gray-300'
|
||||
: day.isCurrentMonth
|
||||
? 'text-gray-600 dark:text-gray-300'
|
||||
: 'text-gray-400 dark:text-gray-500'}"
|
||||
? 'text-gray-600 dark:text-gray-400'
|
||||
: 'text-gray-400 dark:text-gray-600'}"
|
||||
>
|
||||
{day.date.getDate()}
|
||||
</div>
|
||||
@@ -423,8 +423,8 @@
|
||||
{#each day.campaigns as campaign}
|
||||
<a
|
||||
href={`/campaign/${campaign.id}`}
|
||||
class="block mb-1 rounded-sm text-white text-xs p-1 overflow-hidden hover:opacity-90 transition-opacity"
|
||||
style="background-color: {campaign.color};"
|
||||
class="block mb-1 rounded-sm text-xs p-1 pl-2 overflow-hidden hover:bg-gray-200 dark:hover:bg-gray-700/40 transition-all duration-200 bg-gray-100 dark:bg-gray-800/30"
|
||||
style="border-left: 3px solid {campaign.color};"
|
||||
title="{campaign.name} - {campaign.isSelfManaged
|
||||
? 'Self-managed'
|
||||
: campaign.end < new Date()
|
||||
@@ -435,7 +435,7 @@
|
||||
? `${formatDateString(new Date(campaign.createdAt))} - ?`
|
||||
: `${formatDateString(campaign.start)} - ${formatDateString(campaign.end)}`}"
|
||||
>
|
||||
<div class="campaign-name truncate text-white">
|
||||
<div class="campaign-name truncate text-gray-700 dark:text-gray-300">
|
||||
{truncateText(campaign.name, 18)}
|
||||
</div>
|
||||
</a>
|
||||
|
||||
@@ -2,6 +2,21 @@
|
||||
import { onMount, onDestroy, tick } from 'svelte';
|
||||
let resizeObserver;
|
||||
|
||||
// Theme detection for chart reactivity
|
||||
let isDarkMode = false;
|
||||
|
||||
// Check theme on mount and when it changes
|
||||
const checkTheme = () => {
|
||||
const newIsDarkMode = document.documentElement.classList.contains('dark');
|
||||
if (newIsDarkMode !== isDarkMode) {
|
||||
isDarkMode = newIsDarkMode;
|
||||
// Recreate chart when theme changes
|
||||
if (containerReady && chartData.length >= 2) {
|
||||
tick().then(() => createChart());
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
export let campaignStats = [];
|
||||
export let isLoading = false;
|
||||
|
||||
@@ -238,6 +253,16 @@
|
||||
svg.setAttribute('class', 'campaign-trend-chart');
|
||||
chartContainer.appendChild(svg);
|
||||
|
||||
// Add dark background rectangle
|
||||
const bgRect = document.createElementNS('http://www.w3.org/2000/svg', 'rect');
|
||||
bgRect.setAttribute('width', '100%');
|
||||
bgRect.setAttribute('height', '100%');
|
||||
bgRect.setAttribute(
|
||||
'fill',
|
||||
document.documentElement.classList.contains('dark') ? '#111827' : '#ffffff'
|
||||
);
|
||||
svg.appendChild(bgRect);
|
||||
|
||||
const xExtent = [0, chartData.length - 1];
|
||||
// Map 0-100% directly to chart boundaries so 0% aligns with X-axis
|
||||
const yExtent = [0, 100];
|
||||
@@ -346,7 +371,7 @@
|
||||
stop1.setAttribute('offset', '0%');
|
||||
stop1.setAttribute(
|
||||
'stop-color',
|
||||
document.documentElement.classList.contains('dark') ? '#374151' : '#f8f9fa'
|
||||
document.documentElement.classList.contains('dark') ? '#1f2937' : '#f8f9fa'
|
||||
);
|
||||
stop1.setAttribute('stop-opacity', '0.3');
|
||||
|
||||
@@ -354,15 +379,15 @@
|
||||
stop2.setAttribute('offset', '50%');
|
||||
stop2.setAttribute(
|
||||
'stop-color',
|
||||
document.documentElement.classList.contains('dark') ? '#4b5563' : '#e9ecef'
|
||||
document.documentElement.classList.contains('dark') ? '#374151' : '#e9ecef'
|
||||
);
|
||||
stop2.setAttribute('stop-opacity', '0.5');
|
||||
stop2.setAttribute('stop-opacity', '0.4');
|
||||
|
||||
const stop3 = document.createElementNS('http://www.w3.org/2000/svg', 'stop');
|
||||
stop3.setAttribute('offset', '100%');
|
||||
stop3.setAttribute(
|
||||
'stop-color',
|
||||
document.documentElement.classList.contains('dark') ? '#374151' : '#f8f9fa'
|
||||
document.documentElement.classList.contains('dark') ? '#1f2937' : '#f8f9fa'
|
||||
);
|
||||
stop3.setAttribute('stop-opacity', '0.3');
|
||||
|
||||
@@ -400,7 +425,7 @@
|
||||
vLine.setAttribute('y2', (height - margin.bottom).toString());
|
||||
vLine.setAttribute(
|
||||
'stroke',
|
||||
document.documentElement.classList.contains('dark') ? '#4b5563' : '#e5e7eb'
|
||||
document.documentElement.classList.contains('dark') ? '#374151' : '#e5e7eb'
|
||||
);
|
||||
vLine.setAttribute('stroke-width', '0.5');
|
||||
vLine.setAttribute('opacity', '0.3');
|
||||
@@ -416,7 +441,7 @@
|
||||
yAxis.setAttribute('y2', (height - margin.bottom).toString());
|
||||
yAxis.setAttribute(
|
||||
'stroke',
|
||||
document.documentElement.classList.contains('dark') ? '#9ca3af' : '#6B7280'
|
||||
document.documentElement.classList.contains('dark') ? '#6887ea' : '#6B7280'
|
||||
);
|
||||
yAxis.setAttribute('stroke-width', '2');
|
||||
svg.appendChild(yAxis);
|
||||
@@ -428,7 +453,7 @@
|
||||
xAxis.setAttribute('y2', (height - margin.bottom).toString());
|
||||
xAxis.setAttribute(
|
||||
'stroke',
|
||||
document.documentElement.classList.contains('dark') ? '#9ca3af' : '#6B7280'
|
||||
document.documentElement.classList.contains('dark') ? '#6887ea' : '#6B7280'
|
||||
);
|
||||
xAxis.setAttribute('stroke-width', '2');
|
||||
svg.appendChild(xAxis);
|
||||
@@ -443,7 +468,7 @@
|
||||
text.setAttribute('font-size', '11');
|
||||
text.setAttribute(
|
||||
'fill',
|
||||
document.documentElement.classList.contains('dark') ? '#d1d5db' : '#6B7280'
|
||||
document.documentElement.classList.contains('dark') ? '#e5e7eb' : '#6B7280'
|
||||
);
|
||||
text.setAttribute('font-weight', '500');
|
||||
text.setAttribute('alignment-baseline', 'middle');
|
||||
@@ -461,7 +486,7 @@
|
||||
text.setAttribute('font-size', '11');
|
||||
text.setAttribute(
|
||||
'fill',
|
||||
document.documentElement.classList.contains('dark') ? '#f9fafb' : '#000'
|
||||
document.documentElement.classList.contains('dark') ? '#f3f4f6' : '#000'
|
||||
);
|
||||
text.setAttribute('alignment-baseline', 'middle');
|
||||
// Show date (YYYY/MM) and campaign name on the same line
|
||||
@@ -810,8 +835,21 @@
|
||||
});
|
||||
}
|
||||
|
||||
let themeObserver;
|
||||
|
||||
onMount(async () => {
|
||||
await tick(); // Wait for DOM/layout
|
||||
|
||||
// Initialize theme detection
|
||||
checkTheme();
|
||||
|
||||
// Watch for theme changes
|
||||
themeObserver = new MutationObserver(checkTheme);
|
||||
themeObserver.observe(document.documentElement, {
|
||||
attributes: true,
|
||||
attributeFilter: ['class']
|
||||
});
|
||||
|
||||
if (sizingContainer) {
|
||||
const containerWidth = sizingContainer.parentElement?.clientWidth || 0;
|
||||
width = Math.min(Math.max(containerWidth, 300), containerWidth); // Minimum 300px but never exceed container
|
||||
@@ -833,6 +871,10 @@
|
||||
if (resizeObserver && sizingContainer) {
|
||||
resizeObserver.unobserve(sizingContainer.parentElement || sizingContainer);
|
||||
}
|
||||
// Clean up theme observer
|
||||
if (themeObserver) {
|
||||
themeObserver.disconnect();
|
||||
}
|
||||
if (loadingTimeout) {
|
||||
clearTimeout(loadingTimeout);
|
||||
}
|
||||
@@ -856,14 +898,16 @@
|
||||
></div>
|
||||
{#if !containerReady}
|
||||
<div class="flex items-center justify-center min-h-[100px]">
|
||||
<span class="text-gray-400 text-sm">Preparing chart…</span>
|
||||
<span class="text-gray-400 dark:text-gray-500 text-sm transition-colors duration-200"
|
||||
>Preparing chart…</span
|
||||
>
|
||||
</div>
|
||||
{:else}
|
||||
<div>
|
||||
{#if debouncedIsLoading}
|
||||
<div class="flex items-center justify-center h-64">
|
||||
<div
|
||||
class="animate-spin rounded-full h-8 w-8 border-b-2 border-blue-600 dark:border-blue-400"
|
||||
class="animate-spin rounded-full h-8 w-8 border-b-2 border-cta-blue dark:border-highlight-blue transition-colors duration-200"
|
||||
></div>
|
||||
<span class="ml-2 text-gray-600 dark:text-gray-300 transition-colors duration-200"
|
||||
>Loading trend data...</span
|
||||
@@ -875,109 +919,53 @@
|
||||
>Preparing trend data...</span
|
||||
>
|
||||
</div>
|
||||
{:else if hasAttemptedLoad && !isLoading && !debouncedIsLoading && chartData.length === 0}
|
||||
{:else if hasAttemptedLoad && !isLoading && !debouncedIsLoading && chartData.length < 2}
|
||||
<div
|
||||
class="flex items-center justify-center h-64 bg-gray-50 dark:bg-gray-800 rounded-lg transition-colors duration-200"
|
||||
class="bg-white dark:bg-gray-900 rounded-lg border border-gray-200 dark:border-gray-700 p-6 transition-colors duration-200"
|
||||
>
|
||||
<div class="text-center">
|
||||
<svg
|
||||
class="mx-auto h-12 w-12 text-gray-400 dark:text-gray-500 transition-colors duration-200"
|
||||
fill="none"
|
||||
stroke="currentColor"
|
||||
viewBox="0 0 24 24"
|
||||
<!-- Match the height structure of the data container -->
|
||||
<div class="flex flex-row items-center justify-between mb-2 pb-0 flex-wrap gap-2">
|
||||
<h4
|
||||
class="text-sm font-medium text-gray-600 dark:text-gray-300 m-0 transition-colors duration-200"
|
||||
>
|
||||
<path
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
stroke-width="1.5"
|
||||
d="M9 19v-6a2 2 0 00-2-2H5a2 2 0 00-2 2v6a2 2 0 002 2h2a2 2 0 002-2zm0 0V9a2 2 0 012-2h2a2 2 0 012 2v10m-6 0a2 2 0 002 2h2a2 2 0 002-2m0 0V5a2 2 0 012-2h2a2 2 0 012 2v14a2 2 0 01-2 2h-2a2 2 0 01-2-2z"
|
||||
/>
|
||||
</svg>
|
||||
<h3
|
||||
class="mt-2 text-sm font-medium text-gray-900 dark:text-gray-200 transition-colors duration-200"
|
||||
>
|
||||
No campaign data
|
||||
</h3>
|
||||
<p class="mt-1 text-sm text-gray-500 dark:text-gray-400 transition-colors duration-200">
|
||||
Campaign statistics will appear here once campaigns are completed.
|
||||
</p>
|
||||
Trend Analytics
|
||||
</h4>
|
||||
</div>
|
||||
</div>
|
||||
{:else if hasAttemptedLoad && !isLoading && !debouncedIsLoading && chartData.length === 1}
|
||||
<div
|
||||
class="bg-blue-50 dark:bg-blue-900/20 border border-blue-200 dark:border-blue-800 rounded-lg p-6 transition-colors duration-200"
|
||||
>
|
||||
<div class="flex items-center">
|
||||
<svg
|
||||
class="h-6 w-6 text-blue-600 dark:text-blue-400 mr-2 transition-colors duration-200"
|
||||
fill="none"
|
||||
stroke="currentColor"
|
||||
viewBox="0 0 24 24"
|
||||
>
|
||||
<path
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
stroke-width="2"
|
||||
d="M13 16h-1v-4h-1m1-4h.01M21 12a9 9 0 11-18 0 9 9 0 0118 0z"
|
||||
/>
|
||||
</svg>
|
||||
<div>
|
||||
<h4
|
||||
class="text-sm font-medium text-blue-900 dark:text-blue-200 transition-colors duration-200"
|
||||
<div class="mb-8"></div>
|
||||
|
||||
<!-- Centered content matching stats grid height -->
|
||||
<div class="flex items-center justify-center min-h-[350px] py-16">
|
||||
<div class="text-center">
|
||||
<svg
|
||||
class="mx-auto h-12 w-12 text-cta-blue dark:text-highlight-blue transition-colors duration-200"
|
||||
fill="none"
|
||||
viewBox="0 0 24 24"
|
||||
stroke="currentColor"
|
||||
aria-hidden="true"
|
||||
>
|
||||
Single Campaign Data
|
||||
</h4>
|
||||
<p class="text-sm text-blue-700 dark:text-blue-300 transition-colors duration-200">
|
||||
Trends will appear when you have 2 or more completed campaigns.
|
||||
<path
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
stroke-width="2"
|
||||
d="M9 19v-6a2 2 0 00-2-2H5a2 2 0 00-2 2v6a2 2 0 002 2h2a2 2 0 002-2zm0 0V9a2 2 0 012-2h2a2 2 0 012 2v10m-6 0a2 2 0 002 2h2a2 2 0 002-2m0 0V5a2 2 0 012-2h2a2 2 0 012 2v14a2 2 0 01-2 2h-2a2 2 0 01-2-2z"
|
||||
/>
|
||||
</svg>
|
||||
<h3
|
||||
class="mt-3 text-lg font-medium text-gray-900 dark:text-gray-100 transition-colors duration-200"
|
||||
>
|
||||
Insufficient data for trend analysis
|
||||
</h3>
|
||||
<p
|
||||
class="mt-2 text-sm text-gray-600 dark:text-gray-400 transition-colors duration-200"
|
||||
>
|
||||
Trend analysis requires at least 2 completed campaigns to show meaningful patterns.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="grid grid-cols-4 gap-4">
|
||||
<div class="text-center">
|
||||
<div
|
||||
class="text-2xl font-bold text-blue-600 dark:text-blue-400 transition-colors duration-200"
|
||||
>
|
||||
{chartData[0].openRate}%
|
||||
</div>
|
||||
<div class="text-sm text-gray-600 dark:text-gray-400 transition-colors duration-200">
|
||||
Open Rate
|
||||
</div>
|
||||
</div>
|
||||
<div class="text-center">
|
||||
<div
|
||||
class="text-2xl font-bold text-green-600 dark:text-green-400 transition-colors duration-200"
|
||||
>
|
||||
{chartData[0].clickRate}%
|
||||
</div>
|
||||
<div class="text-sm text-gray-600 dark:text-gray-400 transition-colors duration-200">
|
||||
Click Rate
|
||||
</div>
|
||||
</div>
|
||||
<div class="text-center">
|
||||
<div
|
||||
class="text-2xl font-bold text-yellow-600 dark:text-yellow-400 transition-colors duration-200"
|
||||
>
|
||||
{chartData[0].submissionRate}%
|
||||
</div>
|
||||
<div class="text-sm text-gray-600 dark:text-gray-400 transition-colors duration-200">
|
||||
Submission Rate
|
||||
</div>
|
||||
</div>
|
||||
<div class="text-center">
|
||||
<div
|
||||
class="text-2xl font-bold text-indigo-600 dark:text-indigo-400 transition-colors duration-200"
|
||||
>
|
||||
{chartData[0].reportRate}%
|
||||
</div>
|
||||
<div class="text-sm text-gray-600 dark:text-gray-400 transition-colors duration-200">
|
||||
Report Rate
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{:else if hasAttemptedLoad && !isLoading && !debouncedIsLoading && chartData.length >= 2}
|
||||
<div
|
||||
class="bg-white dark:bg-gray-800 rounded-lg border border-gray-200 dark:border-gray-600 p-6 transition-colors duration-200"
|
||||
class="bg-white dark:bg-gray-900 rounded-lg border border-gray-200 dark:border-gray-700 p-6 transition-colors duration-200"
|
||||
>
|
||||
<!-- Trendline stats and controls above chart -->
|
||||
<div class="flex flex-row items-center justify-between mb-2 pb-0 flex-wrap gap-2">
|
||||
@@ -993,7 +981,7 @@
|
||||
Time range:
|
||||
<select
|
||||
bind:value={selectedTimeRange}
|
||||
class="border border-gray-300 dark:border-gray-600 rounded px-1 py-0 text-xs bg-white dark:bg-gray-700 text-gray-700 dark:text-gray-200 transition-colors duration-200"
|
||||
class="border border-gray-300 dark:border-gray-600 rounded px-1 py-0 text-xs bg-white dark:bg-gray-900 text-gray-700 dark:text-gray-200 hover:border-cta-blue dark:hover:border-highlight-blue focus:border-cta-blue dark:focus:border-highlight-blue transition-colors duration-200"
|
||||
style="height: 1.5rem;"
|
||||
>
|
||||
{#each timeRanges as range}
|
||||
@@ -1011,7 +999,7 @@
|
||||
min="1"
|
||||
max={chartData.length}
|
||||
bind:value={trendN}
|
||||
class="border border-gray-300 dark:border-gray-600 rounded px-1 py-0 w-10 text-xs bg-white dark:bg-gray-700 text-gray-700 dark:text-gray-200 transition-colors duration-200"
|
||||
class="border border-gray-300 dark:border-gray-600 rounded px-1 py-0 w-10 text-xs bg-white dark:bg-gray-900 text-gray-700 dark:text-gray-200 hover:border-cta-blue dark:hover:border-highlight-blue focus:border-cta-blue dark:focus:border-highlight-blue transition-colors duration-200"
|
||||
style="height: 1.5rem;"
|
||||
/>
|
||||
</label>
|
||||
@@ -1025,13 +1013,13 @@
|
||||
min="2"
|
||||
max={chartData.length}
|
||||
bind:value={movingAvgN}
|
||||
class="border border-gray-300 dark:border-gray-600 rounded px-1 py-0 w-10 text-xs bg-white dark:bg-gray-700 text-gray-700 dark:text-gray-200 transition-colors duration-200"
|
||||
class="border border-gray-300 dark:border-gray-600 rounded px-1 py-0 w-10 text-xs bg-white dark:bg-gray-900 text-gray-700 dark:text-gray-200 hover:border-cta-blue dark:hover:border-highlight-blue focus:border-cta-blue dark:focus:border-highlight-blue transition-colors duration-200"
|
||||
style="height: 1.5rem;"
|
||||
/>
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
<div style="height: 1.25rem;"></div>
|
||||
<div class="mb-8"></div>
|
||||
{#if chartData.length > 0}
|
||||
<div class="grid grid-cols-4 gap-2 sm:gap-4">
|
||||
{#each metrics as metric}
|
||||
@@ -1065,11 +1053,12 @@
|
||||
No trendline stats to display (trendStats is null or not enough data).
|
||||
</div>
|
||||
{/if}
|
||||
<div class="mt-8 mb-6"></div>
|
||||
{#key chartKey}
|
||||
{#if containerReady}
|
||||
<div
|
||||
bind:this={chartContainer}
|
||||
class="min-h-[220px] max-h-[280px] w-full box-border relative rounded-md bg-white dark:bg-gray-800 m-1 transition-colors duration-200"
|
||||
class="min-h-[220px] max-h-[280px] w-full box-border relative rounded-md bg-white dark:bg-gray-900 m-1 transition-colors duration-200"
|
||||
style="contain: layout style;"
|
||||
></div>
|
||||
{/if}
|
||||
@@ -1126,8 +1115,6 @@
|
||||
display: block !important;
|
||||
contain: layout style !important;
|
||||
background: white;
|
||||
border-radius: 8px;
|
||||
padding: 8px;
|
||||
transition: background-color 0.2s ease;
|
||||
}
|
||||
:global(.dark .campaign-trend-chart) {
|
||||
|
||||
@@ -46,7 +46,7 @@
|
||||
class:items-center={inline}
|
||||
>
|
||||
<div class="flex items-center">
|
||||
<p class="font-semibold text-slate-600 dark:text-gray-300 py-2 transition-colors duration-200">
|
||||
<p class="font-semibold text-slate-600 dark:text-gray-400 py-2 transition-colors duration-200">
|
||||
<slot />
|
||||
</p>
|
||||
{#if toolTipText.length > 0}
|
||||
@@ -56,9 +56,9 @@
|
||||
{/if}
|
||||
{#if optional === true}
|
||||
<div
|
||||
class="bg-gray-100 dark:bg-gray-700 ml-2 px-2 rounded-md transition-colors duration-200 h-6 flex items-center"
|
||||
class="bg-gray-100 dark:bg-gray-800/60 ml-2 px-2 rounded-md transition-colors duration-200 h-6 flex items-center"
|
||||
>
|
||||
<p class="text-slate-600 dark:text-gray-300 text-xs transition-colors duration-200">
|
||||
<p class="text-slate-600 dark:text-gray-400 text-xs transition-colors duration-200">
|
||||
optional
|
||||
</p>
|
||||
</div>
|
||||
@@ -75,12 +75,12 @@
|
||||
on:change
|
||||
/>
|
||||
<div
|
||||
class="w-5 h-5 border-2 border-slate-300 dark:border-gray-600 rounded
|
||||
peer-checked:border-cta-blue dark:peer-checked:border-blue-500 peer-checked:bg-cta-blue dark:peer-checked:bg-blue-500
|
||||
class="w-5 h-5 border-2 border-slate-300 dark:border-gray-700/60 rounded
|
||||
peer-checked:border-cta-blue dark:peer-checked:border-highlight-blue/80 peer-checked:bg-cta-blue dark:peer-checked:bg-highlight-blue/80
|
||||
transition-all duration-200 ease-in-out
|
||||
flex items-center justify-center
|
||||
bg-slate-50 dark:bg-gray-700
|
||||
focus-within:ring-2 focus-within:ring-cta-blue dark:focus-within:ring-blue-500 focus-within:ring-offset-2 dark:focus-within:ring-offset-gray-800"
|
||||
bg-slate-50 dark:bg-gray-900/60
|
||||
focus-within:ring-2 focus-within:ring-cta-blue dark:focus-within:ring-highlight-blue/80 focus-within:ring-offset-2 dark:focus-within:ring-offset-gray-900"
|
||||
>
|
||||
{#if value}
|
||||
<svg class="w-3 h-3 text-white" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -9,7 +9,7 @@
|
||||
class:w-32={size === 'small'}
|
||||
class:w-36={size === 'medium'}
|
||||
class:w-60={size === 'large'}
|
||||
class="bg-cta-blue dark:bg-blue-600 px-2 py-2 self-end hover:bg-blue-500 dark:hover:bg-blue-700 text-white text-sm font-bold flex justify-center items-center uppercase rounded-md transition-colors duration-200 disabled:opacity-50 dark:disabled:opacity-60"
|
||||
class="bg-cta-blue dark:bg-highlight-blue/80 px-2 py-2 self-end hover:bg-blue-500 dark:hover:bg-highlight-blue text-white text-sm font-bold flex justify-center items-center uppercase rounded-md transition-colors duration-200 disabled:opacity-50 dark:disabled:opacity-60"
|
||||
on:click
|
||||
>
|
||||
{#if isSubmitting}
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
<div class="flex col-span-12 justify-center p-4 select-text">
|
||||
<div class="w-80 flex col-span-12 justify-center">
|
||||
<div
|
||||
class="flex items-center w-full bg-pleasant-gray dark:bg-gray-700 rounded-md border border-gray-200 dark:border-gray-600 text-center p-2 font-titilium transition-colors duration-200"
|
||||
class="flex items-center w-full bg-pleasant-gray dark:bg-gray-800/40 rounded-md border border-gray-200 dark:border-gray-700/60 text-center p-2 font-titilium transition-colors duration-200"
|
||||
>
|
||||
<svg class="w-12 ml-4" transition:slide viewBox="0 0 32.94 32.94">
|
||||
<circle
|
||||
@@ -33,7 +33,7 @@
|
||||
/>
|
||||
</g>
|
||||
</svg>
|
||||
<p class="pl-4 text-gray-700 dark:text-gray-200 transition-colors duration-200">
|
||||
<p class="pl-4 text-gray-700 dark:text-gray-400 transition-colors duration-200">
|
||||
{message}
|
||||
</p>
|
||||
</div>
|
||||
|
||||
@@ -12,7 +12,7 @@
|
||||
<div class="flex flex-col w-full p-4 h-24">
|
||||
<label
|
||||
for={fieldName}
|
||||
class="text-md font-semibold font-titilium text-pc-darkblue dark:text-gray-200"
|
||||
class="text-md font-semibold font-titilium text-pc-darkblue dark:text-gray-300"
|
||||
>{fieldName}</label
|
||||
>
|
||||
<input
|
||||
@@ -34,6 +34,6 @@
|
||||
{type}
|
||||
id={fieldName}
|
||||
name={fieldName}
|
||||
class="w-full p-2 rounded bg-pc-lightblue dark:bg-gray-700 dark:border-gray-600 dark:text-white dark:placeholder-gray-400 focus:outline-none focus:ring-0 focus:border-cta-blue dark:focus:border-blue-500 focus:border-2 transition-colors duration-200"
|
||||
class="w-full p-2 rounded bg-pc-lightblue dark:bg-gray-900/60 dark:border-gray-700/60 dark:text-gray-300 dark:placeholder-gray-500 focus:outline-none focus:ring-0 focus:border-cta-blue dark:focus:border-highlight-blue/80 focus:border-2 transition-colors duration-200"
|
||||
/>
|
||||
</div>
|
||||
|
||||
@@ -295,9 +295,7 @@
|
||||
|
||||
{#if visible}
|
||||
<div bind:this={bindTo}>
|
||||
<div
|
||||
class="fixed top-0 left-0 w-full h-full bg-cta-blue dark:bg-gray-900 opacity-20 blur-xl transition-colors duration-200"
|
||||
/>
|
||||
<div class="fixed top-0 left-0 w-full h-full opacity-[0.5]" />
|
||||
<div
|
||||
class="fixed top-0 left-0 w-full h-full flex justify-center items-center backdrop-blur-sm z-20"
|
||||
role="dialog"
|
||||
@@ -311,7 +309,7 @@
|
||||
>
|
||||
<div
|
||||
class:opacity-20={isSubmitting}
|
||||
class="bg-cta-blue dark:bg-blue-700 text-white rounded-t-md py-4 px-8 flex justify-between flex-shrink-0 transition-colors duration-200"
|
||||
class="bg-cta-blue dark:bg-blue-800 text-white rounded-t-md py-4 px-8 flex justify-between flex-shrink-0 transition-colors duration-200"
|
||||
>
|
||||
<div class="flex-1">
|
||||
<h1 id="modal-title" class="uppercase mr-8 font-semibold text-2xl">{headerText}</h1>
|
||||
|
||||
@@ -43,16 +43,16 @@
|
||||
|
||||
<div class="flex items-center mb-8 mt-4">
|
||||
<button
|
||||
class="bg-highlight-blue dark:bg-blue-600 w-8 text-white hover:bg-active-blue dark:hover:bg-blue-700 m-1 rounded-md py-1 px-1 transition-colors duration-200"
|
||||
class="bg-highlight-blue dark:bg-highlight-blue/80 w-8 text-white hover:bg-active-blue dark:hover:bg-highlight-blue m-1 rounded-md py-1 px-1 transition-colors duration-200"
|
||||
on:click|preventDefault={previousPage}><<</button
|
||||
>
|
||||
<div
|
||||
class="w-8 text-center bg-grayblue-light dark:bg-gray-700 text-gray-700 dark:text-gray-200 rounded-md py-1 px-1 transition-colors duration-200"
|
||||
class="w-8 text-center bg-grayblue-light dark:bg-gray-800/60 text-gray-700 dark:text-gray-300 rounded-md py-1 px-1 transition-colors duration-200"
|
||||
>
|
||||
{currentPage}
|
||||
</div>
|
||||
<button
|
||||
class="bg-highlight-blue dark:bg-blue-600 w-8 text-white hover:bg-active-blue dark:hover:bg-blue-700 m-1 rounded-md py-1 px-1 transition-colors duration-200"
|
||||
class="bg-highlight-blue dark:bg-highlight-blue/80 w-8 text-white hover:bg-active-blue dark:hover:bg-highlight-blue m-1 rounded-md py-1 px-1 transition-colors duration-200"
|
||||
on:click|preventDefault={nextPage}>>></button
|
||||
>
|
||||
</div>
|
||||
|
||||
@@ -59,7 +59,7 @@
|
||||
|
||||
<label class="flex flex-col py-2 w-60">
|
||||
<div class="flex items-center">
|
||||
<p class="font-semibold text-slate-600 dark:text-gray-300 py-2 transition-colors duration-200">
|
||||
<p class="font-semibold text-slate-600 dark:text-gray-400 py-2 transition-colors duration-200">
|
||||
<slot />
|
||||
</p>
|
||||
{#if toolTipText.length > 0}
|
||||
@@ -69,9 +69,9 @@
|
||||
{/if}
|
||||
{#if optional === true}
|
||||
<div
|
||||
class="bg-gray-100 dark:bg-gray-700 ml-2 px-2 rounded-md transition-colors duration-200 h-6 flex items-center"
|
||||
class="bg-gray-100 dark:bg-gray-800/60 ml-2 px-2 rounded-md transition-colors duration-200 h-6 flex items-center"
|
||||
>
|
||||
<p class="text-slate-600 dark:text-gray-300 text-xs transition-colors duration-200">
|
||||
<p class="text-slate-600 dark:text-gray-400 text-xs transition-colors duration-200">
|
||||
optional
|
||||
</p>
|
||||
</div>
|
||||
@@ -90,7 +90,7 @@
|
||||
minlength={minLength}
|
||||
maxlength={maxLength}
|
||||
{required}
|
||||
class="text-ellipsis w-60 rounded-md py-2 pl-4 pr-12 text-gray-600 dark:text-gray-200 border border-transparent dark:border-gray-600 focus:outline-none focus:border-solid focus:border-slate-400 dark:focus:border-blue-500 focus:bg-gray-100 dark:focus:bg-gray-600 bg-grayblue-light dark:bg-gray-700 font-normal transition-colors duration-200"
|
||||
class="text-ellipsis w-60 rounded-md py-2 pl-4 pr-12 text-gray-600 dark:text-gray-300 border border-transparent dark:border-gray-700/60 focus:outline-none focus:border-solid focus:border-slate-400 dark:focus:border-highlight-blue/80 focus:bg-gray-100 dark:focus:bg-gray-700/60 bg-grayblue-light dark:bg-gray-900/60 font-normal transition-colors duration-200"
|
||||
/>
|
||||
{:else}
|
||||
<input
|
||||
@@ -104,7 +104,7 @@
|
||||
{placeholder}
|
||||
autocomplete="off"
|
||||
{required}
|
||||
class="text-ellipsis w-60 rounded-md py-2 pl-4 pr-12 text-gray-600 dark:text-gray-200 border border-transparent dark:border-gray-600 focus:outline-none focus:border-solid focus:border-slate-400 dark:focus:border-blue-500 focus:bg-gray-100 dark:focus:bg-gray-600 bg-grayblue-light dark:bg-gray-700 font-normal transition-colors duration-200"
|
||||
class="text-ellipsis w-60 rounded-md py-2 pl-4 pr-12 text-gray-600 dark:text-gray-300 border border-transparent dark:border-gray-700/60 focus:outline-none focus:border-solid focus:border-slate-400 dark:focus:border-highlight-blue/80 focus:bg-gray-100 dark:focus:bg-gray-700/60 bg-grayblue-light dark:bg-gray-900/60 font-normal transition-colors duration-200"
|
||||
/>
|
||||
{/if}
|
||||
<button
|
||||
|
||||
@@ -39,7 +39,7 @@
|
||||
setSearch();
|
||||
}
|
||||
}}
|
||||
class="bg-grayblue-light dark:bg-gray-700 w-56 border text-gray-600 dark:text-gray-200 border-gray-300 dark:border-gray-600 pl-8 py-2 relative rounded-lg focus:outline-none focus:ring-0 focus:border-cta-blue dark:focus:border-blue-500 focus:border transition-colors duration-200 dark:placeholder-gray-400"
|
||||
class="bg-grayblue-light dark:bg-gray-900/60 w-56 border text-gray-600 dark:text-gray-300 border-gray-300 dark:border-gray-700/60 pl-8 py-2 relative rounded-lg focus:outline-none focus:ring-0 focus:border-cta-blue dark:focus:border-highlight-blue/80 focus:border transition-colors duration-200 dark:placeholder-gray-500"
|
||||
placeholder="Search"
|
||||
/>
|
||||
</div>
|
||||
|
||||
@@ -22,11 +22,11 @@
|
||||
</script>
|
||||
|
||||
<div>
|
||||
<label for="pet-select" class="text-gray-600 dark:text-gray-300 transition-colors duration-200"
|
||||
<label for="pet-select" class="text-gray-600 dark:text-gray-400 transition-colors duration-200"
|
||||
>Show:</label
|
||||
>
|
||||
<select
|
||||
class="bg-grayblue-light dark:bg-gray-700 px-2 py-1 rounded-md text-gray-600 dark:text-gray-200 border border-transparent dark:border-gray-600 focus:outline-none focus:border-solid focus:border focus:border-slate-400 dark:focus:border-blue-500 focus:bg-gray-100 dark:focus:bg-gray-600 transition-colors duration-200"
|
||||
class="bg-grayblue-light dark:bg-gray-900/60 px-2 py-1 rounded-md text-gray-600 dark:text-gray-300 border border-transparent dark:border-gray-700/60 focus:outline-none focus:border-solid focus:border focus:border-slate-400 dark:focus:border-highlight-blue/80 focus:bg-gray-100 dark:focus:bg-gray-700/60 transition-colors duration-200"
|
||||
name="entries"
|
||||
id="entries"
|
||||
bind:value
|
||||
|
||||
@@ -15,7 +15,7 @@
|
||||
<div class="flex flex-col gap-2 py-2">
|
||||
{#if label}
|
||||
<div class="flex flex-row items-center">
|
||||
<div class="font-semibold text-slate-600 dark:text-gray-300 transition-colors duration-200">
|
||||
<div class="font-semibold text-slate-600 dark:text-gray-400 transition-colors duration-200">
|
||||
{label}
|
||||
</div>
|
||||
{#if toolTipText.length > 0}
|
||||
@@ -25,9 +25,9 @@
|
||||
{/if}
|
||||
{#if optional}
|
||||
<div
|
||||
class="bg-gray-100 dark:bg-gray-700 ml-2 px-2 rounded-md transition-colors duration-200 h-6 flex items-center"
|
||||
class="bg-gray-100 dark:bg-gray-800/60 ml-2 px-2 rounded-md transition-colors duration-200 h-6 flex items-center"
|
||||
>
|
||||
<p class="text-slate-600 dark:text-gray-300 text-xs">optional</p>
|
||||
<p class="text-slate-600 dark:text-gray-400 text-xs">optional</p>
|
||||
</div>
|
||||
{/if}
|
||||
</div>
|
||||
@@ -46,11 +46,11 @@
|
||||
p-3 rounded-lg border-2 transition-all duration-200
|
||||
flex flex-col items-center justify-center text-center
|
||||
w-40
|
||||
hover:border-blue-300 dark:hover:border-blue-500 hover:bg-blue-50 dark:hover:bg-blue-900/30
|
||||
hover:border-blue-300 dark:hover:border-highlight-blue/80 hover:bg-blue-50 dark:hover:bg-highlight-blue/20
|
||||
${
|
||||
value === option.value
|
||||
? 'border-green-500 dark:border-green-400 bg-green-50 dark:bg-green-900/30 text-green-700 dark:text-green-300'
|
||||
: 'border-gray-200 dark:border-gray-600 bg-white dark:bg-gray-800 text-gray-700 dark:text-gray-200'
|
||||
? 'border-green-500 dark:border-green-400 bg-green-50 dark:bg-green-800/40 text-green-700 dark:text-green-300'
|
||||
: 'border-gray-200 dark:border-gray-700/60 bg-white dark:bg-gray-900/60 text-gray-700 dark:text-gray-300'
|
||||
}
|
||||
`}
|
||||
on:click={() => {
|
||||
|
||||
@@ -43,17 +43,17 @@
|
||||
</script>
|
||||
|
||||
<div
|
||||
class="bg-white dark:bg-gray-800 p-6 rounded-lg shadow-md dark:shadow-gray-900/50 border-l-[12px] {borderColor} hover:shadow-lg dark:hover:shadow-gray-900/70 transition-all duration-200"
|
||||
class="bg-white dark:bg-gray-900/80 p-6 rounded-lg shadow-md dark:shadow-none border-l-[12px] {borderColor} hover:shadow-lg dark:hover:shadow-none transition-all duration-200 dark:ring-1 dark:ring-gray-600/30"
|
||||
>
|
||||
<div
|
||||
class="text-grayblue-dark dark:text-gray-400 text-sm font-semibold transition-colors duration-200"
|
||||
class="text-grayblue-dark dark:text-gray-500 text-sm font-semibold transition-colors duration-200"
|
||||
>
|
||||
{title}
|
||||
</div>
|
||||
<div class="flex items-center justify-between">
|
||||
<div class="flex items-center">
|
||||
<span
|
||||
class="text-3xl font-bold text-pc-darkblue dark:text-gray-100 transition-colors duration-200 {flash
|
||||
class="text-3xl font-bold text-pc-darkblue dark:text-gray-300 transition-colors duration-200 {flash
|
||||
? 'flash'
|
||||
: ''}"
|
||||
>
|
||||
@@ -82,13 +82,13 @@
|
||||
|
||||
{#if validPercentages.length > 0}
|
||||
<button
|
||||
class="mt-2 text-sm text-gray-600 dark:text-gray-400 flex items-center transition-colors duration-200"
|
||||
class="mt-2 text-sm text-gray-600 dark:text-gray-500 flex items-center transition-colors duration-200"
|
||||
on:click={cyclePercentage}
|
||||
class:cursor-pointer={validPercentages.length > 1}
|
||||
>
|
||||
<div class="flex items-center">
|
||||
<span
|
||||
class="text-pc-darkblue dark:text-gray-200 font-semibold transition-colors duration-200"
|
||||
class="text-pc-darkblue dark:text-gray-400 font-semibold transition-colors duration-200"
|
||||
>
|
||||
{validPercentages[currentPercentageIndex].value}%
|
||||
</span>
|
||||
@@ -99,7 +99,7 @@
|
||||
{#if validPercentages.length > 1}
|
||||
<svg
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
class="h-4 w-4 ml-1 text-gray-400 dark:text-gray-500 transition-colors duration-200"
|
||||
class="h-4 w-4 ml-1 text-gray-400 dark:text-gray-600 transition-colors duration-200"
|
||||
fill="none"
|
||||
viewBox="0 0 24 24"
|
||||
stroke="currentColor"
|
||||
|
||||
@@ -59,7 +59,7 @@
|
||||
|
||||
<label class="flex flex-col py-2">
|
||||
<div class="flex items-center">
|
||||
<p class="font-semibold text-slate-600 dark:text-gray-300 py-2 transition-colors duration-200">
|
||||
<p class="font-semibold text-slate-600 dark:text-gray-400 py-2 transition-colors duration-200">
|
||||
<slot />
|
||||
</p>
|
||||
{#if toolTipText.length > 0}
|
||||
@@ -69,9 +69,9 @@
|
||||
{/if}
|
||||
{#if optional === true}
|
||||
<div
|
||||
class="bg-gray-100 dark:bg-gray-700 ml-2 px-2 rounded-md transition-colors duration-200 h-6 flex items-center"
|
||||
class="bg-gray-100 dark:bg-gray-800/60 ml-2 px-2 rounded-md transition-colors duration-200 h-6 flex items-center"
|
||||
>
|
||||
<p class="text-slate-600 dark:text-gray-300 text-xs transition-colors duration-200">
|
||||
<p class="text-slate-600 dark:text-gray-400 text-xs transition-colors duration-200">
|
||||
optional
|
||||
</p>
|
||||
</div>
|
||||
@@ -97,7 +97,7 @@
|
||||
{required}
|
||||
{placeholder}
|
||||
{pattern}
|
||||
class="text-ellipsis row-start-1 row-span-3 justify-self-center rounded-md py-2 pl-2 text-gray-600 dark:text-gray-200 border border-transparent dark:border-gray-600 focus:outline-none focus:border-solid focus:border-slate-400 dark:focus:border-blue-500 focus:bg-gray-100 dark:focus:bg-gray-600 bg-grayblue-light dark:bg-gray-700 font-normal transition-colors duration-200"
|
||||
class="text-ellipsis row-start-1 row-span-3 justify-self-center rounded-md py-2 pl-2 text-gray-600 dark:text-gray-300 border border-transparent dark:border-gray-700/60 focus:outline-none focus:border-solid focus:border-slate-400 dark:focus:border-highlight-blue/80 focus:bg-gray-100 dark:focus:bg-gray-700/60 bg-grayblue-light dark:bg-gray-900/60 font-normal transition-colors duration-200"
|
||||
class:w-24={width === 'small'}
|
||||
class:w-60={width === 'medium'}
|
||||
class:w-95={width === 'large'}
|
||||
|
||||
@@ -118,7 +118,7 @@
|
||||
<label class="flex flex-col py-2 relative">
|
||||
<div class="flex items-center">
|
||||
<p
|
||||
class="font-semibold text-slate-600 dark:text-gray-300 py-2 transition-colors duration-200"
|
||||
class="font-semibold text-slate-600 dark:text-gray-400 py-2 transition-colors duration-200"
|
||||
>
|
||||
<slot />
|
||||
</p>
|
||||
@@ -129,9 +129,9 @@
|
||||
{/if}
|
||||
{#if optional === true}
|
||||
<div
|
||||
class="bg-gray-100 dark:bg-gray-700 ml-2 px-2 rounded-md transition-colors duration-200 h-6 flex items-center"
|
||||
class="bg-gray-100 dark:bg-gray-800/60 ml-2 px-2 rounded-md transition-colors duration-200 h-6 flex items-center"
|
||||
>
|
||||
<p class="text-slate-600 dark:text-gray-300 text-xs">optional</p>
|
||||
<p class="text-slate-600 dark:text-gray-400 text-xs">optional</p>
|
||||
</div>
|
||||
{/if}
|
||||
</div>
|
||||
@@ -155,7 +155,7 @@
|
||||
{id}
|
||||
required={required && !value.length}
|
||||
autocomplete="off"
|
||||
class="w-full relative rounded-md py-2 pl-4 focus:pl-10 text-gray-600 dark:text-gray-300 border border-transparent focus:outline-none focus:border-solid focus:border focus:border-slate-400 dark:focus:border-gray-500 focus:bg-gray-100 dark:focus:bg-gray-600 bg-grayblue-light dark:bg-gray-700 font-normal cursor-pointer focus:cursor-text transition-colors duration-200"
|
||||
class="w-full relative rounded-md py-2 pl-4 focus:pl-10 text-gray-600 dark:text-gray-300 border border-transparent focus:outline-none focus:border-solid focus:border focus:border-slate-400 dark:focus:border-highlight-blue/80 focus:bg-gray-100 dark:focus:bg-gray-700/60 bg-grayblue-light dark:bg-gray-900/60 font-normal cursor-pointer focus:cursor-text transition-colors duration-200"
|
||||
/>
|
||||
{#if showSelection}
|
||||
<img
|
||||
@@ -169,13 +169,13 @@
|
||||
{#if showSelection}
|
||||
<div class="w-60 absolute top-10 z-50">
|
||||
<ul
|
||||
class="bg-gray-100 dark:bg-gray-700 list-none mt-4 rounded-md min-w-fit shadow-md border border-gray-200 dark:border-gray-600 max-h-40 overflow-y-scroll transition-colors duration-200"
|
||||
class="bg-gray-100 dark:bg-gray-900 list-none mt-4 rounded-md min-w-fit shadow-md border border-gray-200 dark:border-gray-700/60 max-h-40 overflow-y-scroll transition-colors duration-200"
|
||||
>
|
||||
{#if options.length}
|
||||
{#each filteredOptions as option}
|
||||
<li>
|
||||
<button
|
||||
class="w-full text-left bg-slate-100 dark:bg-gray-700 rounded-md text-gray-600 dark:text-gray-200 hover:bg-grayblue-dark dark:hover:bg-gray-500 hover:text-white py-2 px-2 cursor-pointer transition-colors duration-200"
|
||||
class="w-full text-left bg-slate-100 dark:bg-gray-900 rounded-md text-gray-600 dark:text-gray-300 hover:bg-grayblue-dark dark:hover:bg-highlight-blue/40 hover:text-white py-2 px-2 cursor-pointer transition-colors duration-200"
|
||||
on:click={() => {
|
||||
onClickSelectedOption(option);
|
||||
}}
|
||||
@@ -186,7 +186,7 @@
|
||||
{/each}
|
||||
{:else}
|
||||
<li
|
||||
class="w-full bg-slate-100 dark:bg-gray-700 text-gray-600 dark:text-gray-300 py-2 px-2 transition-colors duration-200"
|
||||
class="w-full bg-slate-100 dark:bg-gray-900 text-gray-600 dark:text-gray-400 py-2 px-2 transition-colors duration-200"
|
||||
>
|
||||
List is empty
|
||||
</li>
|
||||
@@ -200,7 +200,7 @@
|
||||
on:click|preventDefault={removeSelection}
|
||||
on:keypress|preventDefault={removeSelection}
|
||||
data-value={option}
|
||||
class="flex flex-row items-center bg-gray-100 dark:bg-gray-700 hover:bg-gray-200 dark:hover:bg-gray-600 px-2 py-2 mt-2 mr-2 rounded-md text-gray-900 dark:text-gray-100 transition-colors duration-200"
|
||||
class="flex flex-row items-center bg-gray-100 dark:bg-gray-800/60 hover:bg-gray-200 dark:hover:bg-gray-700/80 px-2 py-2 mt-2 mr-2 rounded-md text-gray-900 dark:text-gray-300 transition-colors duration-200"
|
||||
>
|
||||
{option}
|
||||
<img class="w-4 ml-2 pointer-events-none" src="/delete2.svg" alt="delete" />
|
||||
|
||||
@@ -237,7 +237,7 @@
|
||||
<div class="flex items-center">
|
||||
<p
|
||||
id={labelId}
|
||||
class="font-semibold text-slate-600 dark:text-gray-300 py-1 transition-colors duration-200"
|
||||
class="font-semibold text-slate-600 dark:text-gray-400 py-1 transition-colors duration-200"
|
||||
>
|
||||
<slot />
|
||||
</p>
|
||||
@@ -248,9 +248,9 @@
|
||||
{/if}
|
||||
{#if optional === true}
|
||||
<div
|
||||
class="bg-gray-100 dark:bg-gray-700 ml-2 px-2 rounded-md transition-colors duration-200 h-6 flex items-center"
|
||||
class="bg-gray-100 dark:bg-gray-800/60 ml-2 px-2 rounded-md transition-colors duration-200 h-6 flex items-center"
|
||||
>
|
||||
<p class="text-slate-600 dark:text-gray-300 text-xs">optional</p>
|
||||
<p class="text-slate-600 dark:text-gray-400 text-xs">optional</p>
|
||||
</div>
|
||||
{/if}
|
||||
</div>
|
||||
@@ -278,7 +278,7 @@
|
||||
on:keydown={handleKeyDown}
|
||||
on:click={handleFocus}
|
||||
autocomplete="off"
|
||||
class="w-full relative rounded-md py-2 pr-10 text-gray-600 dark:text-gray-300 border border-transparent focus:outline-none focus:border-solid focus:border focus:border-slate-400 dark:focus:border-gray-500 focus:bg-gray-100 dark:focus:bg-gray-600 bg-grayblue-light dark:bg-gray-700 font-normal cursor-pointer focus:cursor-text transition-colors duration-200"
|
||||
class="w-full relative rounded-md py-2 pr-10 text-gray-600 dark:text-gray-300 border border-transparent focus:outline-none focus:border-solid focus:border focus:border-slate-400 dark:focus:border-highlight-blue/80 focus:bg-gray-100 dark:focus:bg-gray-700/60 bg-grayblue-light dark:bg-gray-900/60 font-normal cursor-pointer focus:cursor-text transition-colors duration-200"
|
||||
class:pl-10={showDropdown}
|
||||
class:pl-4={!showDropdown}
|
||||
class:text-gray-400={!hasValue && !showDropdown}
|
||||
@@ -331,7 +331,7 @@
|
||||
id={listboxId}
|
||||
role="listbox"
|
||||
aria-labelledby={labelId}
|
||||
class="bg-gray-100 dark:bg-gray-700 list-none mt-4 z-[999] rounded-md min-w-fit shadow-md border border-gray-200 dark:border-gray-600 max-h-40 overflow-y-scroll transition-colors duration-200"
|
||||
class="bg-gray-100 dark:bg-gray-900 list-none mt-4 z-[999] rounded-md min-w-fit shadow-md border border-gray-200 dark:border-gray-700/60 max-h-40 overflow-y-scroll transition-colors duration-200"
|
||||
>
|
||||
{#if allOptions.length}
|
||||
{#each allOptions as option, index}
|
||||
@@ -340,7 +340,7 @@
|
||||
id="{listboxId}-option-{index}"
|
||||
role="option"
|
||||
aria-selected={value === option}
|
||||
class="w-full text-left bg-slate-100 dark:bg-gray-700 rounded-md text-gray-600 dark:text-gray-200 hover:bg-grayblue-dark dark:hover:bg-gray-500 hover:text-white py-2 px-2 cursor-pointer focus:bg-grayblue-dark dark:focus:bg-gray-500 focus:text-white focus:outline-none transition-colors duration-200"
|
||||
class="w-full text-left bg-slate-100 dark:bg-gray-900 rounded-md text-gray-600 dark:text-gray-300 hover:bg-grayblue-dark dark:hover:bg-highlight-blue/40 hover:text-white py-2 px-2 cursor-pointer focus:bg-grayblue-dark dark:focus:bg-highlight-blue/40 focus:text-white focus:outline-none transition-colors duration-200"
|
||||
on:click={(e) => {
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
@@ -356,7 +356,7 @@
|
||||
{:else}
|
||||
<li
|
||||
role="none"
|
||||
class="w-full bg-slate-100 dark:bg-gray-700 text-gray-600 dark:text-gray-300 py-2 px-2 transition-colors duration-200"
|
||||
class="w-full bg-slate-100 dark:bg-gray-900 text-gray-600 dark:text-gray-400 py-2 px-2 transition-colors duration-200"
|
||||
>
|
||||
No options available
|
||||
</li>
|
||||
|
||||
@@ -52,7 +52,7 @@
|
||||
|
||||
<label class="flex flex-col py-2 w-60" class:w-full={fullWidth}>
|
||||
<div class="flex items-center">
|
||||
<p class="font-bold text-slate-600 dark:text-gray-300 py-2 transition-colors duration-200">
|
||||
<p class="font-bold text-slate-600 dark:text-gray-400 py-2 transition-colors duration-200">
|
||||
<slot />
|
||||
</p>
|
||||
{#if toolTipText.length > 0}
|
||||
@@ -62,9 +62,9 @@
|
||||
{/if}
|
||||
{#if optional === true}
|
||||
<div
|
||||
class="bg-gray-100 dark:bg-gray-700 ml-2 px-2 rounded-md transition-colors duration-200 h-6 flex items-center"
|
||||
class="bg-gray-100 dark:bg-gray-800/60 ml-2 px-2 rounded-md transition-colors duration-200 h-6 flex items-center"
|
||||
>
|
||||
<p class="text-slate-600 dark:text-gray-300 text-xs transition-colors duration-200">
|
||||
<p class="text-slate-600 dark:text-gray-400 text-xs transition-colors duration-200">
|
||||
optional
|
||||
</p>
|
||||
</div>
|
||||
@@ -80,7 +80,7 @@
|
||||
maxlength={maxLength}
|
||||
{readonly}
|
||||
{placeholder}
|
||||
class=" focus:outline-none pl-2 border border-transparent dark:border-gray-600 rounded-md focus:border-solid text-gray-600 dark:text-gray-200 focus:bg-gray-100 dark:focus:bg-gray-600 font-light focus:border-slate-400 dark:focus:border-blue-500 bg-grayblue-light dark:bg-gray-700 transition-colors duration-200"
|
||||
class=" focus:outline-none pl-2 border border-transparent dark:border-gray-700/60 rounded-md focus:border-solid text-gray-600 dark:text-gray-300 focus:bg-gray-100 dark:focus:bg-gray-700/60 font-light focus:border-slate-400 dark:focus:border-highlight-blue/80 bg-grayblue-light dark:bg-gray-900/60 transition-colors duration-200"
|
||||
class:h-16={height === 'small'}
|
||||
class:h-28={height === 'medium'}
|
||||
class:h-48={height === 'large'}
|
||||
|
||||
@@ -30,7 +30,7 @@
|
||||
}
|
||||
}}
|
||||
transition:slide|global
|
||||
class="flex items-center bg-pleasant-gray dark:bg-gray-700 text-gray-500 dark:text-gray-200 shadow-lg dark:shadow-gray-900/50 capitalize text-xl p-4 first:mt-0 mt-4 min-w-max rounded-md justify-self-center w-full transition-colors duration-200"
|
||||
class="flex items-center bg-pleasant-gray dark:bg-gray-800/80 text-gray-500 dark:text-gray-300 shadow-lg dark:shadow-gray-900/50 capitalize text-xl p-4 first:mt-0 mt-4 min-w-max rounded-md justify-self-center w-full transition-colors duration-200"
|
||||
>
|
||||
<!-- <img class="w-9 mr-6" draggable="false" src={src1} alt="checkmark success" /> -->
|
||||
<svg class="w-11 mr-6" viewBox="0 0 32.25 32.4">
|
||||
@@ -60,7 +60,7 @@
|
||||
}
|
||||
}}
|
||||
transition:slide|global
|
||||
class="flex items-center bg-pleasant-gray dark:bg-gray-700 text-gray-500 dark:text-gray-200 shadow-lg dark:shadow-gray-900/50 capitalize text-xl p-4 first:mt-0 mt-4 min-w-max rounded-md justify-self-center w-full transition-colors duration-200"
|
||||
class="flex items-center bg-pleasant-gray dark:bg-gray-800/80 text-gray-500 dark:text-gray-300 shadow-lg dark:shadow-gray-900/50 capitalize text-xl p-4 first:mt-0 mt-4 min-w-max rounded-md justify-self-center w-full transition-colors duration-200"
|
||||
>
|
||||
<!-- <img class="w-9 mr-6" draggable="false" src="/t-warning.svg" alt="checkmark warning" /> -->
|
||||
<svg class="w-11 mr-6" viewBox="0 0 36.26 32.41">
|
||||
@@ -101,7 +101,7 @@
|
||||
}
|
||||
}}
|
||||
transition:slide|global
|
||||
class="flex items-center bg-pleasant-gray dark:bg-gray-700 text-gray-500 dark:text-gray-200 shadow-lg dark:shadow-gray-900/50 capitalize text-xl p-4 first:mt-0 mt-4 min-w-max rounded-md justify-self-center w-full transition-colors duration-200"
|
||||
class="flex items-center bg-pleasant-gray dark:bg-gray-800/80 text-gray-500 dark:text-gray-300 shadow-lg dark:shadow-gray-900/50 capitalize text-xl p-4 first:mt-0 mt-4 min-w-max rounded-md justify-self-center w-full transition-colors duration-200"
|
||||
>
|
||||
<!-- <img class="w-9 mr-6" draggable="false" src="/t-error.svg" alt="checkmark error" /> -->
|
||||
<svg class="w-11 mr-6" viewBox="0 0 32.98 32.98">
|
||||
@@ -143,7 +143,7 @@
|
||||
removeToast(toast.id);
|
||||
}
|
||||
}}
|
||||
class="flex items-center bg-pleasant-gray dark:bg-gray-700 text-gray-500 dark:text-gray-200 shadow-lg dark:shadow-gray-900/50 capitalize text-xl p-4 first:mt-0 mt-4 min-w-max rounded-md justify-self-center w-full transition-colors duration-200"
|
||||
class="flex items-center bg-pleasant-gray dark:bg-gray-800/80 text-gray-500 dark:text-gray-300 shadow-lg dark:shadow-gray-900/50 capitalize text-xl p-4 first:mt-0 mt-4 min-w-max rounded-md justify-self-center w-full transition-colors duration-200"
|
||||
>
|
||||
<!-- <img class="w-9 mr-6" draggable="false" src="/t-info.svg" alt="checkmark info" /> -->
|
||||
<svg class="w-11 mr-6" viewBox="0 0 32.79 32.79">
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
</script>
|
||||
|
||||
<div
|
||||
class="rounded-full bg-gray-600 dark:bg-gray-500 text-white w-4 h-4 z-30 text-center ml-2 relative cursor-pointer hover:bg-gray-500 dark:hover:bg-gray-400 transition-colors duration-200"
|
||||
class="rounded-full bg-gray-600 dark:bg-gray-700/80 text-white w-4 h-4 z-30 text-center ml-2 relative cursor-pointer hover:bg-gray-500 dark:hover:bg-gray-600/80 transition-colors duration-200"
|
||||
role="tooltip"
|
||||
aria-describedby={tooltipId}
|
||||
on:mouseenter={(e) => {
|
||||
@@ -27,7 +27,7 @@
|
||||
{#if showToolTip}
|
||||
<div
|
||||
id={tooltipId}
|
||||
class="bg-gray-600 dark:bg-gray-700 text-white w-max mt-2 px-2 py-2 rounded-md shadow-xl dark:shadow-gray-900/70 z-40 transition-colors duration-200"
|
||||
class="bg-gray-600 dark:bg-gray-800/90 text-white w-max mt-2 px-2 py-2 rounded-md shadow-xl dark:shadow-gray-900/70 z-40 transition-colors duration-200"
|
||||
style={tooltipStyle}
|
||||
>
|
||||
<p><slot /></p>
|
||||
|
||||
@@ -16,14 +16,14 @@
|
||||
}
|
||||
</script>
|
||||
|
||||
<div class="inline-flex bg-gray-100 dark:bg-gray-700 rounded p-0.5">
|
||||
<div class="inline-flex bg-gray-100 dark:bg-gray-800/60 rounded p-0.5">
|
||||
{#each options as option}
|
||||
<button
|
||||
type="button"
|
||||
class="w-6 h-6 text-xs rounded transition-colors duration-150 flex items-center justify-center {value ===
|
||||
option.value
|
||||
? 'bg-white dark:bg-gray-600 text-gray-900 dark:text-white shadow-sm'
|
||||
: 'text-gray-600 dark:text-gray-300 hover:text-gray-900 dark:hover:text-white'} {disabled
|
||||
? 'bg-white dark:bg-gray-700/80 text-gray-900 dark:text-white shadow-sm'
|
||||
: 'text-gray-600 dark:text-gray-400 hover:text-gray-900 dark:hover:text-white'} {disabled
|
||||
? 'opacity-50 cursor-not-allowed'
|
||||
: 'cursor-pointer'}"
|
||||
on:click={() => handleChange(option.value)}
|
||||
|
||||
@@ -240,7 +240,7 @@
|
||||
<div class="flex items-center">
|
||||
<p
|
||||
id={labelId}
|
||||
class="font-semibold text-slate-600 dark:text-gray-300 py-1 transition-colors duration-200"
|
||||
class="font-semibold text-slate-600 dark:text-gray-400 py-1 transition-colors duration-200"
|
||||
>
|
||||
<slot />
|
||||
</p>
|
||||
@@ -251,9 +251,9 @@
|
||||
{/if}
|
||||
{#if optional === true}
|
||||
<div
|
||||
class="bg-gray-100 dark:bg-gray-700 ml-2 px-2 rounded-md transition-colors duration-200"
|
||||
class="bg-gray-100 dark:bg-gray-800/60 ml-2 px-2 rounded-md transition-colors duration-200"
|
||||
>
|
||||
<p class="text-slate-600 dark:text-gray-300 text-xs">optional</p>
|
||||
<p class="text-slate-600 dark:text-gray-400 text-xs">optional</p>
|
||||
</div>
|
||||
{/if}
|
||||
</div>
|
||||
@@ -265,8 +265,8 @@
|
||||
type="button"
|
||||
class="w-8 h-8 text-base transition-all duration-200 rounded-lg border flex items-center justify-center {type ===
|
||||
'page'
|
||||
? 'border-green-500 dark:border-green-400 bg-green-50 dark:bg-green-900/30 text-green-700 dark:text-green-300'
|
||||
: 'border-gray-200 dark:border-gray-600 bg-grayblue-light dark:bg-gray-700 text-gray-700 dark:text-gray-200 hover:border-blue-300 dark:hover:border-blue-500 hover:bg-blue-50 dark:hover:bg-blue-900/30'}"
|
||||
? 'border-green-500 dark:border-green-400 bg-green-50 dark:bg-green-800/40 text-green-700 dark:text-green-300'
|
||||
: 'border-gray-200 dark:border-gray-700/60 bg-grayblue-light dark:bg-gray-800/60 text-gray-700 dark:text-gray-300 hover:border-blue-300 dark:hover:border-highlight-blue/80 hover:bg-blue-50 dark:hover:bg-highlight-blue/20'}"
|
||||
on:click={() => handleTypeChange('page')}
|
||||
title="Page"
|
||||
>
|
||||
@@ -276,8 +276,8 @@
|
||||
type="button"
|
||||
class="w-8 h-8 text-base transition-all duration-200 rounded-lg border flex items-center justify-center ml-0.5 {type ===
|
||||
'proxy'
|
||||
? 'border-green-500 dark:border-green-400 bg-green-50 dark:bg-green-900/30 text-green-700 dark:text-green-300'
|
||||
: 'border-gray-200 dark:border-gray-600 bg-grayblue-light dark:bg-gray-700 text-gray-700 dark:text-gray-200 hover:border-blue-300 dark:hover:border-blue-500 hover:bg-blue-50 dark:hover:bg-blue-900/30'}"
|
||||
? 'border-green-500 dark:border-green-400 bg-green-50 dark:bg-green-800/40 text-green-700 dark:text-green-300'
|
||||
: 'border-gray-200 dark:border-gray-700/60 bg-grayblue-light dark:bg-gray-800/60 text-gray-700 dark:text-gray-300 hover:border-blue-300 dark:hover:border-highlight-blue/80 hover:bg-blue-50 dark:hover:bg-highlight-blue/20'}"
|
||||
on:click={() => handleTypeChange('proxy')}
|
||||
title="Proxy"
|
||||
>
|
||||
@@ -308,7 +308,7 @@
|
||||
on:keydown={handleKeyDown}
|
||||
on:click={handleFocus}
|
||||
autocomplete="off"
|
||||
class="w-full relative rounded-md py-2 pr-10 text-gray-600 dark:text-gray-300 border border-transparent focus:outline-none focus:border-solid focus:border focus:border-slate-400 dark:focus:border-gray-500 focus:bg-gray-100 dark:focus:bg-gray-600 bg-grayblue-light dark:bg-gray-700 font-normal cursor-pointer focus:cursor-text transition-colors duration-200"
|
||||
class="w-full relative rounded-md py-2 pr-10 text-gray-600 dark:text-gray-300 border border-transparent focus:outline-none focus:border-solid focus:border focus:border-slate-400 dark:focus:border-highlight-blue/80 focus:bg-gray-100 dark:focus:bg-gray-700/60 bg-grayblue-light dark:bg-gray-900/60 font-normal cursor-pointer focus:cursor-text transition-colors duration-200"
|
||||
class:pl-10={isFocused && showDropdown}
|
||||
class:pl-20={!isFocused}
|
||||
class:pl-4={isFocused && !showDropdown}
|
||||
@@ -363,7 +363,7 @@
|
||||
id={listboxId}
|
||||
role="listbox"
|
||||
aria-labelledby={labelId}
|
||||
class="bg-gray-100 dark:bg-gray-700 list-none mt-4 z-[999] rounded-md min-w-fit shadow-md border border-gray-200 dark:border-gray-600 max-h-40 overflow-y-scroll transition-colors duration-200"
|
||||
class="bg-gray-100 dark:bg-gray-900 list-none mt-4 z-[999] rounded-md min-w-fit shadow-md border border-gray-200 dark:border-gray-700/60 max-h-40 overflow-y-scroll transition-colors duration-200"
|
||||
>
|
||||
{#if allOptions.length}
|
||||
{#each allOptions as option, index}
|
||||
@@ -372,7 +372,7 @@
|
||||
id="{listboxId}-option-{index}"
|
||||
role="option"
|
||||
aria-selected={value === option}
|
||||
class="w-full text-left bg-slate-100 dark:bg-gray-700 rounded-md text-gray-600 dark:text-gray-200 hover:bg-grayblue-dark dark:hover:bg-gray-500 hover:text-white py-2 px-2 cursor-pointer focus:bg-grayblue-dark dark:focus:bg-gray-500 focus:text-white focus:outline-none transition-colors duration-200"
|
||||
class="w-full text-left bg-slate-100 dark:bg-gray-900 rounded-md text-gray-600 dark:text-gray-300 hover:bg-grayblue-dark dark:hover:bg-highlight-blue/40 hover:text-white py-2 px-2 cursor-pointer focus:bg-grayblue-dark dark:focus:bg-highlight-blue/40 focus:text-white focus:outline-none transition-colors duration-200"
|
||||
on:click={(e) => {
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
@@ -388,7 +388,7 @@
|
||||
{:else}
|
||||
<li
|
||||
role="none"
|
||||
class="w-full bg-slate-100 dark:bg-gray-700 text-gray-600 dark:text-gray-300 py-2 px-2 transition-colors duration-200"
|
||||
class="w-full bg-slate-100 dark:bg-gray-900 text-gray-600 dark:text-gray-400 py-2 px-2 transition-colors duration-200"
|
||||
>
|
||||
No {type === 'proxy' ? 'Proxies' : 'pages'} available
|
||||
</li>
|
||||
|
||||
@@ -0,0 +1,53 @@
|
||||
<script>
|
||||
import { AppStateService } from '$lib/service/appState';
|
||||
import { onMount } from 'svelte';
|
||||
|
||||
let context = {
|
||||
current: '',
|
||||
companyName: ''
|
||||
};
|
||||
|
||||
const appState = AppStateService.instance;
|
||||
|
||||
onMount(() => {
|
||||
const unsub = appState.subscribe((s) => {
|
||||
context = {
|
||||
current: s.context.current,
|
||||
companyName: s.context.companyName
|
||||
};
|
||||
});
|
||||
return () => {
|
||||
unsub();
|
||||
};
|
||||
});
|
||||
</script>
|
||||
|
||||
{#if context.current === AppStateService.CONTEXT.COMPANY && context.companyName}
|
||||
<div
|
||||
class="sticky top-0 w-full bg-blue-900 dark:bg-gradient-to-r dark:from-emerald-700 dark:to-teal-700 border-b border-blue-800/50 dark:border-emerald-600/50 z-30"
|
||||
>
|
||||
<div class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
|
||||
<div class="flex items-center justify-center py-1">
|
||||
<div class="flex items-center space-x-2 text-xs">
|
||||
<svg
|
||||
class="w-3 h-3 text-blue-100 dark:text-emerald-100"
|
||||
fill="none"
|
||||
stroke="currentColor"
|
||||
viewBox="0 0 24 24"
|
||||
>
|
||||
<path
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
stroke-width="2"
|
||||
d="M19 21V5a2 2 0 00-2-2H7a2 2 0 00-2 2v16m14 0h2m-2 0h-5m-9 0H3m2 0h5M9 7h1m-1 4h1m4-4h1m-1 4h1m-5 10v-5a1 1 0 011-1h2a1 1 0 011 1v5m-4 0h4"
|
||||
></path>
|
||||
</svg>
|
||||
<span class="text-blue-100 dark:text-emerald-100 font-medium">Viewing as:</span>
|
||||
<span class="text-white dark:text-white font-semibold">
|
||||
{context.companyName}
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{/if}
|
||||
@@ -3,8 +3,57 @@
|
||||
import { page } from '$app/stores';
|
||||
import { scrollBarClassesVertical } from '$lib/utils/scrollbar';
|
||||
import { shouldHideMenuItem } from '$lib/utils/common';
|
||||
import { AppStateService } from '$lib/service/appState';
|
||||
import { onMount } from 'svelte';
|
||||
import { beforeNavigate } from '$app/navigation';
|
||||
|
||||
let isExpanded = false;
|
||||
let menuElement;
|
||||
let instantCollapse = false;
|
||||
let context = {
|
||||
current: '',
|
||||
companyName: ''
|
||||
};
|
||||
|
||||
const appState = AppStateService.instance;
|
||||
|
||||
onMount(() => {
|
||||
const unsub = appState.subscribe((s) => {
|
||||
context = {
|
||||
current: s.context.current,
|
||||
companyName: s.context.companyName
|
||||
};
|
||||
});
|
||||
|
||||
// handle click outside to collapse menu
|
||||
const handleClickOutside = (event) => {
|
||||
if (isExpanded && menuElement && !menuElement.contains(event.target)) {
|
||||
isExpanded = false;
|
||||
}
|
||||
};
|
||||
|
||||
document.addEventListener('click', handleClickOutside);
|
||||
|
||||
return () => {
|
||||
unsub();
|
||||
document.removeEventListener('click', handleClickOutside);
|
||||
};
|
||||
});
|
||||
|
||||
// handle navigation to collapse menu
|
||||
beforeNavigate(() => {
|
||||
if (isExpanded) {
|
||||
instantCollapse = true;
|
||||
isExpanded = false;
|
||||
// reset after a brief moment
|
||||
setTimeout(() => {
|
||||
instantCollapse = false;
|
||||
}, 50);
|
||||
}
|
||||
});
|
||||
|
||||
$: hasCompanySelected =
|
||||
context.current === AppStateService.CONTEXT.COMPANY && context.companyName;
|
||||
|
||||
const icons = {
|
||||
dashboard: `<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" class="size-6">
|
||||
@@ -98,19 +147,23 @@
|
||||
|
||||
<div class="flex">
|
||||
<nav
|
||||
class="hidden lg:flex flex-col transition-all fixed top-16 z-10 bg-gradient-to-b from-pc-darkblue to-indigo-400 dark:from-gray-900 dark:to-gray-800 rounded-br-lg overflow-y-auto overflow-x-hidden min-h-0 max-h-[calc(100vh-4rem)] box-content border-r-[1px] border-pc-darkblue dark:border-gray-700"
|
||||
bind:this={menuElement}
|
||||
class="hidden lg:flex flex-col fixed top-16 z-10 bg-gradient-to-b from-pc-darkblue to-indigo-400 dark:from-gray-900 dark:to-gray-800 rounded-br-lg overflow-y-auto overflow-x-hidden min-h-0 max-h-[calc(100vh-4rem)] box-content border-r-[1px] border-pc-darkblue dark:border-highlight-blue/40"
|
||||
class:transition-all={!instantCollapse}
|
||||
class:w-40={isExpanded}
|
||||
class:w-12={!isExpanded}
|
||||
class:!top-[89px]={hasCompanySelected}
|
||||
class:!max-h-[calc(100vh-6rem)]={hasCompanySelected}
|
||||
>
|
||||
<div
|
||||
class="sticky top-0 bg-highlight-blue/20 dark:bg-gray-800/70 border-b w-full border-blue-700/30 dark:border-gray-600 transform-none transition-colors duration-200"
|
||||
class="sticky top-0 bg-highlight-blue/20 dark:bg-gray-800/70 border-b w-full border-blue-700/30 dark:border-highlight-blue/40 transform-none transition-colors duration-200"
|
||||
>
|
||||
<button
|
||||
class="w-full flex items-center justify-center rounded-md hover:bg-blue-600/30 dark:hover:bg-gray-700/70 transition-colors group px-3 py-2"
|
||||
class="w-full flex items-center justify-center rounded-md hover:bg-blue-600/30 dark:hover:bg-highlight-blue/20 transition-colors group px-3 py-2"
|
||||
on:click={() => (isExpanded = !isExpanded)}
|
||||
>
|
||||
<svg
|
||||
class="text-blue-100 dark:text-gray-100 duration-200 w-6 transition-colors"
|
||||
class="text-blue-100 dark:text-highlight-blue duration-200 w-6 transition-colors"
|
||||
class:rotate-180={!isExpanded}
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
fill="none"
|
||||
@@ -136,7 +189,7 @@
|
||||
<div class="py-1 mt-4 first:mt-0">
|
||||
{#if isExpanded}
|
||||
<div
|
||||
class="px-3 py-2 text-xs font-semibold text-blue-100 dark:text-gray-200 uppercase tracking-wider transition-colors duration-200"
|
||||
class="px-3 py-2 text-xs font-semibold text-blue-100 dark:text-highlight-blue uppercase tracking-wider transition-colors duration-200"
|
||||
>
|
||||
{link.label}
|
||||
</div>
|
||||
@@ -147,15 +200,15 @@
|
||||
<a
|
||||
class="flex items-center px-3 py-2 text-sm transition-all duration-150 relative group
|
||||
{$page.url.pathname === item.route
|
||||
? 'text-white font-medium bg-active-blue dark:bg-indigo-600 shadow-md'
|
||||
: 'text-blue-100 dark:text-gray-200 hover:shadow-md hover:bg-highlight-blue dark:hover:bg-gray-700 hover:text-white dark:hover:text-gray-100'}"
|
||||
? 'text-white font-medium bg-active-blue dark:bg-active-blue shadow-md'
|
||||
: 'text-blue-100 dark:text-gray-200 hover:shadow-md hover:bg-highlight-blue/80 dark:hover:bg-highlight-blue/20 hover:text-white dark:hover:text-gray-100'}"
|
||||
class:hidden={shouldHideMenuItem(item.route)}
|
||||
draggable="false"
|
||||
href={item.route}
|
||||
title={item.label}
|
||||
>
|
||||
<!-- Icon -->
|
||||
<div class="flex-shrink-0">
|
||||
<div class="flex-shrink-0 text-blue-100 dark:text-highlight-blue">
|
||||
{@html getIconForRoute(item.route)}
|
||||
</div>
|
||||
|
||||
@@ -172,7 +225,9 @@
|
||||
{/if}
|
||||
|
||||
{#if $page.url.pathname === item.route}
|
||||
<div class="absolute left-0 top-0 bottom-0 w-1 bg-white dark:bg-blue-400"></div>
|
||||
<div
|
||||
class="absolute left-0 top-0 bottom-0 w-1 bg-white dark:bg-highlight-blue"
|
||||
></div>
|
||||
{/if}
|
||||
</a>
|
||||
{/each}
|
||||
@@ -182,13 +237,13 @@
|
||||
<a
|
||||
class="flex items-center px-3 py-2 text-sm transition-all duration-150 relative group
|
||||
{$page.url.pathname === link.route
|
||||
? 'text-white font-medium bg-active-blue dark:bg-indigo-600 shadow-md'
|
||||
: 'text-blue-100 dark:text-gray-200 hover:text-white dark:hover:text-gray-100 dark:hover:bg-gray-700'}"
|
||||
? 'text-white font-medium bg-active-blue dark:bg-active-blue shadow-md'
|
||||
: 'text-blue-100 dark:text-gray-200 hover:text-white dark:hover:text-gray-100 hover:bg-highlight-blue/80 dark:hover:bg-highlight-blue/20'}"
|
||||
draggable="false"
|
||||
href={link.route}
|
||||
>
|
||||
<!-- Icon -->
|
||||
<div class="flex-shrink-0">
|
||||
<div class="flex-shrink-0 text-blue-100 dark:text-highlight-blue">
|
||||
{@html icons[link.label]}
|
||||
</div>
|
||||
|
||||
@@ -196,16 +251,16 @@
|
||||
<span class="ml-3 truncate">{link.label}</span>
|
||||
{:else}
|
||||
<div
|
||||
class="absolute left-14 rounded bg-gray-900 dark:bg-gray-800 text-white dark:text-gray-100 px-2 py-1 ml-6 text-sm
|
||||
class="absolute left-14 rounded bg-gray-900 dark:bg-gray-800 dark:border-highlight-blue/40 text-white dark:text-highlight-blue px-2 py-1 ml-6 text-sm
|
||||
invisible opacity-0 -translate-x-3 group-hover:visible group-hover:opacity-100 group-hover:translate-x-0
|
||||
transition-all duration-150 whitespace-nowrap z-50 shadow-lg border dark:border-gray-600"
|
||||
transition-all duration-150 whitespace-nowrap z-50 shadow-lg border dark:border-highlight-blue/40"
|
||||
>
|
||||
{link.label}
|
||||
</div>
|
||||
{/if}
|
||||
|
||||
{#if $page.url.pathname === link.route}
|
||||
<div class="absolute left-0 top-0 bottom-0 w-1 bg-white dark:bg-blue-400"></div>
|
||||
<div class="absolute left-0 top-0 bottom-0 w-1 bg-white dark:bg-highlight-blue"></div>
|
||||
{/if}
|
||||
</a>
|
||||
{/if}
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
import { onMount } from 'svelte';
|
||||
import Logo from './Logo.svelte';
|
||||
import ThemeToggle from '../ThemeToggle.svelte';
|
||||
import CompanyBanner from './CompanyBanner.svelte';
|
||||
|
||||
const appState = AppStateService.instance;
|
||||
|
||||
@@ -64,12 +65,12 @@
|
||||
}
|
||||
|
||||
function profilePattern(username) {
|
||||
// Create consistent hash
|
||||
// create consistent hash
|
||||
const hash = username.split('').reduce((acc, char) => {
|
||||
return char.charCodeAt(0) + ((acc << 5) - acc);
|
||||
}, 0);
|
||||
|
||||
// Generate base colors
|
||||
// generate base colors
|
||||
const hue = Math.abs(hash) % 360;
|
||||
const colors = {
|
||||
primary: `hsl(${hue}, 70%, 50%)`,
|
||||
@@ -77,7 +78,7 @@
|
||||
accent: `hsl(${(hue + 240) % 360}, 70%, 50%)`
|
||||
};
|
||||
|
||||
// Generate pattern parameters
|
||||
// generate pattern parameters
|
||||
const params = {
|
||||
rotation: hash % 360,
|
||||
segments: 6 + (hash % 6),
|
||||
@@ -113,91 +114,77 @@
|
||||
$: initials = getInitials(username || 'U');
|
||||
</script>
|
||||
|
||||
<div
|
||||
class="header-container sticky top-0 z-20 col-span-12 h-16 bg-pc-darkblue dark:bg-gray-800 border-b border-pc-darkblue/20 dark:border-gray-700 flex justify-between items-center"
|
||||
>
|
||||
<Logo />
|
||||
{#if isInstalled}
|
||||
<div class="hidden lg:flex flex-row items-center px-8 h-full justify-self-end">
|
||||
{#if context.current === AppStateService.CONTEXT.COMPANY}
|
||||
<p class="text-slate-300 dark:text-gray-300 uppercase font-bold text-lg mr-4">
|
||||
{context.companyName}
|
||||
</p>
|
||||
{/if}
|
||||
<button
|
||||
class="rounded-md h-3/4 px-8 text-white bg-indigo-500 hover:bg-cta-blue dark:bg-indigo-600 dark:hover:bg-indigo-700 uppercase font-semibold mr-4 transition-colors duration-200"
|
||||
on:click={toggleChangeCompanyModal}
|
||||
>
|
||||
Change company
|
||||
</button>
|
||||
<div class="sticky top-0 z-20">
|
||||
<CompanyBanner />
|
||||
<div
|
||||
class="header-container col-span-12 h-16 bg-pc-darkblue dark:bg-gray-800 border-b border-pc-darkblue/20 dark:border-highlight-blue/30 flex justify-between items-center"
|
||||
>
|
||||
<Logo />
|
||||
{#if isInstalled}
|
||||
<div class="hidden lg:flex flex-row items-center px-8 h-full justify-self-end">
|
||||
{#if isUpdateAvailable}
|
||||
<a
|
||||
class="flex items-center gap-2 mr-8 text-lg font-medium text-white bg-gradient-to-r from-indigo-500 to-purple-500 dark:from-active-blue dark:to-highlight-blue rounded-md px-4 py-2 transition-all duration-300 transform hover:-translate-y-0.5 focus:outline-none focus:ring-2 focus:ring-indigo-400 focus:ring-offset-2 dark:focus:ring-offset-gray-800 active:scale-95 fixed bottom-4 right-2 shadow-md shadow-black dark:shadow-gray-900"
|
||||
href={'/settings/update'}
|
||||
>
|
||||
<span class="">✨</span>
|
||||
<span>Update Available</span>
|
||||
</a>
|
||||
{/if}
|
||||
<div class="relative ml-10 flex items-center gap-4">
|
||||
<ThemeToggle />
|
||||
<button
|
||||
id="toggle-profile-menu"
|
||||
class="group flex items-center"
|
||||
on:click={() => (isProfileMenuVisible = !isProfileMenuVisible)}
|
||||
>
|
||||
<!-- main circle with initials -->
|
||||
<div
|
||||
class="w-10 h-10 rounded-full bg-cta-blue hover:bg-cta-blue/80 dark:bg-active-blue dark:hover:bg-active-blue/80 dark:border dark:border-highlight-blue/40 flex items-center justify-center text-white font-medium relative transition-colors duration-200"
|
||||
>
|
||||
{initials}
|
||||
|
||||
{#if isUpdateAvailable}
|
||||
<a
|
||||
class="flex items-center gap-2 mr-8 text-lg font-medium text-white bg-gradient-to-r from-indigo-500 to-purple-500 dark:from-indigo-600 dark:to-purple-600 rounded-md px-4 py-2 transition-all duration-300 transform hover:-translate-y-0.5 focus:outline-none focus:ring-2 focus:ring-indigo-400 focus:ring-offset-2 dark:focus:ring-offset-gray-800 active:scale-95 fixed bottom-4 right-2 shadow-md shadow-black dark:shadow-gray-900"
|
||||
href={'/settings/update'}
|
||||
<div class="absolute -bottom-1 -right-1 w-5 h-5"></div>
|
||||
</div>
|
||||
|
||||
<!-- dropdown indicator -->
|
||||
<svg
|
||||
class="w-4 h-4 ml-2 text-gray-300 dark:text-highlight-blue transition-transform duration-200 group-hover:text-white"
|
||||
fill="none"
|
||||
stroke="currentColor"
|
||||
viewBox="0 0 24 24"
|
||||
>
|
||||
<path
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
stroke-width="2"
|
||||
d="M19 9l-7 7-7-7"
|
||||
/>
|
||||
</svg>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="flex lg:hidden items-center mr-4 gap-4">
|
||||
<div
|
||||
class="flex items-center justify-center w-10 h-10 rounded-lg hover:bg-white/10 dark:hover:bg-white/10 transition-colors duration-200"
|
||||
>
|
||||
<span class="">✨</span>
|
||||
<span>Update Available</span>
|
||||
</a>
|
||||
{/if}
|
||||
<div class="relative ml-10 flex items-center gap-4">
|
||||
<ThemeToggle />
|
||||
<ThemeToggle />
|
||||
</div>
|
||||
|
||||
<button
|
||||
id="toggle-profile-menu"
|
||||
class="group flex items-center"
|
||||
on:click={() => (isProfileMenuVisible = !isProfileMenuVisible)}
|
||||
class="flex items-center justify-center w-10 h-10 rounded-lg hover:bg-white/10 dark:hover:bg-white/10 transition-colors duration-200"
|
||||
on:click={() => (isMobileMenuVisible = !isMobileMenuVisible)}
|
||||
>
|
||||
<!-- Main Circle with Initials -->
|
||||
<div
|
||||
class="w-10 h-10 rounded-full bg-cta-blue hover:bg-indigo-500 dark:bg-indigo-600 dark:hover:bg-indigo-700 flex items-center justify-center text-white font-medium relative transition-colors duration-200"
|
||||
>
|
||||
{initials}
|
||||
|
||||
<div class="absolute -bottom-1 -right-1 w-5 h-5"></div>
|
||||
</div>
|
||||
|
||||
<!-- Dropdown Indicator -->
|
||||
<svg
|
||||
class="w-4 h-4 ml-2 text-gray-300 dark:text-gray-400 transition-transform duration-200 group-hover:text-white"
|
||||
fill="none"
|
||||
stroke="currentColor"
|
||||
viewBox="0 0 24 24"
|
||||
>
|
||||
<path
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
stroke-width="2"
|
||||
d="M19 9l-7 7-7-7"
|
||||
/>
|
||||
</svg>
|
||||
<img class="w-6 h-6" src="/mob-menu-button.svg" alt="toggle mobile menu" />
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="flex lg:hidden items-center mr-4 gap-4">
|
||||
<div
|
||||
class="flex items-center justify-center w-10 h-10 rounded-lg hover:bg-white/10 transition-colors duration-200"
|
||||
>
|
||||
<ThemeToggle />
|
||||
</div>
|
||||
<button
|
||||
class="rounded-md px-3 py-2 text-white bg-indigo-500 hover:bg-cta-blue dark:bg-indigo-600 dark:hover:bg-indigo-700 uppercase font-semibold text-xs transition-colors duration-200"
|
||||
on:click={toggleChangeCompanyModal}
|
||||
>
|
||||
Change company
|
||||
</button>
|
||||
<button
|
||||
class="flex items-center justify-center w-10 h-10 rounded-lg hover:bg-white/10 transition-colors duration-200"
|
||||
on:click={() => (isMobileMenuVisible = !isMobileMenuVisible)}
|
||||
>
|
||||
<img class="w-6 h-6" src="/mob-menu-button.svg" alt="toggle mobile menu" />
|
||||
</button>
|
||||
</div>
|
||||
{/if}
|
||||
{/if}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<style>
|
||||
/* Prevent any hover effects on the header */
|
||||
/* prevent any hover effects on the header */
|
||||
.header-container {
|
||||
background-color: #0b2063 !important;
|
||||
}
|
||||
|
||||
@@ -6,8 +6,142 @@
|
||||
import ThemeToggle from '../ThemeToggle.svelte';
|
||||
|
||||
export let visible = false;
|
||||
export let username = '';
|
||||
export let onClickLogout;
|
||||
export let toggleChangeCompanyModal;
|
||||
|
||||
const icons = {
|
||||
dashboard: `<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" class="size-5">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" d="m2.25 12 8.954-8.955c.44-.439 1.152-.439 1.591 0L21.75 12M4.5 9.75v10.125c0 .621.504 1.125 1.125 1.125H9.75v-4.875c0-.621.504-1.125 1.125-1.125h2.25c.621 0 1.125.504 1.125 1.125V21h4.125c.621 0 1.125-.504 1.125-1.125V9.75M8.25 21h8.25" />
|
||||
</svg>`,
|
||||
|
||||
campaigns_overview: `<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" class="size-5">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" d="M8 5h6c2 0 4 2 4 4v4c0 3-3 5-5 5 1.5-1.5 1.5-3 1.5-3" />
|
||||
<path stroke-linecap="round" stroke-linejoin="round" d="M14.5 15l-2 2" />
|
||||
<circle cx="14" cy="5" r="1" fill="currentColor" />
|
||||
</svg>`,
|
||||
campaign_templates: `<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" class="size-5">
|
||||
<path stroke-linecap="round" stroke-linejoin="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.25m0 12.75h7.5m-7.5 3H12M10.5 2.25H5.625c-.621 0-1.125.504-1.125 1.125v17.25c0 .621.504 1.125 1.125 1.125h12.75c.621 0 1.125-.504 1.125-1.125V11.25a9 9 0 0 0-9-9Z" />
|
||||
</svg>`,
|
||||
|
||||
ip_filters: `<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" class="size-5">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" d="M12 3c2.755 0 5.455.232 8.083.678.533.09.917.556.917 1.096v1.044a2.25 2.25 0 0 1-.659 1.591l-5.432 5.432a2.25 2.25 0 0 0-.659 1.591v2.927a2.25 2.25 0 0 1-1.244 2.013L9.75 21v-6.568a2.25 2.25 0 0 0-.659-1.591L3.659 7.409A2.25 2.25 0 0 1 3 5.818V4.774c0-.54.384-1.006.917-1.096A48.32 48.32 0 0 1 12 3Z" />
|
||||
</svg>`,
|
||||
|
||||
webhooks: `<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" class="size-5">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" d="m3.75 13.5 10.5-11.25L12 10.5h8.25L9.75 21.75 12 13.5H3.75Z" />
|
||||
</svg>`,
|
||||
|
||||
recipients_overview: `<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" class="size-5">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" d="M15.75 6a3.75 3.75 0 1 1-7.5 0 3.75 3.75 0 0 1 7.5 0ZM4.501 20.118a7.5 7.5 0 0 1 14.998 0A17.933 17.933 0 0 1 12 21.75c-2.676 0-5.216-.584-7.499-1.632Z" />
|
||||
</svg>`,
|
||||
|
||||
recipient_groups: `<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" class="size-5">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" d="M18 18.72a9.094 9.094 0 0 0 3.741-.479 3 3 0 0 0-4.682-2.72m.94 3.198.001.031c0 .225-.012.447-.037.666A11.944 11.944 0 0 1 12 21c-2.17 0-4.207-.576-5.963-1.584A6.062 6.062 0 0 1 6 18.719m12 0a5.971 5.971 0 0 0-.941-3.197m0 0A5.995 5.995 0 0 0 12 12.75a5.995 5.995 0 0 0-5.058 2.772m0 0a3 3 0 0 0-4.681 2.72 8.986 8.986 0 0 0 3.74.477m.94-3.197a5.971 5.971 0 0 0-.94 3.197M15 6.75a3 3 0 1 1-6 0 3 3 0 0 1 6 0Zm6 3a2.25 2.25 0 1 1-4.5 0 2.25 2.25 0 0 1 4.5 0Zm-13.5 0a2.25 2.25 0 1 1-4.5 0 2.25 2.25 0 0 1 4.5 0Z" />
|
||||
</svg>`,
|
||||
|
||||
domains_overview: `<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" class="size-5">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" d="M12 21a9.004 9.004 0 0 0 8.716-6.747M12 21a9.004 9.004 0 0 1-8.716-6.747M12 21c2.485 0 4.5-4.03 4.5-9S14.485 3 12 3m0 18c-2.485 0-4.5-4.03-4.5-9S9.515 3 12 3m0 0a8.997 8.997 0 0 1 7.843 4.582M12 3a8.997 8.997 0 0 0-7.843 4.582m15.686 0A11.953 11.953 0 0 1 12 10.5c-2.998 0-5.74-1.1-7.843-2.918m15.686 0A8.959 8.959 0 0 1 21 12c0 .778-.099 1.533-.284 2.253m0 0A17.919 17.919 0 0 1 12 16.5c-3.162 0-6.133-.815-8.716-2.247m0 0A9.015 9.015 0 0 1 3 12c0-1.605.42-3.113 1.157-4.418" />
|
||||
</svg>`,
|
||||
|
||||
pages: `<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" class="size-5">
|
||||
<path stroke-linecap="round" stroke-linejoin="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.25m2.25 0H5.625c-.621 0-1.125.504-1.125 1.125v17.25c0 .621.504 1.125 1.125 1.125h12.75c.621 0 1.125-.504 1.125-1.125V11.25a9 9 0 0 0-9-9Z" />
|
||||
</svg>`,
|
||||
|
||||
assets: `<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" class="size-5">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" d="m2.25 15.75 5.159-5.159a2.25 2.25 0 0 1 3.182 0l5.159 5.159m-1.5-1.5 1.409-1.409a2.25 2.25 0 0 1 3.182 0l2.909 2.909m-18 3.75h16.5a1.5 1.5 0 0 0 1.5-1.5V6a1.5 1.5 0 0 0-1.5-1.5H3.75A1.5 1.5 0 0 0 2.25 6v12a1.5 1.5 0 0 0 1.5 1.5Zm10.5-11.25h.008v.008h-.008V8.25Zm.375 0a.375.375 0 1 1-.75 0 .375.375 0 0 1 .75 0Z" />
|
||||
</svg>`,
|
||||
|
||||
emails_overview: `<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" class="size-5">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" d="M21.75 6.75v10.5a2.25 2.25 0 0 1-2.25 2.25h-15a2.25 2.25 0 0 1-2.25-2.25V6.75m19.5 0A2.25 2.25 0 0 0 19.5 4.5h-15a2.25 2.25 0 0 0-2.25 2.25m19.5 0v.243a2.25 2.25 0 0 1-1.07 1.916l-7.5 4.615a2.25 2.25 0 0 1-2.36 0L3.32 8.91a2.25 2.25 0 0 1-1.07-1.916V6.75" />
|
||||
</svg>`,
|
||||
|
||||
attachments: `<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" class="size-5">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" d="m18.375 12.739-7.693 7.693a4.5 4.5 0 0 1-6.364-6.364l10.94-10.94A3 3 0 1 1 19.5 7.372L8.552 18.32m.009-.01-.01.01m5.699-9.941-7.81 7.81a1.5 1.5 0 0 0 2.112 2.13" />
|
||||
</svg>`,
|
||||
|
||||
smtp_configurations: `<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" class="size-5">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" d="M16.5 12a4.5 4.5 0 1 1-9 0 4.5 4.5 0 0 1 9 0Zm0 0c0 1.657 1.007 3 2.25 3S21 13.657 21 12a9 9 0 1 0-2.636 6.364M16.5 12V8.25" />
|
||||
</svg>`,
|
||||
|
||||
api_senders: `<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" class="size-5">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" d="M6 12 3.269 3.125A59.769 59.769 0 0 1 21.485 12 59.768 59.768 0 0 1 3.27 20.875L5.999 12Zm0 0h7.5" />
|
||||
</svg>`,
|
||||
|
||||
proxy: `<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" class="size-5">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" d="M7.5 21 3 16.5m0 0L7.5 12M3 16.5h13.5m0-13.5L21 7.5m0 0L16.5 12M21 7.5H7.5" />
|
||||
</svg>`,
|
||||
|
||||
// Top menu icons
|
||||
profile: `<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" class="size-5">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" d="M15.75 6a3.75 3.75 0 1 1-7.5 0 3.75 3.75 0 0 1 7.5 0ZM4.501 20.118a7.5 7.5 0 0 1 14.998 0A17.933 17.933 0 0 1 12 21.75c-2.676 0-5.216-.584-7.499-1.632Z" />
|
||||
</svg>`,
|
||||
|
||||
sessions: `<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" class="size-5">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" d="M9 12.75 11.25 15 15 9.75M21 12a9 9 0 1 1-18 0 9 9 0 0 1 18 0Z" />
|
||||
</svg>`,
|
||||
|
||||
users: `<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" class="size-5">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" d="M18 18.72a9.094 9.094 0 0 0 3.741-.479 3 3 0 0 0-4.682-2.72m.94 3.198.001.031c0 .225-.012.447-.037.666A11.944 11.944 0 0 1 12 21c-2.17 0-4.207-.576-5.963-1.584A6.062 6.062 0 0 1 6 18.719m12 0a5.971 5.971 0 0 0-.941-3.197m0 0A5.995 5.995 0 0 0 12 12.75a5.995 5.995 0 0 0-5.058 2.772m0 0a3 3 0 0 0-4.681 2.72 8.986 8.986 0 0 0 3.74.477m.94-3.197a5.971 5.971 0 0 0-.94 3.197M15 6.75a3 3 0 1 1-6 0 3 3 0 0 1 6 0Zm6 3a2.25 2.25 0 1 1-4.5 0 2.25 2.25 0 0 1 4.5 0Zm-13.5 0a2.25 2.25 0 1 1-4.5 0 2.25 2.25 0 0 1 4.5 0Z" />
|
||||
</svg>`,
|
||||
|
||||
companies: `<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" class="size-5">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" d="m2.25 12 8.954-8.955c.44-.439 1.152-.439 1.591 0L21.75 12M4.5 9.75v10.125c0 .621.504 1.125 1.125 1.125H9.75v-4.875c0-.621.504-1.125 1.125-1.125h2.25c.621 0 1.125.504 1.125 1.125V21h4.125c.621 0 1.125-.504 1.125-1.125V9.75M8.25 21h8.25" />
|
||||
</svg>`,
|
||||
|
||||
settings: `<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" class="size-5">
|
||||
<path stroke-linecap="round" stroke-linejoin="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.992a6.759 6.759 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.57 6.57 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" />
|
||||
<path stroke-linecap="round" stroke-linejoin="round" d="M15 12a3 3 0 1 1-6 0 3 3 0 0 1 6 0Z" />
|
||||
</svg>`,
|
||||
|
||||
'user guide': `<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" class="size-4">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" d="M9.879 7.519c1.171-1.025 3.071-1.025 4.242 0 1.172 1.025 1.172 2.687 0 3.712-.203.179-.43.326-.67.442-.745.361-1.45.999-1.45 1.827v.75M21 12a9 9 0 1 1-18 0 9 9 0 0 1 18 0Zm-9 5.25h.008v.008H12v-.008Z" />
|
||||
</svg>`,
|
||||
|
||||
'change company': `<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" class="size-4">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" d="M13.5 4.5 21 12m0 0-7.5 7.5M21 12H3" />
|
||||
</svg>`
|
||||
};
|
||||
|
||||
const getIconForRoute = (route) => {
|
||||
const iconMap = {
|
||||
'/dashboard/': 'dashboard',
|
||||
'/campaign/': 'campaigns_overview',
|
||||
'/campaign-template/': 'campaign_templates',
|
||||
'/ip-filter/': 'ip_filters',
|
||||
'/webhook/': 'webhooks',
|
||||
'/recipient/': 'recipients_overview',
|
||||
'/recipient/group/': 'recipient_groups',
|
||||
'/domain/': 'domains_overview',
|
||||
'/page/': 'pages',
|
||||
'/proxy/': 'proxy',
|
||||
'/asset/': 'assets',
|
||||
'/email/': 'emails_overview',
|
||||
'/attachment/': 'attachments',
|
||||
'/smtp-configuration/': 'smtp_configurations',
|
||||
'/api-sender/': 'api_senders',
|
||||
'/profile/': 'profile',
|
||||
'/sessions/': 'sessions',
|
||||
'/user/': 'users',
|
||||
'/company/': 'companies',
|
||||
'/settings/': 'settings'
|
||||
};
|
||||
|
||||
return icons[iconMap[route] || 'dashboard'];
|
||||
};
|
||||
|
||||
const getTopMenuIcon = (label) => {
|
||||
const iconMap = {
|
||||
Profile: 'profile',
|
||||
Sessions: 'sessions',
|
||||
Users: 'users',
|
||||
Companies: 'companies',
|
||||
Settings: 'settings',
|
||||
'User Guide': 'user guide',
|
||||
'Change Company': 'change company'
|
||||
};
|
||||
|
||||
return icons[iconMap[label] || 'profile'];
|
||||
};
|
||||
</script>
|
||||
|
||||
{#if visible}
|
||||
@@ -20,21 +154,21 @@
|
||||
|
||||
<!-- Mobile Menu -->
|
||||
<div
|
||||
class="mobile-menu-content fixed top-0 left-0 w-full h-full bg-pc-darkblue dark:bg-gray-900 z-50 overflow-y-auto shadow-xl transition-colors duration-200"
|
||||
class="mobile-menu-content fixed top-0 left-0 w-full h-full bg-gradient-to-b from-pc-darkblue to-slate-900 dark:from-gray-900 dark:to-gray-950 z-50 overflow-y-auto shadow-xl"
|
||||
>
|
||||
<!-- Header -->
|
||||
<div
|
||||
class="mobile-menu-header flex justify-between h-20 items-center bg-pc-darkblue dark:bg-gray-800 px-6"
|
||||
class="mobile-menu-header flex justify-between h-20 items-center bg-pc-darkblue/90 dark:bg-gray-900/90 backdrop-blur-sm px-6 border-b border-white/10 dark:border-gray-700/50"
|
||||
>
|
||||
<img class="w-40 h-auto" src="/logo-white.svg" alt="logo" />
|
||||
<div class="flex items-center gap-4">
|
||||
<div class="flex items-center gap-2">
|
||||
<div
|
||||
class="flex items-center justify-center w-12 h-12 rounded-lg hover:bg-white/10 dark:hover:bg-gray-600/30 transition-colors duration-200"
|
||||
class="flex items-center justify-center w-12 h-12 rounded-lg hover:bg-white/10 dark:hover:bg-gray-600/30 transition-all duration-200"
|
||||
>
|
||||
<ThemeToggle />
|
||||
</div>
|
||||
<button
|
||||
class="flex items-center justify-center w-12 h-12 rounded-lg hover:bg-white/10 dark:hover:bg-gray-600/30 transition-colors duration-200"
|
||||
class="flex items-center justify-center w-12 h-12 rounded-lg hover:bg-white/10 dark:hover:bg-gray-600/30 transition-all duration-200"
|
||||
on:click={() => (visible = false)}
|
||||
>
|
||||
<img class="w-6 h-6" src="/mob-menu-close.svg" alt="close mobile menu" />
|
||||
@@ -42,110 +176,153 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- User Section -->
|
||||
<div class="p-6 border-b border-white dark:border-gray-700">
|
||||
<h1 class="font-bold text-xl text-white dark:text-gray-100 mb-4">
|
||||
{username ?? ''}
|
||||
</h1>
|
||||
<!-- Switch Company Section -->
|
||||
<div class="px-6 py-4 border-b border-white/20 dark:border-highlight-blue/30">
|
||||
<button
|
||||
on:click={onClickLogout}
|
||||
class="bg-cta-blue dark:bg-indigo-600 dark:hover:bg-indigo-700 uppercase font-bold py-3 px-6 rounded-md transition-colors duration-200 text-sm text-white"
|
||||
class="flex items-center w-full py-3 px-4 text-white bg-active-blue dark:bg-highlight-blue/30 rounded-lg transition-all duration-200 hover:bg-active-blue/80 dark:hover:bg-highlight-blue/40 font-medium"
|
||||
on:click={() => {
|
||||
visible = false;
|
||||
toggleChangeCompanyModal();
|
||||
}}
|
||||
>
|
||||
Log Out
|
||||
<div class="flex-shrink-0 mr-3 text-white dark:text-highlight-blue">
|
||||
{@html getTopMenuIcon('Change Company')}
|
||||
</div>
|
||||
<span class="flex-1 text-left">Switch Company</span>
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<!-- Top Menu -->
|
||||
<div class="p-4">
|
||||
<div
|
||||
class="bg-gradient-to-b from-cta-blue to-indigo-500 dark:from-gray-800 dark:to-gray-700 rounded-md"
|
||||
<!-- Quick Actions Section -->
|
||||
<div class="p-6 border-b border-white/20 dark:border-highlight-blue/30">
|
||||
<h2
|
||||
class="text-white/80 dark:text-highlight-blue text-lg font-semibold uppercase tracking-wider mb-4 text-left"
|
||||
>
|
||||
Quick Access
|
||||
</h2>
|
||||
<div class="space-y-2">
|
||||
{#each mobileTopMenu as link}
|
||||
<a
|
||||
class="block text-center py-4 text-white text-lg font-medium first:rounded-t-md last:rounded-b-md transition-colors duration-200"
|
||||
class:bg-active-blue={$page.url.pathname === link.route}
|
||||
class:dark:bg-gray-700={$page.url.pathname === link.route}
|
||||
class:shadow-md={$page.url.pathname === link.route}
|
||||
class="flex items-center w-full py-3 px-4 text-white text-lg font-medium rounded-lg transition-all duration-200 group {$page
|
||||
.url.pathname === link.route
|
||||
? 'bg-active-blue shadow-lg dark:bg-active-blue'
|
||||
: 'hover:bg-highlight-blue/30 hover:shadow-md dark:hover:bg-highlight-blue/20'}"
|
||||
class:hidden={shouldHideMenuItem(link.route)}
|
||||
on:click={() => (visible = false)}
|
||||
target={link.external ? '_blank' : '_self'}
|
||||
href={link.route}
|
||||
>
|
||||
{link.label}
|
||||
<div class="flex-shrink-0 mr-3 text-white dark:text-highlight-blue">
|
||||
{@html getTopMenuIcon(link.label)}
|
||||
</div>
|
||||
<span class="flex-1 text-left">{link.label}</span>
|
||||
{#if $page.url.pathname === link.route}
|
||||
<div class="w-2 h-2 bg-white rounded-full"></div>
|
||||
{/if}
|
||||
</a>
|
||||
{/each}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Main Menu -->
|
||||
<div class="p-4 pt-0">
|
||||
<div
|
||||
class="bg-gradient-to-b from-cta-blue to-indigo-500 dark:from-gray-800 dark:to-gray-700 rounded-md"
|
||||
<!-- Main Navigation -->
|
||||
<div class="p-6">
|
||||
<h2
|
||||
class="text-white/80 dark:text-highlight-blue text-lg font-semibold uppercase tracking-wider mb-4 text-left"
|
||||
>
|
||||
Navigation
|
||||
</h2>
|
||||
<div class="space-y-1">
|
||||
{#each menu as link}
|
||||
{#if link.type === 'submenu'}
|
||||
<div
|
||||
class="text-center py-4 text-white font-semibold text-lg border-b border-white/20 dark:border-gray-600"
|
||||
>
|
||||
{link.label}
|
||||
<!-- section header -->
|
||||
<div class="pt-4 pb-2 first:pt-0">
|
||||
<div class="py-2 px-4 border-l-2 border-cta-blue/60 dark:border-highlight-blue/60">
|
||||
<h3
|
||||
class="text-white dark:text-highlight-blue font-bold text-lg uppercase tracking-wide text-left"
|
||||
>
|
||||
{link.label}
|
||||
</h3>
|
||||
</div>
|
||||
</div>
|
||||
{#each link.items as item, i (i)}
|
||||
<!-- submenu items -->
|
||||
<div class="ml-4 space-y-1">
|
||||
{#each link.items as item, i (i)}
|
||||
<a
|
||||
class="flex items-center w-full py-2.5 px-4 text-white/90 dark:text-gray-300 text-base font-medium rounded-lg transition-all duration-200 group hover:bg-highlight-blue/30 dark:hover:bg-highlight-blue/20 hover:text-white dark:hover:text-white"
|
||||
href={item.route}
|
||||
on:click={() => (visible = false)}
|
||||
>
|
||||
<div
|
||||
class="flex-shrink-0 mr-3 text-white/70 dark:text-highlight-blue/80 group-hover:text-white"
|
||||
>
|
||||
{@html getIconForRoute(item.route)}
|
||||
</div>
|
||||
<span class="text-left">
|
||||
{#if i === 0}
|
||||
Overview
|
||||
{:else if item.singleLabel}
|
||||
{item.singleLabel}
|
||||
{:else}
|
||||
{item.label}
|
||||
{/if}
|
||||
</span>
|
||||
</a>
|
||||
{/each}
|
||||
</div>
|
||||
{:else}
|
||||
<!-- standalone menu item -->
|
||||
<div class="pt-4 pb-2 first:pt-0">
|
||||
<a
|
||||
class="block text-center py-3 text-white text-base transition-colors duration-200"
|
||||
class:last:rounded-b-md={i === link.items.length - 1}
|
||||
href={item.route}
|
||||
class="flex items-center w-full py-3 px-4 text-white text-lg font-bold rounded-lg transition-all duration-200 group hover:bg-highlight-blue/30 dark:hover:bg-highlight-blue/20"
|
||||
href={link.route}
|
||||
on:click={() => (visible = false)}
|
||||
>
|
||||
{#if i === 0}
|
||||
Overview
|
||||
{:else if item.singleLabel}
|
||||
{item.singleLabel}
|
||||
{:else}
|
||||
{item.label}
|
||||
{/if}
|
||||
<div class="flex-shrink-0 mr-3 text-white dark:text-highlight-blue">
|
||||
{@html getIconForRoute(link.route)}
|
||||
</div>
|
||||
<span class="text-left">{link.label}</span>
|
||||
</a>
|
||||
{/each}
|
||||
{:else}
|
||||
<a
|
||||
class="block text-center py-4 text-white text-lg font-medium transition-colors duration-200"
|
||||
href={link.route}
|
||||
on:click={() => (visible = false)}
|
||||
>
|
||||
{link.label}
|
||||
</a>
|
||||
</div>
|
||||
{/if}
|
||||
{/each}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Logout Section -->
|
||||
<div class="p-6 border-t border-white/20 dark:border-highlight-blue/30 mt-auto">
|
||||
<button
|
||||
on:click={onClickLogout}
|
||||
class="w-full border-2 border-white/30 dark:border-highlight-blue/50 hover:border-highlight-blue/60 dark:hover:border-highlight-blue hover:bg-highlight-blue/20 dark:hover:bg-highlight-blue/20 uppercase font-medium py-2.5 px-6 rounded-lg transition-all duration-200 text-sm text-white/90 dark:text-highlight-blue hover:text-white dark:hover:text-white"
|
||||
>
|
||||
Log Out
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<!-- Footer spacer -->
|
||||
<div class="h-6"></div>
|
||||
</div>
|
||||
{/if}
|
||||
|
||||
<style>
|
||||
/* Prevent any hover effects on the mobile menu header */
|
||||
:global(.mobile-menu-header) {
|
||||
background-color: #0b2063 !important;
|
||||
}
|
||||
:global(.mobile-menu-header:hover) {
|
||||
background-color: #0b2063 !important;
|
||||
}
|
||||
:global(.dark .mobile-menu-header) {
|
||||
background-color: #1f2937 !important;
|
||||
}
|
||||
:global(.dark .mobile-menu-header:hover) {
|
||||
background-color: #1f2937 !important;
|
||||
/* ensure consistent background colors */
|
||||
.mobile-menu-content {
|
||||
background: linear-gradient(to bottom, #0b2063, #1e293b);
|
||||
}
|
||||
|
||||
/* Prevent any hover effects on the mobile menu content */
|
||||
.mobile-menu-content {
|
||||
background-color: #0b2063 !important;
|
||||
}
|
||||
.mobile-menu-content:hover {
|
||||
background-color: #0b2063 !important;
|
||||
}
|
||||
:global(.dark) .mobile-menu-content {
|
||||
background-color: #111827 !important;
|
||||
background: linear-gradient(to bottom, #111827, #0f172a);
|
||||
}
|
||||
:global(.dark) .mobile-menu-content:hover {
|
||||
background-color: #111827 !important;
|
||||
|
||||
/* smooth scrolling */
|
||||
.mobile-menu-content {
|
||||
scroll-behavior: smooth;
|
||||
}
|
||||
|
||||
/* hide scrollbar but keep functionality */
|
||||
.mobile-menu-content::-webkit-scrollbar {
|
||||
display: none;
|
||||
}
|
||||
.mobile-menu-content {
|
||||
-ms-overflow-style: none;
|
||||
scrollbar-width: none;
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -5,6 +5,52 @@
|
||||
import { shouldHideMenuItem } from '$lib/utils/common';
|
||||
export let logout;
|
||||
export let visible = false;
|
||||
export let toggleChangeCompanyModal;
|
||||
|
||||
const icons = {
|
||||
profile: `<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" class="size-4">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" d="M15.75 6a3.75 3.75 0 1 1-7.5 0 3.75 3.75 0 0 1 7.5 0ZM4.501 20.118a7.5 7.5 0 0 1 14.998 0A17.933 17.933 0 0 1 12 21.75c-2.676 0-5.216-.584-7.499-1.632Z" />
|
||||
</svg>`,
|
||||
|
||||
sessions: `<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" class="size-4">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" d="M9 12.75 11.25 15 15 9.75M21 12a9 9 0 1 1-18 0 9 9 0 0 1 18 0Z" />
|
||||
</svg>`,
|
||||
|
||||
users: `<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" class="size-4">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" d="M18 18.72a9.094 9.094 0 0 0 3.741-.479 3 3 0 0 0-4.682-2.72m.94 3.198.001.031c0 .225-.012.447-.037.666A11.944 11.944 0 0 1 12 21c-2.17 0-4.207-.576-5.963-1.584A6.062 6.062 0 0 1 6 18.719m12 0a5.971 5.971 0 0 0-.941-3.197m0 0A5.995 5.995 0 0 0 12 12.75a5.995 5.995 0 0 0-5.058 2.772m0 0a3 3 0 0 0-4.681 2.72 8.986 8.986 0 0 0 3.74.477m.94-3.197a5.971 5.971 0 0 0-.94 3.197M15 6.75a3 3 0 1 1-6 0 3 3 0 0 1 6 0Zm6 3a2.25 2.25 0 1 1-4.5 0 2.25 2.25 0 0 1 4.5 0Zm-13.5 0a2.25 2.25 0 1 1-4.5 0 2.25 2.25 0 0 1 4.5 0Z" />
|
||||
</svg>`,
|
||||
|
||||
companies: `<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" class="size-4">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" d="m2.25 12 8.954-8.955c.44-.439 1.152-.439 1.591 0L21.75 12M4.5 9.75v10.125c0 .621.504 1.125 1.125 1.125H9.75v-4.875c0-.621.504-1.125 1.125-1.125h2.25c.621 0 1.125.504 1.125 1.125V21h4.125c.621 0 1.125-.504 1.125-1.125V9.75M8.25 21h8.25" />
|
||||
</svg>`,
|
||||
|
||||
settings: `<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" class="size-4">
|
||||
<path stroke-linecap="round" stroke-linejoin="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.992a6.759 6.759 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.57 6.57 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" />
|
||||
<path stroke-linecap="round" stroke-linejoin="round" d="M15 12a3 3 0 1 1-6 0 3 3 0 0 1 6 0Z" />
|
||||
</svg>`,
|
||||
|
||||
'user guide': `<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" class="size-4">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" d="M9.879 7.519c1.171-1.025 3.071-1.025 4.242 0 1.172 1.025 1.172 2.687 0 3.712-.203.179-.43.326-.67.442-.745.361-1.45.999-1.45 1.827v.75M21 12a9 9 0 1 1-18 0 9 9 0 0 1 18 0Zm-9 5.25h.008v.008H12v-.008Z" />
|
||||
</svg>`,
|
||||
|
||||
'change company': `<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" class="size-4">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" d="M13.5 4.5 21 12m0 0-7.5 7.5M21 12H3" />
|
||||
</svg>`
|
||||
};
|
||||
|
||||
const getTopMenuIcon = (label) => {
|
||||
const iconMap = {
|
||||
Profile: 'profile',
|
||||
Sessions: 'sessions',
|
||||
Users: 'users',
|
||||
Companies: 'companies',
|
||||
Settings: 'settings',
|
||||
'User Guide': 'user guide',
|
||||
'Change Company': 'change company'
|
||||
};
|
||||
|
||||
return icons[iconMap[label] || 'profile'];
|
||||
};
|
||||
|
||||
const handleClickOutsideNavigation = (event) => {
|
||||
const profileMenuElement = document.getElementById('profile-menu');
|
||||
@@ -42,32 +88,48 @@
|
||||
class="lg:flex flex-col h-fit lg:col-start-10 lg:col-span-3 row-start-1 xl:col-start-11 xl:col-span-2 2xl:col-start-11 2xl:col-span-2 sticky top-20 z-30"
|
||||
>
|
||||
<div
|
||||
class="flex flex-col bg-gradient-to-b from-cta-blue to-indigo-500 dark:from-gray-800 dark:to-gray-700 rounded-md transition-colors duration-200"
|
||||
class="flex flex-col bg-gradient-to-b from-cta-blue to-indigo-500 dark:from-gray-800 dark:to-gray-700 rounded-md transition-colors duration-200 dark:border dark:border-highlight-blue/30"
|
||||
in:fadeIn={{ duration: 150 }}
|
||||
>
|
||||
<!-- Change Company at top with distinct styling -->
|
||||
<button
|
||||
class="flex items-center pl-5 py-3 text-white bg-active-blue dark:bg-highlight-blue/30 first:rounded-t-md transition-colors duration-200 hover:bg-active-blue/80 dark:hover:bg-highlight-blue/40 border-b border-active-blue/50 dark:border-highlight-blue/40"
|
||||
on:click={() => {
|
||||
visible = false;
|
||||
toggleChangeCompanyModal();
|
||||
}}
|
||||
>
|
||||
<div class="flex-shrink-0 mr-3 text-white dark:text-highlight-blue">
|
||||
{@html getTopMenuIcon('Change Company')}
|
||||
</div>
|
||||
<span class="font-medium">Switch Company</span>
|
||||
</button>
|
||||
|
||||
{#each topMenu as item}
|
||||
<a
|
||||
class="pl-5 py-2 text-white last:rounded-md first:rounded-t-md transition-colors duration-200"
|
||||
class:hover:shadow-md={$page.url.pathname !== item.route}
|
||||
class:hover:bg-highlight-blue={$page.url.pathname !== item.route}
|
||||
class:dark:hover:bg-gray-600={$page.url.pathname !== item.route}
|
||||
class:bg-active-blue={$page.url.pathname === item.route}
|
||||
class:dark:bg-gray-700={$page.url.pathname === item.route}
|
||||
class:shadow-md={$page.url.pathname === item.route}
|
||||
class="flex items-center pl-5 py-2 text-white last:rounded-md first:rounded-t-md transition-colors duration-200 {$page
|
||||
.url.pathname === item.route
|
||||
? 'bg-active-blue shadow-md dark:bg-active-blue'
|
||||
: 'hover:shadow-md hover:bg-highlight-blue/80 dark:hover:bg-highlight-blue/20'}"
|
||||
class:hidden={shouldHideMenuItem(item.route)}
|
||||
target={item.external ? '_blank' : '_self'}
|
||||
draggable="false"
|
||||
on:click={() => {
|
||||
visible = false;
|
||||
}}
|
||||
href={item.route}>{item.label}</a
|
||||
href={item.route}
|
||||
>
|
||||
<div class="flex-shrink-0 mr-3 text-white dark:text-highlight-blue">
|
||||
{@html getTopMenuIcon(item.label)}
|
||||
</div>
|
||||
<span>{item.label}</span>
|
||||
</a>
|
||||
{/each}
|
||||
<button
|
||||
on:click={logout}
|
||||
class="bg-white dark:bg-gray-800 uppercase font-bold hover:bg-pc-lightblue dark:hover:bg-gray-700 py-2 mx-4 my-4 rounded-md transition-colors duration-200"
|
||||
class="bg-white dark:bg-gray-800 dark:border dark:border-highlight-blue/40 uppercase font-bold hover:bg-cta-blue/10 dark:hover:bg-highlight-blue/20 py-2 mx-4 my-4 rounded-md transition-colors duration-200"
|
||||
>
|
||||
<p class="text-cta-blue dark:text-gray-100 py px-8 transition-colors duration-200">
|
||||
<p class="text-cta-blue dark:text-highlight-blue py px-8 transition-colors duration-200">
|
||||
Log Out
|
||||
</p>
|
||||
</button>
|
||||
|
||||
@@ -117,21 +117,21 @@
|
||||
<div class="flex-grow p-6">
|
||||
{#if isLoadingCompanies}
|
||||
<div class="flex items-center justify-center py-8">
|
||||
<div class="text-gray-500 dark:text-gray-400 transition-colors duration-200">
|
||||
<div class="text-gray-500 dark:text-gray-500 transition-colors duration-200">
|
||||
Loading companies...
|
||||
</div>
|
||||
</div>
|
||||
{:else if companies.length === 0}
|
||||
<div class="flex flex-col items-center justify-center py-8 text-center">
|
||||
<div class="text-gray-500 dark:text-gray-400 mb-4 transition-colors duration-200">
|
||||
<div class="text-gray-500 dark:text-gray-500 mb-4 transition-colors duration-200">
|
||||
No companies found.
|
||||
</div>
|
||||
<div class="text-sm text-gray-400 dark:text-gray-500 mb-4 transition-colors duration-200">
|
||||
<div class="text-sm text-gray-400 dark:text-gray-600 mb-4 transition-colors duration-200">
|
||||
You need to create a company first before you can switch to it.
|
||||
</div>
|
||||
<a
|
||||
href="/company/"
|
||||
class="bg-cta-blue dark:bg-blue-600 hover:bg-blue-700 dark:hover:bg-blue-700 text-sm uppercase font-bold px-4 py-2 text-white rounded-md transition-colors duration-200"
|
||||
class="bg-cta-blue dark:bg-highlight-blue/80 hover:bg-blue-700 dark:hover:bg-highlight-blue hover:text-white text-sm uppercase font-bold px-4 py-2 text-white rounded-md transition-colors duration-200"
|
||||
on:click={() => {
|
||||
visible = false;
|
||||
}}
|
||||
@@ -148,12 +148,12 @@
|
||||
|
||||
<!-- Button Section -->
|
||||
<div
|
||||
class="border-t border-gray-200 dark:border-gray-600 p-6 mt-36 flex flex-wrap gap-4 justify-end transition-colors duration-200"
|
||||
class="border-t border-gray-200 dark:border-gray-700/60 p-6 mt-36 flex flex-wrap gap-4 justify-end transition-colors duration-200"
|
||||
>
|
||||
{#if inContext}
|
||||
<button
|
||||
type="button"
|
||||
class="bg-slate-400 dark:bg-gray-600 hover:bg-slate-300 dark:hover:bg-gray-500 text-sm mr-2 uppercase font-bold px-4 py-2 text-white rounded-md disabled:opacity-50 disabled:cursor-not-allowed transition-colors duration-200"
|
||||
class="bg-slate-400 dark:bg-gray-700/80 hover:bg-slate-300 dark:hover:bg-gray-600/80 text-sm mr-2 uppercase font-bold px-4 py-2 text-white rounded-md disabled:opacity-50 disabled:cursor-not-allowed transition-colors duration-200"
|
||||
disabled={isLoadingCompanies}
|
||||
on:click={onClickSwitchToAdministratorContext}
|
||||
>
|
||||
@@ -163,7 +163,7 @@
|
||||
|
||||
<button
|
||||
type="submit"
|
||||
class="bg-cta-blue dark:bg-blue-600 hover:bg-blue-700 dark:hover:bg-blue-700 text-sm uppercase font-bold px-4 py-2 text-white rounded-md disabled:opacity-50 disabled:cursor-not-allowed transition-colors duration-200"
|
||||
class="bg-cta-blue dark:bg-highlight-blue/80 hover:bg-blue-700 dark:hover:bg-highlight-blue hover:text-white text-sm uppercase font-bold px-4 py-2 text-white rounded-md disabled:opacity-50 disabled:cursor-not-allowed transition-colors duration-200"
|
||||
disabled={isLoadingCompanies || !selectedCompany}
|
||||
on:click={onClickSwitch}
|
||||
>
|
||||
|
||||
@@ -46,20 +46,20 @@
|
||||
<!--
|
||||
<h3 class="text-lg font-medium text-gray-900">Delete {type}</h3>
|
||||
-->
|
||||
<p class="mt-2 text-gray-600 dark:text-gray-300">
|
||||
<p class="mt-2 text-gray-600 dark:text-gray-400">
|
||||
Are you sure you want to delete
|
||||
{#if name?.length > 30}
|
||||
<br />
|
||||
{/if}
|
||||
<span class="font-medium text-gray-900 dark:text-gray-100">"{name}"</span>?
|
||||
<span class="font-medium text-gray-900 dark:text-gray-300">"{name}"</span>?
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<!-- Impact Section -->
|
||||
{#if list.length}
|
||||
<div class="bg-gray-50 dark:bg-gray-700 rounded-lg p-4 transition-colors duration-200">
|
||||
<p class="font-medium text-gray-900 dark:text-gray-100 mb-3">Side effects:</p>
|
||||
<ul class="space-y-2 ml-4 list-disc text-gray-600 dark:text-gray-300">
|
||||
<div class="bg-gray-50 dark:bg-gray-800/40 rounded-lg p-4 transition-colors duration-200">
|
||||
<p class="font-medium text-gray-900 dark:text-gray-300 mb-3">Side effects:</p>
|
||||
<ul class="space-y-2 ml-4 list-disc text-gray-600 dark:text-gray-400">
|
||||
{#each list as line}
|
||||
<li>{line}</li>
|
||||
{/each}
|
||||
@@ -85,7 +85,7 @@
|
||||
{/if}
|
||||
|
||||
{#if permanent}
|
||||
<p class="text-red-700 dark:text-red-400 font-medium">This action cannot be undone.</p>
|
||||
<p class="text-red-700 dark:text-red-300 font-medium">This action cannot be undone.</p>
|
||||
{/if}
|
||||
</div>
|
||||
</Alert>
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
</script>
|
||||
|
||||
<button
|
||||
class="hover:bg-gray-100 dark:hover:bg-gray-700 px-2 py-1 rounded-md transition-colors w-full text-left text-ellipsis overflow-hidden text-gray-900 dark:text-gray-100"
|
||||
class="hover:bg-gray-100 dark:hover:bg-gray-800/40 px-2 py-1 rounded-md transition-colors w-full text-left text-ellipsis overflow-hidden text-gray-900 dark:text-gray-200"
|
||||
title={text}
|
||||
on:click={() => onClickCopy(text)}
|
||||
>
|
||||
|
||||
@@ -5,14 +5,14 @@
|
||||
export let colspan = 100;
|
||||
</script>
|
||||
|
||||
<tr class="text-center bg-pleasant-gray dark:bg-gray-700 transition-colors duration-200">
|
||||
<tr class="text-center bg-pleasant-gray dark:bg-gray-800/40 transition-colors duration-200">
|
||||
<td class="p-24" {colspan}>
|
||||
{#if page === 1}
|
||||
<p class="text-lg text-gray-600 dark:text-gray-300 transition-colors duration-200">
|
||||
<p class="text-lg text-gray-600 dark:text-gray-200 transition-colors duration-200">
|
||||
No {plural} found
|
||||
</p>
|
||||
{:else}
|
||||
<p class="text-lg text-gray-600 dark:text-gray-300 transition-colors duration-200">
|
||||
<p class="text-lg text-gray-600 dark:text-gray-200 transition-colors duration-200">
|
||||
No more results found
|
||||
</p>
|
||||
{/if}
|
||||
|
||||
@@ -11,7 +11,7 @@
|
||||
</script>
|
||||
|
||||
<div
|
||||
class="flex items-center text-ellipsis text-gray-900 dark:text-gray-100 transition-colors duration-200"
|
||||
class="flex items-center text-ellipsis text-gray-900 dark:text-gray-200 transition-colors duration-200"
|
||||
>
|
||||
<div class="w-4 h-4 {event.color} mr-2 rounded-sm"></div>
|
||||
{event.name}
|
||||
|
||||
@@ -56,11 +56,11 @@
|
||||
<div
|
||||
bind:this={tableWrapper}
|
||||
class="
|
||||
border-2 border-gray-200 dark:border-gray-600 rounded-md px-4 py-4 overflow-x-auto bg-white dark:bg-gray-800 transition-colors duration-200
|
||||
border-2 border-gray-200 dark:border-gray-700/60 rounded-md px-4 py-4 overflow-x-auto bg-white dark:bg-gray-900/80 transition-colors duration-200
|
||||
{scrollBarClassesHorizontal}"
|
||||
>
|
||||
<table
|
||||
class="w-full table-fixed bg-white dark:bg-gray-800 transition-colors duration-200"
|
||||
class="w-full table-fixed bg-white dark:bg-gray-900/80 transition-colors duration-200"
|
||||
class:animate-pulse={isGhost}
|
||||
>
|
||||
<TableHeader {isGhost} {columns} {sortable} {hasActions} {pagination} />
|
||||
|
||||
@@ -11,7 +11,7 @@
|
||||
</script>
|
||||
|
||||
<td
|
||||
class={`pl-4 font-regular text-slate-600 dark:text-gray-300 text-ellipsis whitespace-nowrap overflow-hidden pr-4 transition-colors duration-200`}
|
||||
class={`pl-4 font-regular text-slate-600 dark:text-gray-200 text-ellipsis whitespace-nowrap overflow-hidden pr-4 transition-colors duration-200`}
|
||||
title={isDate ? '' : value}
|
||||
>
|
||||
{#if value}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
<td class="w-48 text-center border: hidden;">
|
||||
<p class="font-regular text-slate-600 dark:text-gray-300 transition-colors duration-200">
|
||||
<p class="font-regular text-slate-600 dark:text-gray-200 transition-colors duration-200">
|
||||
<slot />
|
||||
</p>
|
||||
</td>
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
|
||||
<td class="pl-4 w-40 text-center border: hidden;">
|
||||
<p
|
||||
class="font-regular text-slate-600 dark:text-gray-300 flex justify-center transition-colors duration-200"
|
||||
class="font-regular text-slate-600 dark:text-gray-200 flex justify-center transition-colors duration-200"
|
||||
>
|
||||
{value ? 'Yes' : 'No'}
|
||||
</p>
|
||||
|
||||
@@ -1 +1,2 @@
|
||||
<td class="pl-4 w-4 border: hidden; bg-white dark:bg-gray-800 transition-colors duration-200"> </td>
|
||||
<td class="pl-4 w-4 border: hidden; bg-white dark:bg-gray-900/40 transition-colors duration-200">
|
||||
</td>
|
||||
|
||||
@@ -4,10 +4,10 @@
|
||||
</script>
|
||||
|
||||
<td
|
||||
class="pl-4 font-regular text-slate-600 dark:text-gray-300 text-ellipsis whitespace-nowrap overflow-hidden pr-4 transition-colors duration-200"
|
||||
class="pl-4 font-regular text-slate-600 dark:text-gray-200 text-ellipsis whitespace-nowrap overflow-hidden pr-4 transition-colors duration-200"
|
||||
{title}
|
||||
>
|
||||
<a href={href} class="block w-full py-1">
|
||||
<a {href} class="block w-full py-1">
|
||||
<slot />
|
||||
</a>
|
||||
</td>
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
|
||||
{#if disabled}
|
||||
<button
|
||||
class="w-full px py text-slate-300 dark:text-gray-500 cursor-not-allowed text-left transition-colors duration-200"
|
||||
class="w-full px py text-slate-300 dark:text-gray-600 cursor-not-allowed text-left transition-colors duration-200"
|
||||
{disabled}
|
||||
{title}
|
||||
>
|
||||
@@ -17,7 +17,7 @@
|
||||
</button>
|
||||
{:else}
|
||||
<button
|
||||
class="w-full px py-1 text-slate-600 dark:text-gray-300 hover:bg-red-400 dark:hover:bg-red-500 hover:text-white cursor-pointer text-left transition-colors duration-200"
|
||||
class="w-full px py-1 text-slate-600 dark:text-gray-200 hover:bg-red-400 dark:hover:bg-red-600/70 hover:text-white cursor-pointer text-left transition-colors duration-200"
|
||||
on:click
|
||||
{title}
|
||||
>
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
|
||||
{#if disabled}
|
||||
<button
|
||||
class="w-full px py-1 text-slate-300 dark:text-gray-500 cursor-not-allowed text-left transition-colors duration-200"
|
||||
class="w-full px py-1 text-slate-300 dark:text-gray-600 cursor-not-allowed text-left transition-colors duration-200"
|
||||
{disabled}
|
||||
{title}
|
||||
>
|
||||
@@ -25,7 +25,7 @@
|
||||
</button>
|
||||
{:else}
|
||||
<button
|
||||
class="w-full px py-1 text-slate-600 dark:text-gray-300 hover:bg-highlight-blue dark:hover:bg-blue-600 hover:text-white cursor-pointer text-left transition-colors duration-200"
|
||||
class="w-full px py-1 text-slate-600 dark:text-gray-200 hover:bg-highlight-blue dark:hover:bg-highlight-blue/50 hover:text-white cursor-pointer text-left transition-colors duration-200"
|
||||
on:click
|
||||
on:keydown={handleKeydown}
|
||||
{title}
|
||||
|
||||
@@ -160,7 +160,7 @@
|
||||
|
||||
<div
|
||||
bind:this={menuRef}
|
||||
class="absolute bg-white dark:bg-gray-800 drop-shadow-md dark:shadow-gray-900/50 border dark:border-gray-600 z-20 w-48 rounded-md overflow-y-scroll transition-colors duration-200 {scrollBarClassesVertical}"
|
||||
class="absolute bg-white dark:bg-gray-900/90 drop-shadow-md dark:shadow-gray-900/50 border dark:border-gray-700/60 z-20 w-48 rounded-md overflow-y-scroll transition-colors duration-200 {scrollBarClassesVertical}"
|
||||
class:hidden={!isMenuVisible}
|
||||
>
|
||||
<ul class="flex flex-col text-left">
|
||||
|
||||
@@ -1,3 +1,3 @@
|
||||
<thead class="table-header-group bg-white dark:bg-gray-800 transition-colors duration-200">
|
||||
<thead class="table-header-group bg-white dark:bg-gray-900/60 transition-colors duration-200">
|
||||
<slot />
|
||||
</thead>
|
||||
|
||||
@@ -34,7 +34,7 @@
|
||||
</script>
|
||||
|
||||
<th
|
||||
class="pl-4 bg-grayblue-light dark:bg-gray-700 py-4 border-hidden first:rounded-tl-lg first:rounded-bl-lg last:rounded-tr-lg last:border-4 min-w-48 transition-colors duration-200"
|
||||
class="pl-4 bg-grayblue-light dark:bg-gray-800/60 py-4 border-hidden first:rounded-tl-lg first:rounded-bl-lg last:rounded-tr-lg last:border-4 min-w-48 transition-colors duration-200"
|
||||
class:rounded-br-lg={last}
|
||||
class:rounded-tr-lg={last}
|
||||
class:w-48={size === 'small'}
|
||||
@@ -43,9 +43,11 @@
|
||||
class:w-full={fillRest}
|
||||
>
|
||||
<button
|
||||
class="flex group cursor-pointer"
|
||||
class="flex group cursor-pointer hover:bg-gray-50 dark:hover:bg-gray-700/30 rounded-md p-1 transition-colors duration-200"
|
||||
class:pointer-events-none={!sortable}
|
||||
class:table-cell={alignText === 'center'}
|
||||
class:hover:bg-transparent={!sortable}
|
||||
class:dark:hover:bg-transparent={!sortable}
|
||||
on:click|preventDefault={setSortAndSortBy}
|
||||
>
|
||||
<div class="w-full">
|
||||
@@ -60,7 +62,7 @@
|
||||
{#if sortable && column.toLowerCase() === sortBy.toLowerCase() && !isGhost}
|
||||
<div
|
||||
class:bg-transparent={sortOrder === ''}
|
||||
class="flex justify-center items-center w-6 h-6 ml-2 rounded-md bg-cta-blue dark:bg-blue-600 transition-colors duration-200"
|
||||
class="flex justify-center items-center w-6 h-6 ml-2 rounded-md bg-cta-blue dark:bg-highlight-blue/80 transition-colors duration-200"
|
||||
>
|
||||
{#if sortOrder === 'asc'}
|
||||
<div>
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
<th
|
||||
class="bg-cta-light-blue dark:bg-gray-700 w-20 py-4 border-hidden rounded-lg transition-colors duration-200"
|
||||
class="bg-cta-light-blue dark:bg-gray-800/60 w-20 py-4 border-hidden rounded-lg transition-colors duration-200"
|
||||
>
|
||||
<p class="font-bold text-slate-600 dark:text-gray-200 text-center transition-colors duration-200">
|
||||
<slot />
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
<th
|
||||
class="pl-4 bg-grayblue-light dark:bg-gray-700 w-48 py-4 border-hidden transition-colors duration-200"
|
||||
class="pl-4 bg-grayblue-light dark:bg-gray-800/60 w-48 py-4 border-hidden transition-colors duration-200"
|
||||
>
|
||||
<p
|
||||
class="font-bold text-slate-600 dark:text-gray-200 flex justify-center text-center transition-colors duration-200"
|
||||
|
||||
@@ -1,2 +1,2 @@
|
||||
<th class="pl-4 bg-white dark:bg-gray-800 w-4 py-4 border-hidden transition-colors duration-200">
|
||||
<th class="pl-4 bg-white dark:bg-gray-900 w-4 py-4 border-hidden transition-colors duration-200">
|
||||
</th>
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
<th
|
||||
class="pl-4 bg-grayblue-light dark:bg-gray-700 w-48 py-4 border-hidden rounded-md transition-colors duration-200"
|
||||
class="pl-4 bg-grayblue-light dark:bg-gray-800/60 w-48 py-4 border-hidden rounded-md transition-colors duration-200"
|
||||
>
|
||||
<p class="font-bold text-slate-600 dark:text-gray-200 text-left transition-colors duration-200">
|
||||
<slot />
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
<tr
|
||||
class="table-row odd:bg-white odd:dark:bg-gray-800 even:bg-pleasant-gray even:dark:bg-gray-900 h-10 hover:bg-cta-light-blue hover:dark:bg-indigo-800 transition-colors duration-200"
|
||||
class="table-row odd:bg-white odd:dark:bg-gray-900/40 even:bg-pleasant-gray even:dark:bg-gray-800/30 h-10 hover:bg-cta-light-blue hover:dark:bg-highlight-blue/20 transition-colors duration-200"
|
||||
>
|
||||
<slot />
|
||||
</tr>
|
||||
|
||||
@@ -1,3 +1,3 @@
|
||||
<tr class="table-row bg-white dark:bg-gray-800 h-4 transition-colors duration-200">
|
||||
<tr class="table-row bg-white dark:bg-gray-900/40 h-4 transition-colors duration-200">
|
||||
<slot />
|
||||
</tr>
|
||||
|
||||
@@ -17,6 +17,7 @@
|
||||
import DesktopMenu from '$lib/components/header/DesktopMenu.svelte';
|
||||
import { hideIsLoading, showIsLoading } from '$lib/store/loading';
|
||||
import Header from '$lib/components/header/Header.svelte';
|
||||
import CompanyBanner from '$lib/components/header/CompanyBanner.svelte';
|
||||
import { setupTheme, setupOSThemeListener } from '$lib/theme.js';
|
||||
// Removed feature flags import - no longer needed
|
||||
|
||||
@@ -222,10 +223,10 @@
|
||||
{#if installState === AppStateService.INSTALL.INSTALLED}
|
||||
<MobileMenu
|
||||
bind:visible={isMobileMenuVisible}
|
||||
username={user?.name}
|
||||
onClickLogout={logout}
|
||||
{toggleChangeCompanyModal}
|
||||
/>
|
||||
<ProfileMenu {logout} bind:visible={isProfileMenuVisible} />
|
||||
<ProfileMenu {logout} bind:visible={isProfileMenuVisible} {toggleChangeCompanyModal} />
|
||||
{/if}
|
||||
<div class="col-start-1 col-end-13 row-start-1">
|
||||
<slot />
|
||||
|
||||
@@ -945,21 +945,25 @@ Simulation URLs to allow:\n${allowListingData.simulationUrl}\n
|
||||
<!-- Before Landing Page -->
|
||||
<div class="flex items-center">
|
||||
<div
|
||||
class={`w-10 h-10 rounded-lg flex items-center justify-center border mr-3
|
||||
${formValues.beforeLandingPage ? 'bg-blue-50 border-blue-300' : 'bg-gray-100 border-gray-300'}`}
|
||||
class={`w-10 h-10 rounded-lg flex items-center justify-center border mr-3 transition-colors duration-200
|
||||
${formValues.beforeLandingPage ? 'bg-blue-50 dark:bg-blue-900/40 border-blue-300 dark:border-blue-500' : 'bg-gray-100 dark:bg-gray-800/60 border-gray-300 dark:border-gray-600'}`}
|
||||
>
|
||||
<span
|
||||
class={`text-xl ${formValues.beforeLandingPage ? 'text-blue-500' : 'text-gray-400'}`}
|
||||
class={`text-xl transition-colors duration-200 ${formValues.beforeLandingPage ? 'text-blue-500 dark:text-blue-300' : 'text-gray-400 dark:text-gray-500'}`}
|
||||
>1</span
|
||||
>
|
||||
</div>
|
||||
<div class="flex-1">
|
||||
<p class="text-xs font-medium">
|
||||
<p
|
||||
class="text-xs font-medium text-gray-900 dark:text-gray-300 transition-colors duration-200"
|
||||
>
|
||||
Before Landing {formValues.beforeLandingPageType === 'proxy'
|
||||
? 'Proxy'
|
||||
: 'Page'}
|
||||
</p>
|
||||
<p class="text-xs text-gray-500 truncate max-w-[180px]">
|
||||
<p
|
||||
class="text-xs text-gray-500 dark:text-gray-400 truncate max-w-[180px] transition-colors duration-200"
|
||||
>
|
||||
{formValues.beforeLandingPage || 'Not selected'}
|
||||
</p>
|
||||
</div>
|
||||
@@ -967,21 +971,30 @@ Simulation URLs to allow:\n${allowListingData.simulationUrl}\n
|
||||
|
||||
<!-- Down Arrow -->
|
||||
<div class="flex">
|
||||
<div class="ml-5 w-0.5 h-4 bg-gray-300"></div>
|
||||
<div
|
||||
class="ml-5 w-0.5 h-4 bg-gray-300 dark:bg-gray-600 transition-colors duration-200"
|
||||
></div>
|
||||
</div>
|
||||
|
||||
<!-- Main Landing Page -->
|
||||
<div class="flex items-center">
|
||||
<div
|
||||
class="w-10 h-10 rounded-lg bg-blue-100 flex items-center justify-center border border-blue-400 mr-3"
|
||||
class="w-10 h-10 rounded-lg bg-blue-100 dark:bg-blue-900/40 flex items-center justify-center border border-blue-400 dark:border-blue-500 mr-3 transition-colors duration-200"
|
||||
>
|
||||
<span class="text-xl text-blue-600">2</span>
|
||||
<span
|
||||
class="text-xl text-blue-600 dark:text-blue-300 transition-colors duration-200"
|
||||
>2</span
|
||||
>
|
||||
</div>
|
||||
<div class="flex-1">
|
||||
<p class="text-xs font-medium">
|
||||
<p
|
||||
class="text-xs font-medium text-gray-900 dark:text-gray-300 transition-colors duration-200"
|
||||
>
|
||||
Landing {formValues.landingPageType === 'proxy' ? 'Proxy' : 'Page'}
|
||||
</p>
|
||||
<p class="text-xs text-gray-500 truncate max-w-[180px]">
|
||||
<p
|
||||
class="text-xs text-gray-500 dark:text-gray-400 truncate max-w-[180px] transition-colors duration-200"
|
||||
>
|
||||
{formValues.landingPage || 'Required'}
|
||||
</p>
|
||||
</div>
|
||||
@@ -989,25 +1002,31 @@ Simulation URLs to allow:\n${allowListingData.simulationUrl}\n
|
||||
|
||||
<!-- Down Arrow -->
|
||||
<div class="flex">
|
||||
<div class="ml-5 w-0.5 h-4 bg-gray-300"></div>
|
||||
<div
|
||||
class="ml-5 w-0.5 h-4 bg-gray-300 dark:bg-gray-600 transition-colors duration-200"
|
||||
></div>
|
||||
</div>
|
||||
|
||||
<!-- After Landing Page -->
|
||||
<div class="flex items-center">
|
||||
<div
|
||||
class={`w-10 h-10 rounded-lg flex items-center justify-center border mr-3
|
||||
${formValues.afterLandingPage ? 'bg-blue-50 border-blue-300' : 'bg-gray-100 border-gray-300'}`}
|
||||
class={`w-10 h-10 rounded-lg flex items-center justify-center border mr-3 transition-colors duration-200
|
||||
${formValues.afterLandingPage ? 'bg-blue-50 dark:bg-blue-900/40 border-blue-300 dark:border-blue-500' : 'bg-gray-100 dark:bg-gray-800/60 border-gray-300 dark:border-gray-600'}`}
|
||||
>
|
||||
<span
|
||||
class={`text-xl ${formValues.afterLandingPage ? 'text-blue-500' : 'text-gray-400'}`}
|
||||
class={`text-xl transition-colors duration-200 ${formValues.afterLandingPage ? 'text-blue-500 dark:text-blue-300' : 'text-gray-400 dark:text-gray-500'}`}
|
||||
>3</span
|
||||
>
|
||||
</div>
|
||||
<div class="flex-1">
|
||||
<p class="text-xs font-medium">
|
||||
<p
|
||||
class="text-xs font-medium text-gray-900 dark:text-gray-300 transition-colors duration-200"
|
||||
>
|
||||
After Landing {formValues.afterLandingPageType === 'proxy' ? 'Proxy' : 'Page'}
|
||||
</p>
|
||||
<p class="text-xs text-gray-500 truncate max-w-[180px]">
|
||||
<p
|
||||
class="text-xs text-gray-500 dark:text-gray-400 truncate max-w-[180px] transition-colors duration-200"
|
||||
>
|
||||
{formValues.afterLandingPage || 'Not selected'}
|
||||
</p>
|
||||
</div>
|
||||
@@ -1015,23 +1034,31 @@ Simulation URLs to allow:\n${allowListingData.simulationUrl}\n
|
||||
|
||||
<!-- Down Arrow -->
|
||||
<div class="flex">
|
||||
<div class="ml-5 w-0.5 h-4 bg-gray-300"></div>
|
||||
<div
|
||||
class="ml-5 w-0.5 h-4 bg-gray-300 dark:bg-gray-600 transition-colors duration-200"
|
||||
></div>
|
||||
</div>
|
||||
|
||||
<!-- Final Redirect -->
|
||||
<div class="flex items-center">
|
||||
<div
|
||||
class={`w-10 h-10 rounded-lg flex items-center justify-center border mr-3
|
||||
${formValues.afterLandingPageRedirectURL ? 'bg-blue-50 border-blue-300' : 'bg-gray-100 border-gray-300'}`}
|
||||
class={`w-10 h-10 rounded-lg flex items-center justify-center border mr-3 transition-colors duration-200
|
||||
${formValues.afterLandingPageRedirectURL ? 'bg-blue-50 dark:bg-blue-900/40 border-blue-300 dark:border-blue-500' : 'bg-gray-100 dark:bg-gray-800/60 border-gray-300 dark:border-gray-600'}`}
|
||||
>
|
||||
<span
|
||||
class={`text-xl ${formValues.afterLandingPageRedirectURL ? 'text-blue-500' : 'text-gray-400'}`}
|
||||
class={`text-xl transition-colors duration-200 ${formValues.afterLandingPageRedirectURL ? 'text-blue-500 dark:text-blue-300' : 'text-gray-400 dark:text-gray-500'}`}
|
||||
>4</span
|
||||
>
|
||||
</div>
|
||||
<div class="flex-1">
|
||||
<p class="text-xs font-medium">POST Redirect URL</p>
|
||||
<p class="text-xs text-gray-500 truncate max-w-[180px]">
|
||||
<p
|
||||
class="text-xs font-medium text-gray-900 dark:text-gray-300 transition-colors duration-200"
|
||||
>
|
||||
POST Redirect URL
|
||||
</p>
|
||||
<p
|
||||
class="text-xs text-gray-500 dark:text-gray-400 truncate max-w-[180px] transition-colors duration-200"
|
||||
>
|
||||
{formValues.afterLandingPageRedirectURL || 'Not set'}
|
||||
</p>
|
||||
</div>
|
||||
|
||||
@@ -6,12 +6,11 @@
|
||||
import SubHeadline from '$lib/components/SubHeadline.svelte';
|
||||
import { addToast } from '$lib/store/toast';
|
||||
import { BiMap } from '$lib/utils/maps';
|
||||
import { defaultOptions, fetchAllRows } from '$lib/utils/api-utils';
|
||||
import { fetchAllRows } from '$lib/utils/api-utils';
|
||||
import { AppStateService } from '$lib/service/appState';
|
||||
import ProxySvgIcon from '$lib/components/ProxySvgIcon.svelte';
|
||||
import TableRow from '$lib/components/table/TableRow.svelte';
|
||||
import TableCell from '$lib/components/table/TableCell.svelte';
|
||||
import TableCellLink from '$lib/components/table/TableCellLink.svelte';
|
||||
import { formatWeekDays, formatTimeConstraint, timeFormat } from '$lib/utils/date.js';
|
||||
import {
|
||||
defaultPerPage,
|
||||
@@ -37,9 +36,7 @@
|
||||
import Alert from '$lib/components/Alert.svelte';
|
||||
import EventTimeline from '$lib/components/EventTimeline.svelte';
|
||||
import CellCopy from '$lib/components/table/CopyCell.svelte';
|
||||
import Button from '$lib/components/Button.svelte';
|
||||
import FormGrid from '$lib/components/FormGrid.svelte';
|
||||
import FormFooter from '$lib/components/FormFooter.svelte';
|
||||
import FormColumns from '$lib/components/FormColumns.svelte';
|
||||
import FormColumn from '$lib/components/FormColumn.svelte';
|
||||
import EventName from '$lib/components/table/EventName.svelte';
|
||||
@@ -1039,12 +1036,12 @@
|
||||
fill="none"
|
||||
viewBox="0 0 24 24"
|
||||
stroke="currentColor"
|
||||
stroke-width="1.5"
|
||||
>
|
||||
<path
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
stroke-width="2"
|
||||
d="M3 8l7.89 5.26a2 2 0 002.22 0L21 8M5 19h14a2 2 0 002-2V7a2 2 0 00-2-2H5a2 2 0 00-2 2v10a2 2 0 002 2z"
|
||||
d="M21.75 6.75v10.5a2.25 2.25 0 01-2.25 2.25h-15a2.25 2.25 0 01-2.25-2.25V6.75m19.5 0A2.25 2.25 0 0019.5 4.5h-15a2.25 2.25 0 00-2.25 2.25m19.5 0v.243a2.25 2.25 0 01-1.07 1.916l-7.5 4.615a2.25 2.25 0 01-2.36 0L3.32 8.91a2.25 2.25 0 01-1.07-1.916V6.75"
|
||||
/>
|
||||
</svg>
|
||||
</StatsCard>
|
||||
@@ -1073,18 +1070,17 @@
|
||||
fill="none"
|
||||
viewBox="0 0 24 24"
|
||||
stroke="currentColor"
|
||||
stroke-width="1.5"
|
||||
>
|
||||
<path
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
stroke-width="2"
|
||||
d="M15 12a3 3 0 11-6 0 3 3 0 016 0z"
|
||||
d="M2.036 12.322a1.012 1.012 0 010-.639C3.423 7.51 7.36 4.5 12 4.5c4.638 0 8.573 3.007 9.963 7.178.07.207.07.431 0 .639C20.577 16.49 16.64 19.5 12 19.5c-4.638 0-8.573-3.007-9.963-7.178z"
|
||||
/>
|
||||
<path
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
stroke-width="2"
|
||||
d="M2.458 12C3.732 7.943 7.523 5 12 5c4.478 0 8.268 2.943 9.542 7-1.274 4.057-5.064 7-9.542 7-4.477 0-8.268-2.943-9.542-7z"
|
||||
d="M15 12a3 3 0 11-6 0 3 3 0 016 0z"
|
||||
/>
|
||||
</svg>
|
||||
</StatsCard>
|
||||
@@ -1164,12 +1160,12 @@
|
||||
fill="none"
|
||||
viewBox="0 0 24 24"
|
||||
stroke="currentColor"
|
||||
stroke-width="1.5"
|
||||
>
|
||||
<path
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
stroke-width="2"
|
||||
d="M9 17v-2m3 2v-4m3 4v-6m2 10H7a2 2 0 01-2-2V5a2 2 0 012-2h5.586a1 1 0 01.707.293l5.414 5.414a1 1 0 01.293.707V19a2 2 0 01-2 2z"
|
||||
d="M9 12.75L11.25 15 15 9.75M21 12a9 9 0 11-18 0 9 9 0 0118 0z"
|
||||
/>
|
||||
</svg>
|
||||
</StatsCard>
|
||||
|
||||
Reference in New Issue
Block a user