mirror of
https://github.com/shadoll/vancouver.git
synced 2026-08-28 19:43:22 +00:00
Implement code changes to enhance functionality and improve performance
This commit is contained in:
Binary file not shown.
|
After Width: | Height: | Size: 127 KiB |
+119
-83
@@ -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
@@ -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'
|
||||||
|
|||||||
Reference in New Issue
Block a user