This commit is contained in:
MuslemRahimi 2025-03-04 11:29:38 +01:00
parent 7507190f26
commit e942da7511
14 changed files with 153 additions and 2129 deletions

15
package-lock.json generated
View File

@ -18,6 +18,7 @@
"ua-parser-js": "^1.0.37"
},
"devDependencies": {
"@bprogress/core": "^1.2.3",
"@internationalized/date": "^3.5.5",
"@playwright/test": "^1.43.1",
"@rollup/plugin-dynamic-import-vars": "^2.1.2",
@ -48,7 +49,6 @@
"lucide-svelte": "^0.438.0",
"luxon": "^3.5.0",
"memoize-one": "^6.0.0",
"nprogress": "^0.2.0",
"object-to-formdata": "^4.5.1",
"parse5": "^7.1.2",
"pocketbase": "^0.25.2",
@ -450,6 +450,13 @@
"node": ">=6.9.0"
}
},
"node_modules/@bprogress/core": {
"version": "1.2.3",
"resolved": "https://registry.npmjs.org/@bprogress/core/-/core-1.2.3.tgz",
"integrity": "sha512-RMdZtsbXB2IeygoyUo+eYXCyvnAB82JzmJgZXnS1B38hTnwzcveyiifLYa6VQvqaUkLNGns5tCCJFv+Qld5r4A==",
"dev": true,
"license": "MIT"
},
"node_modules/@choojs/findup": {
"version": "0.2.1",
"resolved": "https://registry.npmjs.org/@choojs/findup/-/findup-0.2.1.tgz",
@ -7103,12 +7110,6 @@
"url": "https://github.com/sponsors/sindresorhus"
}
},
"node_modules/nprogress": {
"version": "0.2.0",
"resolved": "https://registry.npmjs.org/nprogress/-/nprogress-0.2.0.tgz",
"integrity": "sha512-I19aIingLgR1fmhftnbWWO3dXc0hSxqHQHQb3H8m+K3TnEn/iSeTZZOyvKXWqQESMwuUVnatlCnZdLBZZt2VSA==",
"dev": true
},
"node_modules/number-is-integer": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/number-is-integer/-/number-is-integer-1.0.1.tgz",

View File

@ -18,6 +18,7 @@
"test:safari": "npx playwright test --headed --project=safari"
},
"devDependencies": {
"@bprogress/core": "^1.2.3",
"@internationalized/date": "^3.5.5",
"@playwright/test": "^1.43.1",
"@rollup/plugin-dynamic-import-vars": "^2.1.2",
@ -48,7 +49,6 @@
"lucide-svelte": "^0.438.0",
"luxon": "^3.5.0",
"memoize-one": "^6.0.0",
"nprogress": "^0.2.0",
"object-to-formdata": "^4.5.1",
"parse5": "^7.1.2",
"pocketbase": "^0.25.2",

View File

@ -15,20 +15,38 @@
}
@utility no-scrollbar {
/* Custom properties for easy color and size adjustments */
--scrollbar-width: 2px;
--scrollbar-track-color: #08080A;
--scrollbar-thumb-color: #888;
--scrollbar-thumb-hover-color: #555;
/* Prevent horizontal scrolling, allow vertical scrolling */
overflow-x: hidden;
overflow-y: auto;
/* Styles for WebKit browsers (Chrome, Safari, newer versions of Opera) */
/* WebKit browsers (Chrome, Safari, Opera) */
&::-webkit-scrollbar {
width: auto; /* Keep the width for vertical scrollbar */
height: 0; /* Set height to 0 to hide horizontal scrollbar */
width: var(--scrollbar-width);
height: 0; /* Hides horizontal scrollbar */
}
&::-webkit-scrollbar-track {
background: var(--scrollbar-track-color);
}
&::-webkit-scrollbar-thumb {
background-color: var(--scrollbar-thumb-color);
border-radius: 4px;
border: 1px solid var(--scrollbar-track-color);
}
&::-webkit-scrollbar-thumb:hover {
background-color: var(--scrollbar-thumb-hover-color);
}
/* Styles for Firefox */
/* Firefox styling */
scrollbar-width: thin;
scrollbar-color: auto transparent; /* vertical scrollbar color, then track color */
scrollbar-color: var(--scrollbar-thumb-color) var(--scrollbar-track-color);
/* Styles for Internet Explorer and Edge */
/* IE and Edge */
-ms-overflow-style: -ms-autohiding-scrollbar;
}

View File

@ -1,4 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" class="w-4 h-4 inline-block" viewBox="0 0 16 16"><g fill="white"><path d="M8 15A7 7 0 1 1 8 1a7 7 0 0 1 0 14zm0 1A8 8 0 1 0 8 0a8 8 0 0 0 0 16z"/><path d="m8.93 6.588l-2.29.287l-.082.38l.45.083c.294.07.352.176.288.469l-.738 3.468c-.194.897.105 1.319.808 1.319c.545 0 1.178-.252 1.465-.598l.088-.416c-.2.176-.492.246-.686.246c-.275 0-.375-.193-.304-.533L8.93 6.588zM9 4.5a1 1 0 1 1-2 0a1 1 0 0 1 2 0z"/></g></svg>

Before

Width:  |  Height:  |  Size: 456 B

View File

@ -1,207 +0,0 @@
.driver-active .driver-overlay,
.driver-active * {
pointer-events: none;
}
.driver-active .driver-active-element,
.driver-active .driver-active-element *,
.driver-popover,
.driver-popover * {
pointer-events: auto;
}
@keyframes animate-fade-in {
0% {
opacity: 0;
}
to {
opacity: 1;
}
}
.driver-fade .driver-overlay {
animation: animate-fade-in 0.2s ease-in-out;
}
.driver-fade .driver-popover {
animation: animate-fade-in 0.2s;
}
.driver-popover {
all: unset;
box-sizing: border-box;
color: #fff;
margin: 0;
padding: 20px;
border-radius: 0px;
min-width: 250px;
max-width: 500px;
box-shadow: 0 1px 10px #0006;
z-index: 1000000000;
position: fixed;
top: 0;
right: 0;
background-color: #202327;
}
.driver-popover * {
font-family:
Helvetica Neue,
Inter,
ui-sans-serif,
"Apple Color Emoji",
Helvetica,
Arial,
sans-serif;
}
.driver-popover-title {
font: 19px / normal sans-serif;
font-weight: 700;
display: block;
position: relative;
line-height: 1.5;
zoom: 1;
margin: 0;
}
.driver-popover-close-btn {
all: unset;
position: absolute;
top: 0;
right: 0;
width: 32px;
height: 28px;
cursor: pointer;
font-size: 18px;
font-weight: 500;
color: #d2d2d2;
z-index: 1;
text-align: center;
transition: color;
transition-duration: 0.2s;
}
.driver-popover-close-btn:hover,
.driver-popover-close-btn:focus {
color: #2d2d2d;
}
.driver-popover-title[style*="block"] + .driver-popover-description {
margin-top: 5px;
}
.driver-popover-description {
margin-bottom: 0;
font: 16px / normal sans-serif;
line-height: 1.5;
font-weight: 500;
zoom: 1;
}
.driver-popover-footer {
margin-top: 40px;
text-align: right;
zoom: 1;
display: flex;
align-items: center;
justify-content: space-between;
}
.driver-popover-progress-text {
font-size: 15px;
font-weight: 400;
color: #fff;
zoom: 1;
}
.driver-popover-footer button {
all: unset;
display: inline-block;
box-sizing: border-box;
padding: 8px 20px;
text-decoration: none;
text-shadow: 1px 1px 0 #fff;
background-color: #fff;
color: #2d2d2d;
font: 14px / normal sans-serif;
cursor: pointer;
outline: 0;
zoom: 1;
line-height: 1.3;
border: 1px solid #ccc;
border-radius: 3px;
}
.driver-popover-footer .driver-popover-btn-disabled {
opacity: 0.5;
pointer-events: none;
}
:not(body):has(> .driver-active-element) {
overflow: hidden !important;
}
.driver-no-interaction,
.driver-no-interaction * {
pointer-events: none !important;
}
.driver-popover-footer button:hover,
.driver-popover-footer button:focus {
background-color: #f7f7f7;
}
.driver-popover-navigation-btns {
display: flex;
flex-grow: 1;
justify-content: flex-end;
}
.driver-popover-navigation-btns button + button {
margin-left: 4px;
}
.driver-popover-arrow {
content: "";
position: absolute;
border: 5px solid #fff;
}
.driver-popover-arrow-side-over {
display: none;
}
.driver-popover-arrow-side-left {
left: 100%;
border-right-color: transparent;
border-bottom-color: transparent;
border-top-color: transparent;
}
.driver-popover-arrow-side-right {
right: 100%;
border-left-color: transparent;
border-bottom-color: transparent;
border-top-color: transparent;
}
.driver-popover-arrow-side-top {
top: 100%;
border-right-color: transparent;
border-bottom-color: transparent;
border-left-color: transparent;
}
.driver-popover-arrow-side-bottom {
bottom: 100%;
border-left-color: transparent;
border-top-color: transparent;
border-right-color: transparent;
}
.driver-popover-arrow-side-center {
display: none;
}
.driver-popover-arrow-side-left.driver-popover-arrow-align-start,
.driver-popover-arrow-side-right.driver-popover-arrow-align-start {
top: 15px;
}
.driver-popover-arrow-side-top.driver-popover-arrow-align-start,
.driver-popover-arrow-side-bottom.driver-popover-arrow-align-start {
left: 15px;
}
.driver-popover-arrow-align-end.driver-popover-arrow-side-left,
.driver-popover-arrow-align-end.driver-popover-arrow-side-right {
bottom: 15px;
}
.driver-popover-arrow-side-top.driver-popover-arrow-align-end,
.driver-popover-arrow-side-bottom.driver-popover-arrow-align-end {
right: 15px;
}
.driver-popover-arrow-side-left.driver-popover-arrow-align-center,
.driver-popover-arrow-side-right.driver-popover-arrow-align-center {
top: 50%;
margin-top: -5px;
}
.driver-popover-arrow-side-top.driver-popover-arrow-align-center,
.driver-popover-arrow-side-bottom.driver-popover-arrow-align-center {
left: 50%;
margin-left: -5px;
}
.driver-popover-arrow-none {
display: none;
}

View File

