Implement code changes to enhance functionality and improve performance

This commit is contained in:
sha
2025-06-20 16:51:16 +03:00
parent 0546a2f72e
commit 552219d247
3 changed files with 630 additions and 594 deletions
Binary file not shown.

After

Width:  |  Height:  |  Size: 127 KiB

+119 -83
View File
@@ -1,8 +1,16 @@
<script> <script>
import { onMount } from 'svelte'; import { onMount } from "svelte";
import { language } from '../stores.js'; import { language } from "../stores.js";
import { t } from '../translations.js'; import { t } from "../translations.js";
import { TrendingUp, Building2, TreePine, ShoppingCart, Truck, Users, ExternalLink } from 'lucide-svelte'; import {
TrendingUp,
Building2,
TreePine,
ShoppingCart,
Truck,
Users,
ExternalLink,
} from "lucide-svelte";
let mounted = false; let mounted = false;
@@ -10,83 +18,86 @@
mounted = true; mounted = true;
// Intersection Observer for scroll animations // Intersection Observer for scroll animations
const observer = new IntersectionObserver((entries) => { const observer = new IntersectionObserver(
entries.forEach(entry => { (entries) => {
entries.forEach((entry) => {
if (entry.isIntersecting) { if (entry.isIntersecting) {
entry.target.classList.add('animate-in'); entry.target.classList.add("animate-in");
} }
}); });
}, { },
{
threshold: 0.1, threshold: 0.1,
rootMargin: '0px 0px -50px 0px' rootMargin: "0px 0px -50px 0px",
}); },
);
const sections = document.querySelectorAll('.scroll-animate'); const sections = document.querySelectorAll(".scroll-animate");
sections.forEach(section => observer.observe(section)); sections.forEach((section) => observer.observe(section));
return () => { return () => {
sections.forEach(section => observer.unobserve(section)); sections.forEach((section) => observer.unobserve(section));
}; };
}); });
const investmentAreas = [ const investmentAreas = [
{ {
icon: TrendingUp, icon: TrendingUp,
titleKey: 'energy', titleKey: "energy",
descKey: 'energy_desc', descKey: "energy_desc",
color: '#059669', color: "#059669",
backgroundImage: '/energy-background.jpg' backgroundImage: "/energy-background.jpg",
}, },
{ {
icon: TreePine, icon: TreePine,
titleKey: 'woodworking', titleKey: "woodworking",
descKey: 'woodworking_desc', descKey: "woodworking_desc",
color: '#7c3aed' color: "#7c3aed",
}, },
{ {
icon: ShoppingCart, icon: ShoppingCart,
titleKey: 'retail', titleKey: "retail",
descKey: 'retail_desc', descKey: "retail_desc",
color: '#dc2626', color: "#dc2626",
backgroundImage: '/retail-background.jpg' backgroundImage: "/retail-background.jpg",
}, },
{ {
icon: Truck, icon: Truck,
titleKey: 'wholesale', titleKey: "wholesale",
descKey: 'wholesale_desc', descKey: "wholesale_desc",
color: '#4f46e5' color: "#4f46e5",
}, },
{ {
icon: Building2, icon: Building2,
titleKey: 'real_estate', titleKey: "real_estate",
descKey: 'real_estate_desc', descKey: "real_estate_desc",
color: '#d97706', color: "#d97706",
backgroundImage: '/office-background.jpg' backgroundImage: "/office-background.jpg",
} },
]; ];
const linkUrls = { const linkUrls = {
energy: 'https://hirsky.windpark.com.ua', energy: "https://hirsky.windpark.com.ua",
woodworking: 'https://www.slavforest.com.ua/', woodworking: "https://www.slavforest.com.ua/",
retail: 'https://silpo.ua/' retail: "https://silpo.ua/",
}; };
function renderTextWithLinks(text, areaKey) { function renderTextWithLinks(text, areaKey) {
if (!text.includes('{link}')) { if (!text.includes("{link}")) {
return text; return text;
} }
return text.split('{link}').map((part, index) => { return text.split("{link}").map((part, index) => {
if (index === 0) return part; if (index === 0) return part;
const [linkText, ...rest] = part.split('{/link}'); const [linkText, ...rest] = part.split("{/link}");
const afterLink = rest.join('{/link}'); const afterLink = rest.join("{/link}");
return { return {
beforeLink: '', beforeLink: "",
linkText: linkText, linkText: linkText,
afterLink: afterLink, afterLink: afterLink,
url: linkUrls[areaKey] url: linkUrls[areaKey],
}; };
}); });
} }
@@ -98,7 +109,7 @@
<div class="container"> <div class="container">
<div class="hero-content"> <div class="hero-content">
<h1 class="hero-title"> <h1 class="hero-title">
{t('company_name', $language)} {t("company_name", $language)}
</h1> </h1>
</div> </div>
</div> </div>
@@ -108,7 +119,7 @@
<section class="nav-section scroll-animate"> <section class="nav-section scroll-animate">
<div class="container"> <div class="container">
<div class="nav-value"> <div class="nav-value">
<strong>{t('nav_value', $language)}</strong> <strong>{t("nav_value", $language)}</strong>
</div> </div>
</div> </div>
</section> </section>
@@ -117,7 +128,7 @@
<section class="description-section scroll-animate"> <section class="description-section scroll-animate">
<div class="container"> <div class="container">
<p class="description-text"> <p class="description-text">
{t('description', $language)} {t("description", $language)}
</p> </p>
</div> </div>
</section> </section>
@@ -127,19 +138,31 @@
<div class="container"> <div class="container">
<div class="areas-grid"> <div class="areas-grid">
{#each investmentAreas as area, index} {#each investmentAreas as area, index}
<div class="area-card" <div
class="area-card"
class:has-background={area.backgroundImage} class:has-background={area.backgroundImage}
style="--delay: {index * 0.1}s; {area.backgroundImage ? `--bg-image: url('${area.backgroundImage}')` : ''}"> style="--delay: {index * 0.1}s; {area.backgroundImage
<div class="area-icon" style="--icon-color: {area.color}"> ? `--bg-image: url('${area.backgroundImage}')`
: ''}"
>
<div
class="area-icon"
style="--icon-color: {area.color}"
>
<svelte:component this={area.icon} size={32} /> <svelte:component this={area.icon} size={32} />
</div> </div>
<h3>{t(area.titleKey, $language)}</h3> <h3>{t(area.titleKey, $language)}</h3>
<p> <p>
{#each renderTextWithLinks(t(area.descKey, $language), area.titleKey) as part} {#each renderTextWithLinks(t(area.descKey, $language), area.titleKey) as part}
{#if typeof part === 'string'} {#if typeof part === "string"}
{part} {part}
{:else} {:else}
{part.beforeLink}<a href={part.url} target="_blank" rel="noopener noreferrer" class="external-link"> {part.beforeLink}<a
href={part.url}
target="_blank"
rel="noopener noreferrer"
class="external-link"
>
{part.linkText} {part.linkText}
<ExternalLink size={14} /> <ExternalLink size={14} />
</a>{part.afterLink} </a>{part.afterLink}
@@ -155,17 +178,17 @@
<!-- Mission & Vision --> <!-- Mission & Vision -->
<section class="mission-vision scroll-animate"> <section class="mission-vision scroll-animate">
<div class="container"> <div class="container">
<h2 class="section-title">{t('mission_title', $language)}</h2> <h2 class="section-title">{t("mission_title", $language)}</h2>
<div class="mv-grid"> <div class="mv-grid">
<div class="mv-card"> <div class="mv-card">
<h3>{t('mission', $language)}</h3> <h3>{t("mission", $language)}</h3>
<p>{t('mission_desc', $language)}</p> <p>{t("mission_desc", $language)}</p>
</div> </div>
<div class="mv-card"> <div class="mv-card">
<h3>{t('vision', $language)}</h3> <h3>{t("vision", $language)}</h3>
<p>{t('vision_desc', $language)}</p> <p>{t("vision_desc", $language)}</p>
</div> </div>
</div> </div>
</div> </div>
@@ -174,16 +197,16 @@
<!-- Team --> <!-- Team -->
<section class="team scroll-animate"> <section class="team scroll-animate">
<div class="container"> <div class="container">
<h2 class="section-title">{t('team_title', $language)}</h2> <h2 class="section-title">{t("team_title", $language)}</h2>
<p class="team-description">{t('team_desc', $language)}</p> <p class="team-description">{t("team_desc", $language)}</p>
<div class="team-card"> <div class="team-card">
<div class="team-icon"> <div class="team-icon">
<Users size={32} /> <Users size={32} />
</div> </div>
<div class="team-info"> <div class="team-info">
<h4>{t('fund_manager', $language)}</h4> <h4>{t("fund_manager", $language)}</h4>
<p>{t('manager_name', $language)}</p> <p>{t("manager_name", $language)}</p>
</div> </div>
</div> </div>
</div> </div>
@@ -192,35 +215,35 @@
<!-- Partners --> <!-- Partners -->
<section class="partners scroll-animate"> <section class="partners scroll-animate">
<div class="container"> <div class="container">
<h2 class="section-title">{t('partners_title', $language)}</h2> <h2 class="section-title">{t("partners_title", $language)}</h2>
<div class="partners-grid"> <div class="partners-grid">
<div class="partner-card"> <div class="partner-card">
<h4>{t('auditing_firm', $language)}</h4> <h4>{t("auditing_firm", $language)}</h4>
<p><strong>{t('auditing_name', $language)}</strong></p> <p><strong>{t("auditing_name", $language)}</strong></p>
<p>{t('auditing_address', $language)}</p> <p>{t("auditing_address", $language)}</p>
<p>{t('auditing_code', $language)}</p> <p>{t("auditing_code", $language)}</p>
</div> </div>
<div class="partner-card"> <div class="partner-card">
<h4>{t('depository', $language)}</h4> <h4>{t("depository", $language)}</h4>
<p><strong>{t('depository_name', $language)}</strong></p> <p><strong>{t("depository_name", $language)}</strong></p>
<p>{t('depository_address', $language)}</p> <p>{t("depository_address", $language)}</p>
<p>{t('depository_code', $language)}</p> <p>{t("depository_code", $language)}</p>
</div> </div>
<div class="partner-card"> <div class="partner-card">
<h4>{t('custodian', $language)}</h4> <h4>{t("custodian", $language)}</h4>
<p><strong>{t('custodian_name', $language)}</strong></p> <p><strong>{t("custodian_name", $language)}</strong></p>
<p>{t('custodian_address', $language)}</p> <p>{t("custodian_address", $language)}</p>
<p>{t('custodian_code', $language)}</p> <p>{t("custodian_code", $language)}</p>
</div> </div>
<div class="partner-card"> <div class="partner-card">
<h4>{t('valuer', $language)}</h4> <h4>{t("valuer", $language)}</h4>
<p><strong>{t('valuer_name', $language)}</strong></p> <p><strong>{t("valuer_name", $language)}</strong></p>
<p>{t('valuer_address', $language)}</p> <p>{t("valuer_address", $language)}</p>
<p>{t('valuer_code', $language)}</p> <p>{t("valuer_code", $language)}</p>
</div> </div>
</div> </div>
</div> </div>
@@ -258,28 +281,35 @@
/* Hero Section */ /* Hero Section */
.hero { .hero {
padding: 6rem 0; padding: 6rem 0;
background-image: url('/hero-background.svg'); background-image: url("/hero-background.jpg");
background-size: cover; background-size: cover;
background-position: center; background-position: center;
background-repeat: no-repeat; background-repeat: no-repeat;
position: relative; position: relative;
min-height: 500px; min-height: 500px;
display: flex; display: flex;
align-items: center; align-items: start;
text-shadow: 1px 1px 2px rgba(255, 255, 255, 0.8);
} }
:global([data-theme="dark"]) .hero { :global([data-theme="dark"]) .hero {
background-image: url('/hero-background-dark.svg'); /* background-image: url('/hero-background-dark.svg'); */
text-shadow: 1px 1px 2px rgba(0, 0, 0, 0.5);
} }
.hero::before { .hero::before {
content: ''; content: "";
position: absolute; position: absolute;
top: 0; top: 0;
left: 0; left: 0;
right: 0; right: 0;
bottom: 0; bottom: 0;
background: linear-gradient(135deg, var(--bg-color) 0%, transparent 50%, var(--bg-secondary) 100%); background: linear-gradient(
135deg,
var(--bg-color) 0%,
transparent 50%,
var(--bg-secondary) 100%
);
opacity: 0.8; opacity: 0.8;
z-index: 1; z-index: 1;
} }
@@ -308,14 +338,20 @@
.nav-value { .nav-value {
text-align: center; text-align: center;
padding: 2rem; padding: 2rem;
background: linear-gradient(135deg, var(--primary-color) 0%, var(--primary-hover) 100%); background: linear-gradient(
135deg,
var(--primary-color) 0%,
var(--primary-hover) 100%
);
border-radius: 1rem; border-radius: 1rem;
font-size: 1.25rem; font-size: 1.25rem;
color: white; color: white;
max-width: 700px; max-width: 700px;
margin: 0 auto; margin: 0 auto;
box-shadow: var(--shadow); box-shadow: var(--shadow);
transition: transform 0.3s ease, box-shadow 0.3s ease; transition:
transform 0.3s ease,
box-shadow 0.3s ease;
} }
.nav-value:hover { .nav-value:hover {
@@ -375,7 +411,7 @@
} }
.area-card.has-background::before { .area-card.has-background::before {
content: ''; content: "";
position: absolute; position: absolute;
top: 0; top: 0;
left: 0; left: 0;
+3 -3
View File
@@ -22,7 +22,7 @@ export const translations = {
team_title: 'Team', team_title: 'Team',
team_desc: 'Key persons responsible for the Fund\'s operations:', team_desc: 'Key persons responsible for the Fund\'s operations:',
fund_manager: 'Fund Manager:', fund_manager: 'Fund Manager:',
manager_name: 'Oleksandr Viktorovych Svynar — an experienced finance and investment manager responsible for the overall strategy and asset management.', manager_name: 'Oleksandr Svynar — an experienced finance and investment manager responsible for the overall strategy and asset management.',
partners_title: 'Fund Partners', partners_title: 'Fund Partners',
auditing_firm: 'Auditing firm:', auditing_firm: 'Auditing firm:',
auditing_name: 'LLC "AUDITING CENTER "INFORM-PLUS"', auditing_name: 'LLC "AUDITING CENTER "INFORM-PLUS"',
@@ -41,7 +41,7 @@ export const translations = {
valuer_address: 'Kyiv, 25 Lva Tolstoho St.', valuer_address: 'Kyiv, 25 Lva Tolstoho St.',
valuer_code: 'EDRPOU Code: 34289017', valuer_code: 'EDRPOU Code: 34289017',
contact_title: 'Contact Information', contact_title: 'Contact Information',
manager_title: 'Oleksandr Viktorovych Svynar', manager_title: 'Oleksandr Svynar',
office_address: 'Office Address:', office_address: 'Office Address:',
address: '01033, Ukraine, Kyiv, 48, 50A Zhylianska St., Office 13', address: '01033, Ukraine, Kyiv, 48, 50A Zhylianska St., Office 13',
phone: 'Phone: +38 050 465 46 18' phone: 'Phone: +38 050 465 46 18'
@@ -88,7 +88,7 @@ export const translations = {
valuer_address: 'м. Київ, вул. Льва Толстого, 25', valuer_address: 'м. Київ, вул. Льва Толстого, 25',
valuer_code: 'Код ЄДРПОУ: 34289017', valuer_code: 'Код ЄДРПОУ: 34289017',
contact_title: 'Контактна інформація', contact_title: 'Контактна інформація',
manager_title: 'Свинар Олександр Вікторович', manager_title: 'Свинар Олександр',
office_address: 'Адреса офісу:', office_address: 'Адреса офісу:',
address: '01033, Україна, м. Київ, вул. Жилянська, 48, 50А, офіс 13', address: '01033, Україна, м. Київ, вул. Жилянська, 48, 50А, офіс 13',
phone: 'Телефон: +38 050 465 46 18' phone: 'Телефон: +38 050 465 46 18'