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