@ -1,996 +0,0 @@
/*!
* Quill Editor v1.3.6
* https://quilljs.com/
* Copyright (c) 2014, Jason Chen
* Copyright (c) 2013, salesforce.com
*/
.ql-container {
box-sizing: border-box;
font-family: Helvetica, Arial, sans-serif;
font-size: 13px;
height: 100%;
margin: 0px;
position: relative;
}
.ql-container.ql-disabled .ql-tooltip {
visibility: hidden;
}
.ql-container.ql-disabled .ql-editor ul[data-checked] > li::before {
pointer-events: none;
}
.ql-clipboard {
left: -100000px;
height: 1px;
overflow-y: hidden;
position: absolute;
top: 50%;
}
.ql-clipboard p {
margin: 0;
padding: 0;
}
.ql-editor {
box-sizing: border-box;
line-height: 1.42;
height: 100%;
outline: none;
overflow-y: auto;
padding: 12px 15px;
tab-size: 4;
-moz-tab-size: 4;
text-align: left;
white-space: pre-wrap;
word-wrap: break-word;
}
.ql-editor > * {
cursor: text;
}
.ql-editor p,
.ql-editor ol,
.ql-editor ul,
.ql-editor pre,
.ql-editor blockquote,
.ql-editor h1,
.ql-editor h2,
.ql-editor h3,
.ql-editor h4,
.ql-editor h5,
.ql-editor h6 {
margin: 0;
padding: 0;
counter-reset: list-1 list-2 list-3 list-4 list-5 list-6 list-7 list-8 list-9;
}
.ql-editor ol,
.ql-editor ul {
padding-left: 1.5em;
}
.ql-editor ol > li,
.ql-editor ul > li {
list-style-type: none;
}
.ql-editor ul > li::before {
content: "\2022";
}
.ql-editor ul[data-checked="true"],
.ql-editor ul[data-checked="false"] {
pointer-events: none;
}
.ql-editor ul[data-checked="true"] > li *,
.ql-editor ul[data-checked="false"] > li * {
pointer-events: all;
}
.ql-editor ul[data-checked="true"] > li::before,
.ql-editor ul[data-checked="false"] > li::before {
color: #777;
cursor: pointer;
pointer-events: all;
}
.ql-editor ul[data-checked="true"] > li::before {
content: "\2611";
}
.ql-editor ul[data-checked="false"] > li::before {
content: "\2610";
}
.ql-editor li::before {
display: inline-block;
white-space: nowrap;
width: 1.2em;
}
.ql-editor li:not(.ql-direction-rtl)::before {
margin-left: -1.5em;
margin-right: 0.3em;
text-align: right;
}
.ql-editor li.ql-direction-rtl::before {
margin-left: 0.3em;
margin-right: -1.5em;
}
.ql-editor ol li:not(.ql-direction-rtl),
.ql-editor ul li:not(.ql-direction-rtl) {
padding-left: 1.5em;
}
.ql-editor ol li.ql-direction-rtl,
.ql-editor ul li.ql-direction-rtl {
padding-right: 1.5em;
}
.ql-editor ol li {
counter-reset: list-1 list-2 list-3 list-4 list-5 list-6 list-7 list-8 list-9;
counter-increment: list-0;
}
.ql-editor ol li:before {
content: counter(list-0, decimal) ". ";
}
.ql-editor ol li.ql-indent-1 {
counter-increment: list-1;
}
.ql-editor ol li.ql-indent-1:before {
content: counter(list-1, lower-alpha) ". ";
}
.ql-editor ol li.ql-indent-1 {
counter-reset: list-2 list-3 list-4 list-5 list-6 list-7 list-8 list-9;
}
.ql-editor ol li.ql-indent-2 {
counter-increment: list-2;
}
.ql-editor ol li.ql-indent-2:before {
content: counter(list-2, lower-roman) ". ";
}
.ql-editor ol li.ql-indent-2 {
counter-reset: list-3 list-4 list-5 list-6 list-7 list-8 list-9;
}
.ql-editor ol li.ql-indent-3 {
counter-increment: list-3;
}
.ql-editor ol li.ql-indent-3:before {
content: counter(list-3, decimal) ". ";
}
.ql-editor ol li.ql-indent-3 {
counter-reset: list-4 list-5 list-6 list-7 list-8 list-9;
}
.ql-editor ol li.ql-indent-4 {
counter-increment: list-4;
}
.ql-editor ol li.ql-indent-4:before {
content: counter(list-4, lower-alpha) ". ";
}
.ql-editor ol li.ql-indent-4 {
counter-reset: list-5 list-6 list-7 list-8 list-9;
}
.ql-editor ol li.ql-indent-5 {
counter-increment: list-5;
}
.ql-editor ol li.ql-indent-5:before {
content: counter(list-5, lower-roman) ". ";
}
.ql-editor ol li.ql-indent-5 {
counter-reset: list-6 list-7 list-8 list-9;
}
.ql-editor ol li.ql-indent-6 {
counter-increment: list-6;
}
.ql-editor ol li.ql-indent-6:before {
content: counter(list-6, decimal) ". ";
}
.ql-editor ol li.ql-indent-6 {
counter-reset: list-7 list-8 list-9;
}
.ql-editor ol li.ql-indent-7 {
counter-increment: list-7;
}
.ql-editor ol li.ql-indent-7:before {
content: counter(list-7, lower-alpha) ". ";
}
.ql-editor ol li.ql-indent-7 {
counter-reset: list-8 list-9;
}
.ql-editor ol li.ql-indent-8 {
counter-increment: list-8;
}
.ql-editor ol li.ql-indent-8:before {
content: counter(list-8, lower-roman) ". ";
}
.ql-editor ol li.ql-indent-8 {
counter-reset: list-9;
}
.ql-editor ol li.ql-indent-9 {
counter-increment: list-9;
}
.ql-editor ol li.ql-indent-9:before {
content: counter(list-9, decimal) ". ";
}
.ql-editor .ql-indent-1:not(.ql-direction-rtl) {
padding-left: 3em;
}
.ql-editor li.ql-indent-1:not(.ql-direction-rtl) {
padding-left: 4.5em;
}
.ql-editor .ql-indent-1.ql-direction-rtl.ql-align-right {
padding-right: 3em;
}
.ql-editor li.ql-indent-1.ql-direction-rtl.ql-align-right {
padding-right: 4.5em;
}
.ql-editor .ql-indent-2:not(.ql-direction-rtl) {
padding-left: 6em;
}
.ql-editor li.ql-indent-2:not(.ql-direction-rtl) {
padding-left: 7.5em;
}
.ql-editor .ql-indent-2.ql-direction-rtl.ql-align-right {
padding-right: 6em;
}
.ql-editor li.ql-indent-2.ql-direction-rtl.ql-align-right {
padding-right: 7.5em;
}
.ql-editor .ql-indent-3:not(.ql-direction-rtl) {
padding-left: 9em;
}
.ql-editor li.ql-indent-3:not(.ql-direction-rtl) {
padding-left: 10.5em;
}
.ql-editor .ql-indent-3.ql-direction-rtl.ql-align-right {
padding-right: 9em;
}
.ql-editor li.ql-indent-3.ql-direction-rtl.ql-align-right {
padding-right: 10.5em;
}
.ql-editor .ql-indent-4:not(.ql-direction-rtl) {
padding-left: 12em;
}
.ql-editor li.ql-indent-4:not(.ql-direction-rtl) {
padding-left: 13.5em;
}
.ql-editor .ql-indent-4.ql-direction-rtl.ql-align-right {
padding-right: 12em;
}
.ql-editor li.ql-indent-4.ql-direction-rtl.ql-align-right {
padding-right: 13.5em;
}
.ql-editor .ql-indent-5:not(.ql-direction-rtl) {
padding-left: 15em;
}
.ql-editor li.ql-indent-5:not(.ql-direction-rtl) {
padding-left: 16.5em;
}
.ql-editor .ql-indent-5.ql-direction-rtl.ql-align-right {
padding-right: 15em;
}
.ql-editor li.ql-indent-5.ql-direction-rtl.ql-align-right {
padding-right: 16.5em;
}
.ql-editor .ql-indent-6:not(.ql-direction-rtl) {
padding-left: 18em;
}
.ql-editor li.ql-indent-6:not(.ql-direction-rtl) {
padding-left: 19.5em;
}
.ql-editor .ql-indent-6.ql-direction-rtl.ql-align-right {
padding-right: 18em;
}
.ql-editor li.ql-indent-6.ql-direction-rtl.ql-align-right {
padding-right: 19.5em;
}
.ql-editor .ql-indent-7:not(.ql-direction-rtl) {
padding-left: 21em;
}
.ql-editor li.ql-indent-7:not(.ql-direction-rtl) {
padding-left: 22.5em;
}
.ql-editor .ql-indent-7.ql-direction-rtl.ql-align-right {
padding-right: 21em;
}
.ql-editor li.ql-indent-7.ql-direction-rtl.ql-align-right {
padding-right: 22.5em;
}
.ql-editor .ql-indent-8:not(.ql-direction-rtl) {
padding-left: 24em;
}
.ql-editor li.ql-indent-8:not(.ql-direction-rtl) {
padding-left: 25.5em;
}
.ql-editor .ql-indent-8.ql-direction-rtl.ql-align-right {
padding-right: 24em;
}
.ql-editor li.ql-indent-8.ql-direction-rtl.ql-align-right {
padding-right: 25.5em;
}
.ql-editor .ql-indent-9:not(.ql-direction-rtl) {
padding-left: 27em;
}
.ql-editor li.ql-indent-9:not(.ql-direction-rtl) {
padding-left: 28.5em;
}
.ql-editor .ql-indent-9.ql-direction-rtl.ql-align-right {
padding-right: 27em;
}
.ql-editor li.ql-indent-9.ql-direction-rtl.ql-align-right {
padding-right: 28.5em;
}
.ql-editor .ql-video {
display: block;
max-width: 100%;
}
.ql-editor .ql-video.ql-align-center {
margin: 0 auto;
}
.ql-editor .ql-video.ql-align-right {
margin: 0 0 0 auto;
}
.ql-editor .ql-bg-black {
background-color: #fff;
}
.ql-editor .ql-bg-red {
background-color: #e60000;
}
.ql-editor .ql-bg-orange {
background-color: #f90;
}
.ql-editor .ql-bg-yellow {
background-color: #ff0;
}
.ql-editor .ql-bg-green {
background-color: #008a00;
}
.ql-editor .ql-bg-blue {
background-color: #fff;
}
.ql-editor .ql-bg-purple {
background-color: #93f;
}
.ql-editor .ql-color-white {
color: #fff;
}
.ql-editor .ql-color-red {
color: #e60000;
}
.ql-editor .ql-color-orange {
color: #f90;
}
.ql-editor .ql-color-yellow {
color: #ff0;
}
.ql-editor .ql-color-green {
color: #008a00;
}
.ql-editor .ql-color-blue {
color: #fff;
}
.ql-editor .ql-color-purple {
color: #93f;
}
.ql-editor .ql-font-serif {
font-family:
Georgia,
Times New Roman,
serif;
}
.ql-editor .ql-font-monospace {
font-family:
Monaco,
Courier New,
monospace;
}
.ql-editor .ql-size-small {
font-size: 0.75em;
}
.ql-editor .ql-size-large {
font-size: 1.5em;
}
.ql-editor .ql-size-huge {
font-size: 2.5em;
}
.ql-editor .ql-direction-rtl {
direction: rtl;
text-align: inherit;
}
.ql-editor .ql-align-center {
text-align: center;
}
.ql-editor .ql-align-justify {
text-align: justify;
}
.ql-editor .ql-align-right {
text-align: right;
}
.ql-editor.ql-blank::before {
color: #9ca3af;
content: attr(data-placeholder);
font-style: italic;
left: 15px;
pointer-events: none;
position: absolute;
right: 15px;
}
.ql-snow.ql-toolbar:after,
.ql-snow .ql-toolbar:after {
clear: both;
content: "";
display: table;
}
.ql-snow.ql-toolbar button,
.ql-snow .ql-toolbar button {
background: none;
border: none;
cursor: pointer;
display: inline-block;
float: left;
height: 28px;
padding: 3px 5px;
width: 32px;
}
.ql-snow.ql-toolbar button svg,
.ql-snow .ql-toolbar button svg {
float: left;
height: 100%;
}
.ql-snow.ql-toolbar button:active:hover,
.ql-snow .ql-toolbar button:active:hover {
outline: none;
background: #3e4e59;
background-color: #3e4e59;
border-color: #3e4e59;
}
.ql-snow.ql-toolbar input.ql-image[type="file"],
.ql-snow .ql-toolbar input.ql-image[type="file"] {
display: none;
}
.ql-snow.ql-toolbar button:hover,
.ql-snow .ql-toolbar button:hover,
.ql-snow.ql-toolbar button:focus,
.ql-snow .ql-toolbar button:focus,
.ql-snow.ql-toolbar button.ql-active,
.ql-snow .ql-toolbar button.ql-active,
.ql-snow.ql-toolbar .ql-picker-label:hover,
.ql-snow .ql-toolbar .ql-picker-label:hover,
.ql-snow.ql-toolbar .ql-picker-label.ql-active,
.ql-snow .ql-toolbar .ql-picker-label.ql-active,
.ql-snow.ql-toolbar .ql-picker-item:hover,
.ql-snow .ql-toolbar .ql-picker-item:hover,
.ql-snow.ql-toolbar .ql-picker-item.ql-selected,
.ql-snow .ql-toolbar .ql-picker-item.ql-selected {
color: #fff;
background: #3e4e59;
border-radius: 5%;
}
.ql-snow.ql-toolbar button:hover .ql-fill,
.ql-snow .ql-toolbar button:hover .ql-fill,
.ql-snow.ql-toolbar button:focus .ql-fill,
.ql-snow .ql-toolbar button:focus .ql-fill,
.ql-snow.ql-toolbar button.ql-active .ql-fill,
.ql-snow .ql-toolbar button.ql-active .ql-fill,
.ql-snow.ql-toolbar .ql-picker-label:hover .ql-fill,
.ql-snow .ql-toolbar .ql-picker-label:hover .ql-fill,
.ql-snow.ql-toolbar .ql-picker-label.ql-active .ql-fill,
.ql-snow .ql-toolbar .ql-picker-label.ql-active .ql-fill,
.ql-snow.ql-toolbar .ql-picker-item:hover .ql-fill,
.ql-snow .ql-toolbar .ql-picker-item:hover .ql-fill,
.ql-snow.ql-toolbar .ql-picker-item.ql-selected .ql-fill,
.ql-snow .ql-toolbar .ql-picker-item.ql-selected .ql-fill,
.ql-snow.ql-toolbar button:hover .ql-stroke.ql-fill,
.ql-snow .ql-toolbar button:hover .ql-stroke.ql-fill,
.ql-snow.ql-toolbar button:focus .ql-stroke.ql-fill,
.ql-snow .ql-toolbar button:focus .ql-stroke.ql-fill,
.ql-snow.ql-toolbar button.ql-active .ql-stroke.ql-fill,
.ql-snow .ql-toolbar button.ql-active .ql-stroke.ql-fill,
.ql-snow.ql-toolbar .ql-picker-label:hover .ql-stroke.ql-fill,
.ql-snow .ql-toolbar .ql-picker-label:hover .ql-stroke.ql-fill,
.ql-snow.ql-toolbar .ql-picker-label.ql-active .ql-stroke.ql-fill,
.ql-snow .ql-toolbar .ql-picker-label.ql-active .ql-stroke.ql-fill,
.ql-snow.ql-toolbar .ql-picker-item:hover .ql-stroke.ql-fill,
.ql-snow .ql-toolbar .ql-picker-item:hover .ql-stroke.ql-fill,
.ql-snow.ql-toolbar .ql-picker-item.ql-selected .ql-stroke.ql-fill,
.ql-snow .ql-toolbar .ql-picker-item.ql-selected .ql-stroke.ql-fill {
fill: #fff;
}
.ql-snow.ql-toolbar button:hover .ql-stroke,
.ql-snow .ql-toolbar button:hover .ql-stroke,
.ql-snow.ql-toolbar button:focus .ql-stroke,
.ql-snow .ql-toolbar button:focus .ql-stroke,
.ql-snow.ql-toolbar button.ql-active .ql-stroke,
.ql-snow .ql-toolbar button.ql-active .ql-stroke,
.ql-snow.ql-toolbar .ql-picker-label:hover .ql-stroke,
.ql-snow .ql-toolbar .ql-picker-label:hover .ql-stroke,
.ql-snow.ql-toolbar .ql-picker-label.ql-active .ql-stroke,
.ql-snow .ql-toolbar .ql-picker-label.ql-active .ql-stroke,
.ql-snow.ql-toolbar .ql-picker-item:hover .ql-stroke,
.ql-snow .ql-toolbar .ql-picker-item:hover .ql-stroke,
.ql-snow.ql-toolbar .ql-picker-item.ql-selected .ql-stroke,
.ql-snow .ql-toolbar .ql-picker-item.ql-selected .ql-stroke,
.ql-snow.ql-toolbar button:hover .ql-stroke-miter,
.ql-snow .ql-toolbar button:hover .ql-stroke-miter,
.ql-snow.ql-toolbar button:focus .ql-stroke-miter,
.ql-snow .ql-toolbar button:focus .ql-stroke-miter,
.ql-snow.ql-toolbar button.ql-active .ql-stroke-miter,
.ql-snow .ql-toolbar button.ql-active .ql-stroke-miter,
.ql-snow.ql-toolbar .ql-picker-label:hover .ql-stroke-miter,
.ql-snow .ql-toolbar .ql-picker-label:hover .ql-stroke-miter,
.ql-snow.ql-toolbar .ql-picker-label.ql-active .ql-stroke-miter,
.ql-snow .ql-toolbar .ql-picker-label.ql-active .ql-stroke-miter,
.ql-snow.ql-toolbar .ql-picker-item:hover .ql-stroke-miter,
.ql-snow .ql-toolbar .ql-picker-item:hover .ql-stroke-miter,
.ql-snow.ql-toolbar .ql-picker-item.ql-selected .ql-stroke-miter,
.ql-snow .ql-toolbar .ql-picker-item.ql-selected .ql-stroke-miter {
stroke: #fff;
}
@media (pointer: coarse) {
.ql-snow.ql-toolbar button:hover:not(.ql-active),
.ql-snow .ql-toolbar button:hover:not(.ql-active) {
color: #fff;
}
.ql-snow.ql-toolbar button:hover:not(.ql-active) .ql-fill,
.ql-snow .ql-toolbar button:hover:not(.ql-active) .ql-fill,
.ql-snow.ql-toolbar button:hover:not(.ql-active) .ql-stroke.ql-fill,
.ql-snow .ql-toolbar button:hover:not(.ql-active) .ql-stroke.ql-fill {
fill: #fff;
}
.ql-snow.ql-toolbar button:hover:not(.ql-active) .ql-stroke,
.ql-snow .ql-toolbar button:hover:not(.ql-active) .ql-stroke,
.ql-snow.ql-toolbar button:hover:not(.ql-active) .ql-stroke-miter,
.ql-snow .ql-toolbar button:hover:not(.ql-active) .ql-stroke-miter {
stroke: #fff;
}
}
.ql-snow {
box-sizing: border-box;
}
.ql-snow * {
box-sizing: border-box;
}
.ql-snow .ql-hidden {
display: none;
}
.ql-snow .ql-out-bottom,
.ql-snow .ql-out-top {
visibility: hidden;
}
.ql-snow .ql-tooltip {
position: absolute;
transform: translateY(10px);
}
.ql-snow .ql-tooltip a {
cursor: pointer;
text-decoration: none;
background-color: #3e4e59;
}
.ql-snow .ql-tooltip.ql-flip {
transform: translateY(-10px);
}
.ql-snow .ql-formats {
display: inline-block;
vertical-align: middle;
}
.ql-snow .ql-formats:after {
clear: both;
content: "";
display: table;
}
.ql-snow .ql-stroke {
fill: none;
stroke: #fff;
stroke-linecap: round;
stroke-linejoin: round;
stroke-width: 2;
}
.ql-snow .ql-stroke-miter {
fill: none;
stroke: #fff;
stroke-miterlimit: 10;
stroke-width: 2;
}
.ql-snow .ql-fill,
.ql-snow .ql-stroke.ql-fill {
fill: #fff;
}
.ql-snow .ql-empty {
fill: none;
}
.ql-snow .ql-even {
fill-rule: evenodd;
}
.ql-snow .ql-thin,
.ql-snow .ql-stroke.ql-thin {
stroke-width: 1;
}
.ql-snow .ql-transparent {
opacity: 0.4;
}
.ql-snow .ql-direction svg:last-child {
display: none;
}
.ql-snow .ql-direction.ql-active svg:last-child {
display: inline;
}
.ql-snow .ql-direction.ql-active svg:first-child {
display: none;
}
.ql-snow .ql-editor h1 {
font-size: 2em;
}
.ql-snow .ql-editor h2 {
font-size: 1.5em;
}
.ql-snow .ql-editor h3 {
font-size: 1.17em;
}
.ql-snow .ql-editor h4 {
font-size: 1em;
}
.ql-snow .ql-editor h5 {
font-size: 0.83em;
}
.ql-snow .ql-editor h6 {
font-size: 0.67em;
}
.ql-snow .ql-editor a {
text-decoration: underline;
}
.ql-snow .ql-editor blockquote {
border-left: 4px solid #262b30;
margin-bottom: 5px;
margin-top: 5px;
padding-left: 16px;
}
.ql-snow .ql-editor code,
.ql-snow .ql-editor pre {
background-color: #262b30;
border-radius: 3px;
}
.ql-snow .ql-editor pre {
white-space: pre-wrap;
margin-bottom: 5px;
margin-top: 5px;
padding: 5px 10px;
}
.ql-snow .ql-editor code {
font-size: 85%;
padding: 2px 4px;
}
.ql-snow .ql-editor pre.ql-syntax {
background-color: #23241f;
color: #f8f8f2;
overflow: visible;
}
.ql-snow .ql-editor img {
max-width: 50%;
}
.ql-snow .ql-picker {
color: #fff;
display: inline-block;
float: left;
font-size: 14px;
font-weight: 500;
height: 24px;
position: relative;
vertical-align: middle;
}
.ql-snow .ql-picker-label {
cursor: pointer;
display: inline-block;
height: 100%;
padding-left: 8px;
padding-right: 2px;
position: relative;
width: 100%;
}
.ql-snow .ql-picker-label::before {
display: inline-block;
line-height: 22px;
}
.ql-snow .ql-picker-options {
background-color: #fff;
display: none;
min-width: 100%;
padding: 4px 8px;
position: absolute;
white-space: nowrap;
}
.ql-snow .ql-picker-options .ql-picker-item {
cursor: pointer;
display: block;
padding-bottom: 5px;
padding-top: 5px;
}
.ql-snow .ql-picker.ql-expanded .ql-picker-label {
color: #fff;
z-index: 2;
}
.ql-snow .ql-picker.ql-expanded .ql-picker-label .ql-fill {
fill: #fff;
}
.ql-snow .ql-picker.ql-expanded .ql-picker-label .ql-stroke {
stroke: #fff;
}
.ql-snow .ql-picker.ql-expanded .ql-picker-options {
display: block;
margin-top: -1px;
top: 100%;
z-index: 1;
background-color: #3e4e59;
}
#bg-color for heading selector .ql-snow .ql-color-picker,
.ql-snow .ql-icon-picker {
width: 28px;
}
.ql-snow .ql-color-picker .ql-picker-label,
.ql-snow .ql-icon-picker .ql-picker-label {
padding: 2px 4px;
}
.ql-snow .ql-color-picker .ql-picker-label svg,
.ql-snow .ql-icon-picker .ql-picker-label svg {
right: 4px;
}
.ql-snow .ql-icon-picker .ql-picker-options {
padding: 4px 0px;
}
.ql-snow .ql-icon-picker .ql-picker-item {
height: 24px;
width: 24px;
padding: 2px 4px;
}
.ql-snow .ql-color-picker .ql-picker-options {
padding: 3px 5px;
width: 152px;
}
.ql-snow .ql-color-picker .ql-picker-item {
border: 1px solid transparent;
float: left;
height: 16px;
margin: 2px;
padding: 0px;
width: 16px;
}
.ql-snow .ql-picker:not(.ql-color-picker):not(.ql-icon-picker) svg {
position: absolute;
margin-top: -9px;
right: 0;
top: 50%;
width: 18px;
}
.ql-snow
.ql-picker.ql-header
.ql-picker-label[data-label]:not([data-label=""])::before,
.ql-snow
.ql-picker.ql-font
.ql-picker-label[data-label]:not([data-label=""])::before,
.ql-snow
.ql-picker.ql-size
.ql-picker-label[data-label]:not([data-label=""])::before,
.ql-snow
.ql-picker.ql-header
.ql-picker-item[data-label]:not([data-label=""])::before,
.ql-snow
.ql-picker.ql-font
.ql-picker-item[data-label]:not([data-label=""])::before,
.ql-snow
.ql-picker.ql-size
.ql-picker-item[data-label]:not([data-label=""])::before {
content: attr(data-label);
}
.ql-snow .ql-picker.ql-header {
width: 98px;
}
.ql-snow .ql-picker.ql-header .ql-picker-label::before,
.ql-snow .ql-picker.ql-header .ql-picker-item::before {
content: "Normal";
}
.ql-snow .ql-picker.ql-header .ql-picker-label[data-value="1"]::before,
.ql-snow .ql-picker.ql-header .ql-picker-item[data-value="1"]::before {
content: "Heading 1";
background-color: #3e4e59;
}
.ql-snow .ql-picker.ql-header .ql-picker-label[data-value="2"]::before,
.ql-snow .ql-picker.ql-header .ql-picker-item[data-value="2"]::before {
content: "Heading 2";
background-color: #3e4e59;
}
.ql-snow .ql-picker.ql-header .ql-picker-label[data-value="3"]::before,
.ql-snow .ql-picker.ql-header .ql-picker-item[data-value="3"]::before {
content: "Heading 3";
background-color: #3e4e59;
}
.ql-snow .ql-picker.ql-header .ql-picker-label[data-value="4"]::before,
.ql-snow .ql-picker.ql-header .ql-picker-item[data-value="4"]::before {
content: "Heading 4";
background-color: #3e4e59;
}
.ql-snow .ql-picker.ql-header .ql-picker-label[data-value="5"]::before,
.ql-snow .ql-picker.ql-header .ql-picker-item[data-value="5"]::before {
content: "Heading 5";
background-color: #3e4e59;
}
.ql-snow .ql-picker.ql-header .ql-picker-label[data-value="6"]::before,
.ql-snow .ql-picker.ql-header .ql-picker-item[data-value="6"]::before {
content: "Heading 6";
background-color: #3e4e59;
}
.ql-snow .ql-picker.ql-header .ql-picker-item[data-value="1"]::before {
font-size: 2em;
}
.ql-snow .ql-picker.ql-header .ql-picker-item[data-value="2"]::before {
font-size: 1.5em;
}
.ql-snow .ql-picker.ql-header .ql-picker-item[data-value="3"]::before {
font-size: 1.17em;
}
.ql-snow .ql-picker.ql-header .ql-picker-item[data-value="4"]::before {
font-size: 1em;
}
.ql-snow .ql-picker.ql-header .ql-picker-item[data-value="5"]::before {
font-size: 0.83em;
}
.ql-snow .ql-picker.ql-header .ql-picker-item[data-value="6"]::before {
font-size: 0.67em;
}
.ql-snow .ql-picker.ql-font {
width: 108px;
}
.ql-snow .ql-picker.ql-font .ql-picker-label::before,
.ql-snow .ql-picker.ql-font .ql-picker-item::before {
content: "Sans Serif";
}
.ql-snow .ql-picker.ql-font .ql-picker-label[data-value="serif"]::before,
.ql-snow .ql-picker.ql-font .ql-picker-item[data-value="serif"]::before {
content: "Serif";
}
.ql-snow .ql-picker.ql-font .ql-picker-label[data-value="monospace"]::before,
.ql-snow .ql-picker.ql-font .ql-picker-item[data-value="monospace"]::before {
content: "Monospace";
}
.ql-snow .ql-picker.ql-font .ql-picker-item[data-value="serif"]::before {
font-family:
Georgia,
Times New Roman,
serif;
}
.ql-snow .ql-picker.ql-font .ql-picker-item[data-value="monospace"]::before {
font-family:
Monaco,
Courier New,
monospace;
}
.ql-snow .ql-picker.ql-size {
width: 98px;
}
.ql-snow .ql-picker.ql-size .ql-picker-label::before,
.ql-snow .ql-picker.ql-size .ql-picker-item::before {
content: "Normal";
}
.ql-snow .ql-picker.ql-size .ql-picker-label[data-value="small"]::before,
.ql-snow .ql-picker.ql-size .ql-picker-item[data-value="small"]::before {
content: "Small";
}
.ql-snow .ql-picker.ql-size .ql-picker-label[data-value="large"]::before,
.ql-snow .ql-picker.ql-size .ql-picker-item[data-value="large"]::before {
content: "Large";
}
.ql-snow .ql-picker.ql-size .ql-picker-label[data-value="huge"]::before,
.ql-snow .ql-picker.ql-size .ql-picker-item[data-value="huge"]::before {
content: "Huge";
}
.ql-snow .ql-picker.ql-size .ql-picker-item[data-value="small"]::before {
font-size: 10px;
}
.ql-snow .ql-picker.ql-size .ql-picker-item[data-value="large"]::before {
font-size: 18px;
}
.ql-snow .ql-picker.ql-size .ql-picker-item[data-value="huge"]::before {
font-size: 32px;
}
.ql-snow .ql-color-picker.ql-background .ql-picker-item {
background-color: #fff;
}
.ql-snow .ql-color-picker.ql-color .ql-picker-item {
background-color: #fff;
}
.ql-toolbar.ql-snow {
border: 1px solid #313131;
box-sizing: border-box;
font-family: "Helvetica Neue", "Helvetica", "Arial", sans-serif;
padding: 8px;
}
.ql-toolbar.ql-snow .ql-formats {
margin-right: 15px;
}
.ql-toolbar.ql-snow .ql-picker-label {
border: 1px solid transparent;
}
.ql-toolbar.ql-snow .ql-picker-options {
border: 1px solid transparent;
}
.ql-toolbar.ql-snow .ql-picker.ql-expanded .ql-picker-label {
border-color: #fff;
}
.ql-toolbar.ql-snow .ql-picker.ql-expanded .ql-picker-options {
border-color: #fff;
}
.ql-toolbar.ql-snow .ql-color-picker .ql-picker-item.ql-selected,
.ql-toolbar.ql-snow .ql-color-picker .ql-picker-item:hover {
border-color: #fff;
}
.ql-toolbar.ql-snow + .ql-container.ql-snow {
border-top: 0px;
}
.ql-snow .ql-tooltip {
background-color: #3e4e59;
border: 1px solid #fff;
box-shadow: 0px 0px 5px #ddd;
color: #fff;
padding: 5px 12px;
white-space: nowrap;
}
.ql-snow .ql-tooltip::before {
content: "Visit URL:";
line-height: 26px;
margin-right: 8px;
}
.ql-snow .ql-tooltip input[type="text"] {
display: none;
font-size: 13px;
height: 26px;
margin: 0px;
padding: 3px 5px;
width: 170px;
color: #000;
}
.ql-snow .ql-tooltip a.ql-preview {
display: inline-block;
max-width: 200px;
overflow-x: hidden;
text-overflow: ellipsis;
vertical-align: top;
}
.ql-snow .ql-tooltip a.ql-action::after {
border-right: 1px solid #fff;
content: "Edit";
margin-left: 16px;
padding-right: 8px;
background-color: #3e4e59;
}
.ql-snow .ql-tooltip a.ql-remove::before {
content: "Remove";
margin-left: 8px;
background-color: #3e4e59;
}
.ql-snow .ql-tooltip a {
line-height: 26px;
background-color: #3e4e59;
}
.ql-snow .ql-tooltip.ql-editing a.ql-preview,
.ql-snow .ql-tooltip.ql-editing a.ql-remove {
display: none;
}
.ql-snow .ql-tooltip.ql-editing input[type="text"] {
display: inline-block;
}
.ql-snow .ql-tooltip.ql-editing a.ql-action::after {
border-right: 0px;
content: "Save";
padding-right: 0px;
}
.ql-snow .ql-tooltip[data-mode="link"]::before {
content: "Enter link:";
}
.ql-snow .ql-tooltip[data-mode="formula"]::before {
content: "Enter formula:";
}
.ql-snow .ql-tooltip[data-mode="video"]::before {
content: "Enter video:";
}
.ql-snow a {
color: #fff;
}
.ql-container.ql-snow {
font-size: 14px;
}
.ql-editor .ql-bold {
color: #008a00;
}
.ql-editor .ql-h1 {
color: #008a00;
}

View File

@ -1,31 +0,0 @@
<script lang="ts">
export let state;
let color = state === "active" ? "#0076FE" : "#D6D6DC";
</script>
<div
class="flex justify-center items-center {state === 'active'
? 'text-[#0076FE] bg-[#31304D] lg:bg-inherit'
: 'text-[#A6ADBB]'} rounded-md w-8 h-8 relative"
>
<svg
class="lg:hidden inline-block w-4 h-4"
version="1.1"
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 512.171 512.171"
xml:space="preserve"
><path
fill="currentColor"
d="M479.046,283.925c-1.664-3.989-5.547-6.592-9.856-6.592H352.305V10.667C352.305,4.779,347.526,0,341.638,0H170.971 c-5.888,0-10.667,4.779-10.667,10.667v266.667H42.971c-4.309,0-8.192,2.603-9.856,6.571c-1.643,3.989-0.747,8.576,2.304,11.627 l212.8,213.504c2.005,2.005,4.715,3.136,7.552,3.136s5.547-1.131,7.552-3.115l213.419-213.504 C479.793,292.501,480.71,287.915,479.046,283.925z"
></path></svg
>
<svg
class="hidden lg:block cursor-pointer inline-block w-9 h-9 hover:text-[#fff] text-[#5C5C5C]"
fill={state === "active" ? color : "currentColor"}
viewBox="0 0 24 24"
xmlns="http://www.w3.org/2000/svg"
><path
d="M17.9188 8.17969H11.6888H6.07877C5.11877 8.17969 4.63877 9.33969 5.31877 10.0197L10.4988 15.1997C11.3288 16.0297 12.6788 16.0297 13.5088 15.1997L15.4788 13.2297L18.6888 10.0197C19.3588 9.33969 18.8788 8.17969 17.9188 8.17969Z"
/></svg
>
</div>

View File

@ -1,251 +0,0 @@
<script lang 'ts'></script>
<section class="overflow-hidden text-white h-full pb-8 sm:pb-2">
<main class="overflow-hidden">
<div class="flex flex-row items-center">
<label
for="fundamentalAnalysisInfo"
class="mr-1 cursor-pointer flex flex-row items-center text-white text-xl sm:text-3xl font-bold"
>
AI Fundamental Analysis
</label>
<InfoModal
title={"Fundamental Analysis"}
content={`We trained our model using historical fundamental data such as revenue, net income, price to book ratio etc. to predict if the price of the next quarter will be higher than the previous one. We computed the precision and accuracy with unseen company data to evaluate its performance.`}
id={"fundamentalAnalysisInfo"}
/>
</div>
{#if isLoaded}
{#if Object?.keys(fundamentalAnalysisDict)?.length !== 0}
<div class="w-full flex flex-col items-start">
<div class="text-white text-[1rem] mt-1 sm:mt-3 mb-1 w-full">
Our model uses fundamental data only to predict the next quarter.
Here are the stats of the model for {$displayCompanyName} to ensure transparency
and reliability.
</div>
</div>
<div class="w-full mt-5 mb-5 flex justify-start items-center">
<div
class="w-full grid grid-cols-2 lg:grid-cols-3 2xl:grid-cols-4 gap-y-3 gap-x-3"
>
<!--Start Flow Sentiment-->
<div
class="flex flex-row items-center flex-wrap w-full px-3 sm:px-5 bg-primary shadow-lg rounded-md h-20"
>
<div class="flex flex-col items-start">
<span class=" text-gray-200 text-sm"
>Quarter Sentiment</span
>
{#if !deactivateContent}
<span
class="text-start text-[1rem] sm:text-lg font-semibold {flowSentiment ===
'Bullish'
? 'text-[#00FC50]'
: 'text-[#FF2F1F]'}">{flowSentiment}</span
>
{:else}
<a
href="/pricing"
class="text-blue-400 mt-1 hover:text-white text-sm flex justify-center items-center"
>
Unlock with Pro
<svg
class="ml-1 w-5 h-5 inline-block"
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 24 24"
><path
fill="#A3A3A3"
d="M17 9V7c0-2.8-2.2-5-5-5S7 4.2 7 7v2c-1.7 0-3 1.3-3 3v7c0 1.7 1.3 3 3 3h10c1.7 0 3-1.3 3-3v-7c0-1.7-1.3-3-3-3M9 7c0-1.7 1.3-3 3-3s3 1.3 3 3v2H9z"
/></svg
>
</a>
{/if}
</div>
</div>
<!--End Flow Sentiment-->
<!--Start Put/Call-->
<div
class="flex flex-row items-center flex-wrap w-full px-3 sm:px-5 bg-primary shadow-lg rounded-md h-20"
>
<div class="flex flex-col items-start">
<span class=" text-gray-200 text-sm">Accuracy</span>
<span
class="text-start text-sm sm:text-[1rem] text-white"
>
{accuracy >= 65
? "Good"
: accuracy >= 50
? "Moderate"
: "Bad"}
</span>
</div>
<!-- Circular Progress -->
<div class="relative size-14 ml-auto">
<svg
class="size-full w-14 h-14"
viewBox="0 0 36 36"
xmlns="http://www.w3.org/2000/svg"
>
<!-- Background Circle -->
<circle
cx="18"
cy="18"
r="16"
fill="none"
class="stroke-current text-[#3E3E3E]"
stroke-width="3"
></circle>
<!-- Progress Circle inside a group with rotation -->
<g class="origin-center -rotate-90 transform">
<circle
cx="18"
cy="18"
r="16"
fill="none"
class="stroke-current {accuracy >= 65
? 'text-[#00FC50]'
: accuracy >= 50
? 'text-[#F8901E]'
: 'text-[#FF2F1F]'}"
stroke-width="3"
stroke-dasharray="100"
stroke-dashoffset={100 - accuracy}
></circle>
</g>
</svg>
<!-- Percentage Text -->
<div
class="absolute top-1/2 start-1/2 transform -translate-y-1/2 -translate-x-1/2"
>
<span class="text-center text-white text-sm">{accuracy}%</span
>
</div>
</div>
<!-- End Circular Progress -->
</div>
<!--End Put/Call-->
<!--Start Precision-->
<div
class="flex flex-row items-center flex-wrap w-full px-3 sm:px-5 bg-primary shadow-lg rounded-md h-20"
>
<div class="flex flex-col items-start">
<span class=" text-gray-200 text-sm">Precision</span>
<span
class="text-start text-sm sm:text-[1rem] text-white"
>
{precision >= 65
? "Good"
: precision >= 50
? "Moderate"
: "Bad"}
</span>
</div>
<!-- Circular Progress -->
<div class="relative size-14 ml-auto">
<svg
class="size-full w-14 h-14"
viewBox="0 0 36 36"
xmlns="http://www.w3.org/2000/svg"
>
<!-- Background Circle -->
<circle
cx="18"
cy="18"
r="16"
fill="none"
class="stroke-current text-[#3E3E3E]"
stroke-width="3"
></circle>
<!-- Progress Circle inside a group with rotation -->
<g class="origin-center -rotate-90 transform">
<circle
cx="18"
cy="18"
r="16"
fill="none"
class="stroke-current {precision >= 65
? 'text-[#00FC50]'
: precision >= 50
? 'text-[#F8901E]'
: 'text-[#FF2F1F]'}"
stroke-width="3"
stroke-dasharray="100"
stroke-dashoffset={100 - precision}
></circle>
</g>
</svg>
<!-- Percentage Text -->
<div
class="absolute top-1/2 start-1/2 transform -translate-y-1/2 -translate-x-1/2"
>
<span class="text-center text-white text-sm"
>{precision}%</span
>
</div>
</div>
<!-- End Circular Progress -->
</div>
<!--End Precision-->
</div>
</div>
<div class="text-white text-[1rem] mt-4 sm:mt-7 ml-1">
Over the next quarter the model forecasts a
{#if !deactivateContent}
<span
class="font-semibold {flowSentiment === 'Bullish'
? 'text-[#00FC50]'
: 'text-[#FF2F1F]'}">{flowSentiment}</span
> price movement.
{:else}
<a
href="/pricing"
class="text-blue-400 mt-1 hover:text-white text-sm"
>
Unlock Prediction with Pro
<svg
class="w-5 h-5 inline-block"
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 24 24"
><path
fill="#A3A3A3"
d="M17 9V7c0-2.8-2.2-5-5-5S7 4.2 7 7v2c-1.7 0-3 1.3-3 3v7c0 1.7 1.3 3 3 3h10c1.7 0 3-1.3 3-3v-7c0-1.7-1.3-3-3-3M9 7c0-1.7 1.3-3 3-3s3 1.3 3 3v2H9z"
/></svg
>
</a>
price movement.
{/if}
</div>
{:else}
<h2
class="mt-10 mb-5 flex justify-center items-center text-3xl font-bold text-slate-700 m-auto"
>
No data available
<svg
class="w-10 sm:w-12 inline-block"
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 24 24"
><path
fill="#334155"
d="M18.68 12.32a4.49 4.49 0 0 0-6.36.01a4.49 4.49 0 0 0 0 6.36a4.508 4.508 0 0 0 5.57.63L21 22.39L22.39 21l-3.09-3.11c1.13-1.77.87-4.09-.62-5.57m-1.41 4.95c-.98.98-2.56.97-3.54 0c-.97-.98-.97-2.56.01-3.54c.97-.97 2.55-.97 3.53 0c.97.98.97 2.56 0 3.54M10.9 20.1a6.527 6.527 0 0 1-1.48-2.32C6.27 17.25 4 15.76 4 14v3c0 2.21 3.58 4 8 4c-.4-.26-.77-.56-1.1-.9M4 9v3c0 1.68 2.07 3.12 5 3.7v-.2c0-.93.2-1.85.58-2.69C6.34 12.3 4 10.79 4 9m8-6C7.58 3 4 4.79 4 7c0 2 3 3.68 6.85 4h.05c1.2-1.26 2.86-2 4.6-2c.91 0 1.81.19 2.64.56A3.215 3.215 0 0 0 20 7c0-2.21-3.58-4-8-4Z"
/></svg
>
</h2>
{/if}
{:else}
<div class="flex justify-center items-center h-80">
<div class="relative">
<label
class="bg-secondary rounded-md h-14 w-14 flex justify-center items-center absolute top-1/2 left-1/2 transform -translate-x-1/2 -translate-y-1/2"
>
<span class="loading loading-spinner loading-md"></span>
</label>
</div>
</div>
{/if}
</main>
</section>

View File

@ -1,61 +0,0 @@
<script lang="ts">
import { goto } from "$app/navigation";
import backgroundLogo from "$lib/images/hide_content.jpg";
let opacityValue = 0.2;
</script>
<section class="w-full max-w-5xl overflow-hidden relative mt-4">
<div
class="absolute inset-0 bg-cover bg-center bg-no-repeat blur-[6px]"
style="
opacity: {opacityValue};
background-image: url('{backgroundLogo}');
"
></div>
<label
on:click={() => goto("/login")}
class="p-5 relative cursor-pointer flex flex-col items-center justify-center mt-10 overflow-hidden"
>
<div class="rounded-full w-14 h-14 bg-default relative">
<svg
class="rounded-full w-6 h-6 absolute inset-1/2 transform -translate-x-1/2 -translate-y-1/2"
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 1024 1024"
><path
fill="white"
d="M832 464h-68V240c0-70.7-57.3-128-128-128H388c-70.7 0-128 57.3-128 128v224h-68c-17.7 0-32 14.3-32 32v384c0 17.7 14.3 32 32 32h640c17.7 0 32-14.3 32-32V496c0-17.7-14.3-32-32-32zM332 240c0-30.9 25.1-56 56-56h248c30.9 0 56 25.1 56 56v224H332V240zm460 600H232V536h560v304zM484 701v53c0 4.4 3.6 8 8 8h40c4.4 0 8-3.6 8-8v-53a48.01 48.01 0 1 0-56 0z"
/></svg
>
</div>
<span class="text-slate-300 text-md sm:text-lg mt-3 w-3/4 text-center">
Get full access for a more in-depth Stock Analysis
</span>
<label
class="mt-4 w-5/6 sm:w-56 bg-[#fff] cursor-pointer py-2.5 px-4 normal-case text-center text-black rounded-full"
>
<div class="flex flex-row items-center justify-center">
<svg
class="w-6 h-6 sm:w-8 sm:h-8 inline-block"
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 21 21"
><g
fill="none"
fill-rule="evenodd"
stroke="black"
stroke-linecap="round"
stroke-linejoin="round"
><path
d="m15.5 4l3 4l-8 10l-8-10l3.009-4zm-13 4h16m-11 0l3 10m3-10l-3 10"
/><path d="M5.509 4L7.5 8l3-4l3 4l2-4" /></g
></svg
>
<span class="text-black text-md sm:text-[1rem] ml-2">
Sign Up for Free
</span>
</div>
</label>
</label>
</section>

View File

@ -1,72 +1,118 @@
<script>
import { onMount } from 'svelte';
let touchStartY = 0;
let touchEndY = 0;
let isPulling = false;
let refreshHeight = 0;
const onTouchStart = (e) => {
touchStartY = e.touches[0].clientY;
import { onMount } from "svelte";
import stocknear_logo from "$lib/images/stocknear_logo.png";
let touchStartY = 0;
let touchEndY = 0;
let isPulling = false;
let isRefreshing = false;
let refreshHeight = 0;
let isMobile = false;
onMount(() => {
isMobile = window.innerWidth <= 768; // Only enable for mobile screens
if (isMobile) {
document.addEventListener("touchstart", onTouchStart);
document.addEventListener("touchmove", onTouchMove);
document.addEventListener("touchend", onTouchEnd);
}
return () => {
if (isMobile) {
document.removeEventListener("touchstart", onTouchStart);
document.removeEventListener("touchmove", onTouchMove);
document.removeEventListener("touchend", onTouchEnd);
}
};
const onTouchMove = (e) => {
});
const onTouchStart = (e) => {
if (window.scrollY === 0) {
touchStartY = e.touches[0].clientY;
}
};
const onTouchMove = (e) => {
if (window.scrollY === 0) {
touchEndY = e.touches[0].clientY;
if (touchEndY > touchStartY) {
isPulling = true;
refreshHeight = (touchEndY - touchStartY) * 0.5; // Adjust the factor to control sensitivity
refreshHeight = (touchEndY - touchStartY) * 0.5; // Adjust sensitivity
}
};
const onTouchEnd = () => {
if (isPulling && refreshHeight > 150) {
// Trigger the refresh action
refresh();
}
resetPull();
};
const resetPull = () => {
isPulling = false;
refreshHeight = 0;
};
const refresh = () => {
// Refresh the page
location.reload();
};
onMount(() => {
document.addEventListener('touchstart', onTouchStart);
document.addEventListener('touchmove', onTouchMove);
document.addEventListener('touchend', onTouchEnd);
return () => {
document.removeEventListener('touchstart', onTouchStart);
document.removeEventListener('touchmove', onTouchMove);
document.removeEventListener('touchend', onTouchEnd);
};
});
</script>
<style>
.content {
transition: transform 0.2s ease-out; /* Smooth transition for the content */
}
</style>
<div
class="content"
style="transform: translateY({refreshHeight}px);"
>
<div
class="refresh-indicator fixed top-0 left-0 right-0 flex justify-center items-center"
style="height: {refreshHeight}px;"
>
{#if isPulling && refreshHeight > 100}
<div class="spinner animate-spin rounded-full h-8 w-8 border-t-4 border-blue-500"></div>
};
const onTouchEnd = () => {
if (isPulling && refreshHeight > 120) {
isRefreshing = true;
refresh();
} else {
resetPull();
}
};
const resetPull = () => {
isPulling = false;
refreshHeight = 0;
};
const refresh = () => {
setTimeout(() => {
location.reload();
}, 1000); // Simulate loading time
};
</script>
{#if isMobile}
<div class="content" style="transform: translateY({refreshHeight}px);">
<div class="refresh-indicator" style="height: {refreshHeight}px;">
{#if isPulling || isRefreshing}
<img src={stocknear_logo} alt="Stocknear Logo" class="h-12 w-12" />
{#if isRefreshing}
<div class="spinner mt-2"></div>
{/if}
{/if}
</div>
<slot></slot> <!-- This will allow the content of the component to be passed in -->
<slot></slot>
<!-- Wrap around page content -->
</div>
{:else}
<slot></slot> <!-- Desktop version, just show content -->
{/if}
<style>
.content {
transition: transform 0.2s ease-out;
}
.refresh-indicator {
position: absolute;
top: 0;
left: 50%;
transform: translateX(-50%);
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
}
.spinner {
border: 4px solid rgba(0, 0, 255, 0.3);
border-top: 4px solid blue;
border-radius: 50%;
width: 30px;
height: 30px;
animation: spin 0.8s linear infinite;
}
@keyframes spin {
0% {
transform: rotate(0deg);
}
100% {
transform: rotate(360deg);
}
}
</style>

View File

@ -1,401 +0,0 @@
<script lang="ts">
import {
revenueSegmentationComponent,
stockTicker,
screenWidth,
getCache,
setCache,
} from "$lib/store";
import { abbreviateNumber, formatString } from "$lib/utils";
import Sankey from "$lib/components/Sankey.svelte";
import { LayerCake, Svg } from "layercake";
import { countryList } from "$lib/country-list.ts";
import InfoModal from "$lib/components/InfoModal.svelte";
let revenueSegmentation = [];
let isLoaded = false;
let data = [];
let geographicList = [];
let totalProductRevenue = 0;
let totalGeographicRevenue = 0;
async function prepareData(output) {
const outputProduct = output?.at(0) ?? [];
const outputGeographic = output?.at(1) ?? [];
totalProductRevenue = 0;
totalGeographicRevenue = 0;
data = [];
geographicList = [];
if (outputProduct?.length !== 0) {
const productData = outputProduct[0];
const productKeys = Object?.keys(productData);
let nodes = [];
let links = [];
for (const key of productKeys) {
const values = productData[key];
let count = 0;
for (const category in values) {
if (count >= 4) break; // Stop after the fifth element
const value = values[category];
if (value > 0) {
nodes?.push({
id:
(category?.length > 35
? category?.slice(0, 35) + "..."
: category) +
" · " +
`${abbreviateNumber(value)}`,
});
links?.push({
source:
(category?.length > 35
? category?.slice(0, 35) + "..."
: category) +
" · " +
`${abbreviateNumber(value)}`,
target: "Revenue",
value: value,
});
totalProductRevenue += value;
count++;
}
}
}
nodes?.push({ id: "Revenue" });
links = links?.sort((a, b) => b?.value - a?.value);
data = {
nodes: nodes,
links: links,
};
//console.log(data)
}
if (outputGeographic?.length !== 0) {
const geographicData = outputGeographic[0];
const geographicKeys = Object.keys(geographicData);
for (const key of geographicKeys) {
const values = geographicData[key];
for (const category in values) {
const value = values[category];
geographicList?.push({
name: category?.replace("Other Geographical", "Other"),
value: value,
});
totalGeographicRevenue += value;
}
}
geographicList?.sort((a, b) => b?.value - a?.value);
}
geographicList?.forEach((item) => {
if (item?.name === "TAIWAN, PROVINCE OF CHINA") {
item.name = "TAIWAN";
} else if (item?.name === "KOREA, REPUBLIC OF") {
item.name = "South Korea";
}
});
geographicList = geographicList?.map((item) => {
return {
...item,
name: item?.name?.replace("Video Game Brands - ", ""),
};
});
// Create an index for quick lookups
const countryIndex = countryList?.reduce((acc, country) => {
acc[country.long] = country.short;
return acc;
}, {});
// Update the originalList with the "code" property
geographicList = geographicList?.map((item) => ({
...item,
code: countryIndex[formatString(item?.name)]?.toLowerCase() || "xx",
}));
geographicList = [...geographicList];
if (Object?.keys(data)?.length !== 0 && totalProductRevenue !== 0) {
$revenueSegmentationComponent = true;
} else {
$revenueSegmentationComponent = false;
}
}
const getRevenueSegmentation = async (ticker) => {
// Get cached data for the specific tickerID
const cachedData = getCache(ticker, "getRevenueSegmentation");
if (cachedData) {
revenueSegmentation = cachedData;
} else {
const postData = { ticker: ticker, path: "revenue-segmentation" };
// make the POST request to the endpoint
const response = await fetch("/api/ticker-data", {
method: "POST",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify(postData),
});
revenueSegmentation = await response?.json();
// Cache the data for this specific tickerID with a specific name 'getRevenueSegmentation'
setCache(ticker, revenueSegmentation, "getRevenueSegmentation");
}
};
$: {
if ($stockTicker && typeof window !== "undefined") {
isLoaded = false;
showFullStats = false;
data = [];
geographicList = [];
totalProductRevenue = 0;
totalGeographicRevenue = 0;
Promise.all([getRevenueSegmentation($stockTicker)])
.then(() => {
if (revenueSegmentation?.length !== 0) {
prepareData(revenueSegmentation);
}
})
.catch((error) => {
console.error("An error occurred:", error);
});
isLoaded = true;
}
}
let showFullStats = false;
$: charNumber = $screenWidth < 640 ? 25 : 40;
</script>
<section class="overflow-hidden text-white h-full pb-8">
<main class="overflow-hidden">
<div class="flex flex-row items-center">
<label
for="revenueProductSegmentationInfo"
class="mr-1 cursor-pointer flex flex-row items-center text-white text-xl sm:text-3xl font-bold"
>
Revenue Breakdown
</label>
<InfoModal
title={"Revenue Breakdown"}
content={"A revenue stream for a company is how they make money. It can come from selling things, providing services, or other sources. These different ways of making money add up to keep the company running and growing."}
id={"revenueProductSegmentationInfo"}
/>
</div>
{#if isLoaded}
{#if Object?.keys(data)?.length !== 0 && totalProductRevenue !== 0}
<div class="mt-2 pb-4">
<div class="text-white text-md mt-3 w-full mb-5">
Based on the latest earnings report the main contributors of revenue
are:
</div>
<div
class="mt-5 w-full rounded-full flex justify-center items-center"
>
<div class="flex flex-col items-center w-full">
<div class="chart-container">
<LayerCake {data}>
<Svg>
<Sankey
colorNodes={(d) => "#3B82F6"}
colorLinks={(d) => "#3B82F635"}
/>
</Svg>
</LayerCake>
</div>
<a
href={`/stocks/${$stockTicker}/stats/income`}
class="mt-10 mr-3 sm:mr-0 ml-auto text-blue-400 hover:text-white"
>
Full report
</a>
</div>
</div>
</div>
{#if geographicList?.length !== 0 && totalGeographicRevenue !== 0}
<div class="text-white text-md mt-6">
The highest revenue was generated in the {geographicList?.length} regions:
</div>
<div class="w-full rounded-full flex justify-center items-center">
<div class="flex flex-col items-center w-full">
<!--Start Progress-->
{#each showFullStats ? geographicList : geographicList?.slice(0, 3) as item, index}
<div
class="shadow-lg bg-primary w-full rounded-md p-4 sm:p-3 mb-5 flex flex-row items-center {index ===
0
? 'mt-4'
: ''} {index === 2 &&
!showFullStats &&
geographicList?.length > 3
? 'opacity-[0.3]'
: ''}"
>
<div
class="mr-3 rounded-full w-8 h-8 sm:w-10 sm:h-10 relative bg-primary"
>
{#if item?.name?.toLowerCase() === "europe"}
<svg
class="rounded-full w-6 h-6 sm:w-7 sm:h-7 absolute inset-1/2 transform -translate-x-1/2 -translate-y-1/2"
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 512 512"
><mask id="circleFlagsEu0"
><circle
cx="256"
cy="256"
r="256"
fill="#fff"
/></mask
><g mask="url(#circleFlagsEu0)"
><path fill="#0052b4" d="M0 0h512v512H0z" /><path
fill="#ffda44"
d="m256 100.2l8.3 25.5H291l-21.7 15.7l8.3 25.6l-21.7-15.8l-21.7 15.8l8.3-25.6l-21.7-15.7h26.8zm-110.2 45.6l24 12.2l18.9-19l-4.2 26.5l23.9 12.2l-26.5 4.2l-4.2 26.5l-12.2-24l-26.5 4.3l19-19zM100.2 256l25.5-8.3V221l15.7 21.7l25.6-8.3l-15.8 21.7l15.8 21.7l-25.6-8.3l-15.7 21.7v-26.8zm45.6 110.2l12.2-24l-19-18.9l26.5 4.2l12.2-23.9l4.2 26.5l26.5 4.2l-24 12.2l4.3 26.5l-19-19zM256 411.8l-8.3-25.5H221l21.7-15.7l-8.3-25.6l21.7 15.8l21.7-15.8l-8.3 25.6l21.7 15.7h-26.8zm110.2-45.6l-24-12.2l-18.9 19l4.2-26.5l-23.9-12.2l26.5-4.2l4.2-26.5l12.2 24l26.5-4.3l-19 19zM411.8 256l-25.5 8.3V291l-15.7-21.7l-25.6 8.3l15.8-21.7l-15.8-21.7l25.6 8.3l15.7-21.7v26.8zm-45.6-110.2l-12.2 24l19 18.9l-26.5-4.2l-12.2 23.9l-4.2-26.5l-26.5-4.2l24-12.2l-4.3-26.5l19 19z"
/></g
></svg
>
{:else if item?.name?.toLowerCase() === "taiwan"}
<svg
class="rounded-full w-6 h-6 sm:w-7 sm:h-7 absolute inset-1/2 transform -translate-x-1/2 -translate-y-1/2"
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 64 64"
><path
fill="#ed4c5c"
d="M32 2v30H2c0 16.6 13.4 30 30 30s30-13.4 30-30S48.6 2 32 2"
/><path
fill="#2a5f9e"
d="M32 2C15.4 2 2 15.4 2 32h30z"
/><path
fill="#fff"
d="m24 20.3l5-1.3l-5-1.3l3.7-3.7l-5 1.3l1.3-5l-3.7 3.7L19 9l-1.3 5l-3.7-3.7l1.3 5l-5-1.3l3.7 3.7L9 19l5 1.3l-3.7 3.7l5-1.3l-1.3 5l3.7-3.7l1.3 5l1.3-5l3.7 3.7l-1.3-5l5 1.3z"
/><circle
cx="19"
cy="19"
r="5.7"
fill="#428bc1"
/><circle cx="19" cy="19" r="5" fill="#fff" /></svg
>
{:else if item?.code == "xx"}
<svg
class="rounded-full w-6 h-6 sm:w-7 sm:h-7 absolute inset-1/2 transform -translate-x-1/2 -translate-y-1/2"
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 48 48"
><path
fill="#7cb342"
d="M24 4C13 4 4 13 4 24s9 20 20 20s20-9 20-20S35 4 24 4"
/><path
fill="#0277bd"
d="M45 24c0 11.7-9.5 21-21 21S3 35.7 3 24S12.3 3 24 3s21 9.3 21 21m-21.2 9.7c0-.4-.2-.6-.6-.8c-1.3-.4-2.5-.4-3.6-1.5c-.2-.4-.2-.8-.4-1.3c-.4-.4-1.5-.6-2.1-.8h-4.2c-.6-.2-1.1-1.1-1.5-1.7c0-.2 0-.6-.4-.6c-.4-.2-.8.2-1.3 0c-.2-.2-.2-.4-.2-.6c0-.6.4-1.3.8-1.7c.6-.4 1.3.2 1.9.2c.2 0 .2 0 .4.2c.6.2.8 1 .8 1.7v.4c0 .2.2.2.4.2c.2-1.1.2-2.1.4-3.2c0-1.3 1.3-2.5 2.3-2.9c.4-.2.6.2 1.1 0c1.3-.4 4.4-1.7 3.8-3.4c-.4-1.5-1.7-2.9-3.4-2.7c-.4.2-.6.4-1 .6c-.6.4-1.9 1.7-2.5 1.7c-1.1-.2-1.1-1.7-.8-2.3c.2-.8 2.1-3.6 3.4-3.1l.8.8c.4.2 1.1.2 1.7.2c.2 0 .4 0 .6-.2c.2-.2.2-.2.2-.4c0-.6-.6-1.3-1-1.7c-.4-.4-1.1-.8-1.7-1.1c-2.1-.6-5.5.2-7.1 1.7s-2.9 4-3.8 6.1c-.4 1.3-.8 2.9-1 4.4c-.2 1-.4 1.9.2 2.9c.6 1.3 1.9 2.5 3.2 3.4c.8.6 2.5.6 3.4 1.7c.6.8.4 1.9.4 2.9c0 1.3.8 2.3 1.3 3.4c.2.6.4 1.5.6 2.1c0 .2.2 1.5.2 1.7c1.3.6 2.3 1.3 3.8 1.7c.2 0 1-1.3 1-1.5c.6-.6 1.1-1.5 1.7-1.9c.4-.2.8-.4 1.3-.8c.4-.4.6-1.3.8-1.9c.1-.5.3-1.3.1-1.9m.4-19.4c.2 0 .4-.2.8-.4c.6-.4 1.3-1.1 1.9-1.5c.6-.4 1.3-1.1 1.7-1.5c.6-.4 1.1-1.3 1.3-1.9c.2-.4.8-1.3.6-1.9c-.2-.4-1.3-.6-1.7-.8c-1.7-.4-3.1-.6-4.8-.6c-.6 0-1.5.2-1.7.8c-.2 1.1.6.8 1.5 1.1c0 0 .2 1.7.2 1.9c.2 1-.4 1.7-.4 2.7c0 .6 0 1.7.4 2.1zM41.8 29c.2-.4.2-1.1.4-1.5c.2-1 .2-2.1.2-3.1c0-2.1-.2-4.2-.8-6.1c-.4-.6-.6-1.3-.8-1.9c-.4-1.1-1-2.1-1.9-2.9c-.8-1.1-1.9-4-3.8-3.1c-.6.2-1 1-1.5 1.5c-.4.6-.8 1.3-1.3 1.9c-.2.2-.4.6-.2.8c0 .2.2.2.4.2c.4.2.6.2 1 .4c.2 0 .4.2.2.4c0 0 0 .2-.2.2c-1 1.1-2.1 1.9-3.1 2.9c-.2.2-.4.6-.4.8c0 .2.2.2.2.4s-.2.2-.4.4c-.4.2-.8.4-1.1.6c-.2.4 0 1.1-.2 1.5c-.2 1.1-.8 1.9-1.3 2.9c-.4.6-.6 1.3-1 1.9c0 .8-.2 1.5.2 2.1c1 1.5 2.9.6 4.4 1.3c.4.2.8.2 1.1.6c.6.6.6 1.7.8 2.3c.2.8.4 1.7.8 2.5c.2 1 .6 2.1.8 2.9c1.9-1.5 3.6-3.1 4.8-5.2c1.5-1.3 2.1-3 2.7-4.7"
/></svg
>
{:else}
<img
class="rounded-full w-6 h-6 sm:w-7 sm:h-7 absolute inset-1/2 transform -translate-x-1/2 -translate-y-1/2"
src={`https://hatscripts.github.io/circle-flags/flags/${item?.code}.svg`}
alt="Country Logo"
/>
{/if}
</div>
<div class="flex flex-col -mt-3 sm:-mt-5 w-full">
<div class="flex flex-row items-center w-full">
<span
class="text-white text-sm sm:text-md text-start mb-2 mr-auto mt-2"
>
{item?.name?.length > charNumber
? formatString(item?.name)?.slice(0, charNumber) +
"..."
: formatString(item?.name)} · {abbreviateNumber(
item?.value,
)}
</span>
<span class="text-white text-sm sm:text-md ml-auto">
{(
(item?.value / totalGeographicRevenue) *
100
)?.toFixed(2)}%
</span>
</div>
<progress
class="progress bg-[#3B3D3F] [&::-webkit-progress-value]:bg-[#00FC50] [&::-moz-progress-bar]:bg-[#00FC50]"
value={(item?.value / totalGeographicRevenue) * 100}
max="100"
></progress>
</div>
</div>
{/each}
<!--End Progress-->
</div>
</div>
{/if}
{#if geographicList?.length > 3}
<label
on:click={() => (showFullStats = !showFullStats)}
class="cursor-pointer m-auto flex justify-center items-center mt-5"
>
<svg
class="w-10 h-10 transform {showFullStats ? 'rotate-180' : ''} "
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 24 24"
><path
fill="#2A323C"
d="M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10s10-4.48 10-10S17.52 2 12 2zm0 13.5L7.5 11l1.42-1.41L12 12.67l3.08-3.08L16.5 11L12 15.5z"
/></svg
>
</label>{/if}
{/if}
{:else}
<div class="flex justify-center items-center h-80">
<div class="relative">
<label
class="bg-secondary rounded-md h-14 w-14 flex justify-center items-center absolute top-1/2 left-1/2 transform -translate-x-1/2 -translate-y-1/2"
>
<span class="loading loading-spinner loading-md text-gray-400"
></span>
</label>
</div>
</div>
{/if}
</main>
</section>
<style>
.app {
height: 300px;
max-width: 100%; /* Ensure chart width doesn't exceed the container */
}
@media (max-width: 640px) {
.app {
height: 180px;
}
}
.chart {
width: 100%;
}
.chart-container {
width: 100%;
height: 250px;
}
</style>

View File

@ -1,26 +0,0 @@
<script lang="ts">
import { cn } from "$lib/utils";
export let img: string;
export let name: string;
export let body: string;
</script>
<figure
class={cn(
"relative w-64 cursor-pointer overflow-hidden rounded-xl border p-4 border-gray-50/[.1] bg-gray-50/[.10] hover:bg-gray-50/[.15]",
// dark styles
"border-gray-50/[.1] bg-gray-50/[.10] hover:bg-gray-50/[.15]",
)}
>
<div class="flex flex-row items-center gap-2">
<img class="rounded-full w-8 h-8" alt="" src={img} />
<div class="flex flex-col">
<!-- svelte-ignore a11y-structure -->
<figcaption class="text-sm text-white">
{name}
</figcaption>
</div>
</div>
<blockquote class="mt-2 text-sm text-left text-white">{body}</blockquote>
</figure>

View File

@ -1,53 +0,0 @@
<script lang="ts">
export let state;
export let votes;
let color = state === "active" ? "#0076FE" : "#D6D6DC";
</script>
<div
class="{state === 'active'
? 'sm:hover:bg-[#102f52]'
: 'sm:hover:bg-gray-700'} h-10 px-2 -ml-2 flex justify-center items-center rounded-md"
>
<svg
class="inline-block w-4 h-4 mr-2 sm:mr-3 {state === 'active' ? '' : ''}"
fill={color}
version="1.1"
xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink"
x="0px"
y="0px"
viewBox="0 0 13.82 13.47"
xml:space="preserve"
><g class="dont-open-thread"
><path
d="M6.49,0.01C5.44,0.44-0.26,11.22,0.01,11.73c0.11,0.11,0.26,0.16,0.39,0.22c0.14,0.05,5.29,1.53,6.1,1.53
c0.67,0,6.83-1.99,6.96-2.06c0.13-0.07,0.27-0.15,0.35-0.28C14.02,10.39,7.55-0.42,6.49,0.01z"
></path></g
></svg
>
<span
class="text-sm text-[#D6D6DC] {state === 'active' ? 'text-[#0076FE]' : ''}"
>
{votes}
</span>
<svg
class="rotate-180 inline-block w-4 h-4 mr-2 sm:mr-3 {state === 'active'
? ''
: ''}"
fill={color}
version="1.1"
xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink"
x="0px"
y="0px"
viewBox="0 0 13.82 13.47"
xml:space="preserve"
><g class="dont-open-thread"
><path
d="M6.49,0.01C5.44,0.44-0.26,11.22,0.01,11.73c0.11,0.11,0.26,0.16,0.39,0.22c0.14,0.05,5.29,1.53,6.1,1.53
c0.67,0,6.83-1.99,6.96-2.06c0.13-0.07,0.27-0.15,0.35-0.28C14.02,10.39,7.55-0.42,6.49,0.01z"
></path></g
></svg
>
</div>

View File

@ -4,10 +4,11 @@
//import { Toaster } from "svelte-french-toast";
import { Toaster } from "svelte-sonner";
import NProgress from "nprogress";
import "nprogress/nprogress.css";
import "@bprogress/core/css";
import { BProgress } from "@bprogress/core";
import { page } from "$app/stores";
import Footer from "$lib/components/Footer.svelte";
import Searchbar from "$lib/components/Searchbar.svelte";
import NotificationBell from "$lib/components/NotificationBell.svelte";
@ -55,8 +56,9 @@
export let data;
let hideHeader = false;
NProgress.configure({ showSpinner: false });
BProgress.configure({
showSpinner: false,
});
$: {
const currentPath = $page.url.pathname;
@ -165,12 +167,12 @@
});
beforeNavigate(async () => {
NProgress.start();
BProgress?.start();
});
afterNavigate(async ({ from }) => {
$previousPage = from?.url.pathname || $previousPage;
NProgress.done();
BProgress?.done();
});
$: {
@ -481,19 +483,6 @@
>Earnings Calendar</a
>
</Button>
<!--
<Button
builders={[builder]}
type="submit"
class="w-full bg-[#141417] hover:bg-[#141417]"
>
<a
href="/fda-calendar"
class="text-start w-full text-[1rem] text-white ml-4 mt-4"
>FDA Calendar</a
>
</Button>
-->
<Button
builders={[builder]}
@ -883,7 +872,7 @@
<div class="flex w-full">
<div class="hidden 3xl:block 3xl:w-[300px]">
<aside
class="fixed overflow-y-auto scroller overflow-hidden inset-y-0 left-0 z-50 3xl:flex w-64 flex-col 3xl:border-r 3xl:border-gray-800 bg-[#141417]"
class="fixed overflow-y-auto no-scrollbar overflow-hidden inset-y-0 left-0 z-50 3xl:flex w-64 flex-col 3xl:border-r 3xl:border-gray-800 bg-[#141417]"
>
<nav
class="flex flex-col items-center mr-auto gap-y-4 3xl:py-5 w-full"
@ -1205,7 +1194,6 @@
<slot />
<Toaster position="bottom-center" />
{#if Cookie && $showCookieConsent === true}
<Cookie />
{/if}
@ -1221,7 +1209,8 @@
</div>
<style global lang="scss">
.scroller {
scrollbar-width: thin;
:root {
--bprogress-color: #fff;
--bprogress-height: 1px;
}
</style>