added phone number and updated some things
This commit is contained in:
@@ -1,5 +1,5 @@
|
|||||||
import Link from "next/link";
|
import Link from "next/link";
|
||||||
import { Mail } from "lucide-react";
|
import { Mail, Phone } from "lucide-react";
|
||||||
import { FaLinkedin } from "react-icons/fa6";
|
import { FaLinkedin } from "react-icons/fa6";
|
||||||
import { SiGitea } from "react-icons/si";
|
import { SiGitea } from "react-icons/si";
|
||||||
import type { Locale, Dictionary } from "@/lib/dictionaries";
|
import type { Locale, Dictionary } from "@/lib/dictionaries";
|
||||||
@@ -23,6 +23,7 @@ export default function Footer({ locale, dict }: FooterProps) {
|
|||||||
[dict.footer.connect]: [
|
[dict.footer.connect]: [
|
||||||
{ label: "Source Code", href: "https://git.ksan.dev/ksan", external: true },
|
{ label: "Source Code", href: "https://git.ksan.dev/ksan", external: true },
|
||||||
{ label: "Email", href: "mailto:contact@ksan.dev", external: true },
|
{ label: "Email", href: "mailto:contact@ksan.dev", external: true },
|
||||||
|
{ label: "+387 66 644 094", href: "tel:+38766644094", external: true },
|
||||||
{ label: "LinkedIn", href: "https://www.linkedin.com/in/%C4%91or%C4%91e-k%C5%A1an-886871266", external: true },
|
{ label: "LinkedIn", href: "https://www.linkedin.com/in/%C4%91or%C4%91e-k%C5%A1an-886871266", external: true },
|
||||||
],
|
],
|
||||||
};
|
};
|
||||||
@@ -30,6 +31,7 @@ export default function Footer({ locale, dict }: FooterProps) {
|
|||||||
const socials = [
|
const socials = [
|
||||||
{ icon: SiGitea, href: "https://git.ksan.dev/ksan", label: "Gitea" },
|
{ icon: SiGitea, href: "https://git.ksan.dev/ksan", label: "Gitea" },
|
||||||
{ icon: Mail, href: "mailto:contact@ksan.dev", label: "Email" },
|
{ icon: Mail, href: "mailto:contact@ksan.dev", label: "Email" },
|
||||||
|
{ icon: Phone, href: "tel:+38766644094", label: "Phone" },
|
||||||
{ icon: FaLinkedin, href: "https://www.linkedin.com/in/%C4%91or%C4%91e-k%C5%A1an-886871266/", label: "LinkedIn" },
|
{ icon: FaLinkedin, href: "https://www.linkedin.com/in/%C4%91or%C4%91e-k%C5%A1an-886871266/", label: "LinkedIn" },
|
||||||
];
|
];
|
||||||
|
|
||||||
@@ -84,8 +86,8 @@ export default function Footer({ locale, dict }: FooterProps) {
|
|||||||
{"external" in link && link.external ? (
|
{"external" in link && link.external ? (
|
||||||
<a
|
<a
|
||||||
href={link.href}
|
href={link.href}
|
||||||
target="_blank"
|
target={link.href.startsWith("http") ? "_blank" : undefined}
|
||||||
rel="noopener noreferrer"
|
rel={link.href.startsWith("http") ? "noopener noreferrer" : undefined}
|
||||||
className="text-sm text-text-secondary transition-colors hover:text-text-primary"
|
className="text-sm text-text-secondary transition-colors hover:text-text-primary"
|
||||||
>
|
>
|
||||||
{link.label}
|
{link.label}
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ import { SiGitea } from "react-icons/si";
|
|||||||
import {
|
import {
|
||||||
ArrowRight,
|
ArrowRight,
|
||||||
Mail,
|
Mail,
|
||||||
|
Phone,
|
||||||
MapPin,
|
MapPin,
|
||||||
Clock,
|
Clock,
|
||||||
Send,
|
Send,
|
||||||
@@ -74,6 +75,12 @@ export default function ContactForm({ dict }: ContactFormProps) {
|
|||||||
value: "contact@ksan.dev",
|
value: "contact@ksan.dev",
|
||||||
href: "mailto:contact@ksan.dev",
|
href: "mailto:contact@ksan.dev",
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
icon: Phone,
|
||||||
|
label: t.phoneLabel,
|
||||||
|
value: "+387 66 644 094",
|
||||||
|
href: "tel:+38766644094",
|
||||||
|
},
|
||||||
{
|
{
|
||||||
icon: SiGitea,
|
icon: SiGitea,
|
||||||
label: "Source Code",
|
label: "Source Code",
|
||||||
|
|||||||
@@ -14,7 +14,7 @@ interface HeroProps {
|
|||||||
export default function Hero({ locale, dict }: HeroProps) {
|
export default function Hero({ locale, dict }: HeroProps) {
|
||||||
const stats = [
|
const stats = [
|
||||||
{ value: "13+", label: dict.hero.stats.projects },
|
{ value: "13+", label: dict.hero.stats.projects },
|
||||||
{ value: "4", label: dict.hero.stats.clients },
|
{ value: "5", label: dict.hero.stats.clients },
|
||||||
{ value: "10", label: dict.hero.stats.infra },
|
{ value: "10", label: dict.hero.stats.infra },
|
||||||
{ value: "<24h", label: dict.hero.stats.response },
|
{ value: "<24h", label: dict.hero.stats.response },
|
||||||
];
|
];
|
||||||
@@ -65,17 +65,6 @@ export default function Hero({ locale, dict }: HeroProps) {
|
|||||||
animate="visible"
|
animate="visible"
|
||||||
className="mx-auto max-w-4xl text-center"
|
className="mx-auto max-w-4xl text-center"
|
||||||
>
|
>
|
||||||
{/* Badge */}
|
|
||||||
<motion.div variants={fadeUp} className="mb-8 flex justify-center">
|
|
||||||
<span className="inline-flex items-center gap-2 rounded-full border border-emerald-500/30 bg-emerald-500/10 px-3.5 py-1.5 font-mono text-xs tracking-tight text-emerald-300 backdrop-blur-md">
|
|
||||||
<span className="relative flex h-1.5 w-1.5">
|
|
||||||
<span className="absolute inset-0 animate-ping rounded-full bg-emerald-400 opacity-75" />
|
|
||||||
<span className="relative inline-flex h-1.5 w-1.5 rounded-full bg-emerald-400" />
|
|
||||||
</span>
|
|
||||||
{dict.hero.badge}
|
|
||||||
</span>
|
|
||||||
</motion.div>
|
|
||||||
|
|
||||||
{/* Heading */}
|
{/* Heading */}
|
||||||
<motion.h1
|
<motion.h1
|
||||||
variants={fadeUp}
|
variants={fadeUp}
|
||||||
|
|||||||
+5
-5
@@ -17,9 +17,9 @@ export type Dictionary = typeof dictionaries.en;
|
|||||||
// independently of type. Lower numbers come first. `inCarousel: false` hides
|
// independently of type. Lower numbers come first. `inCarousel: false` hides
|
||||||
// a project from the homepage carousel while keeping it on the projects page.
|
// a project from the homepage carousel while keeping it on the projects page.
|
||||||
const projectsMeta = {
|
const projectsMeta = {
|
||||||
"security-consultancy": { order: 1, carouselOrder: 4, inCarousel: true, tags: ["React", "Node.js", "Express", "JavaScript"], live: true, type: "client" as const, url: "https://obzor.rs/", github: "", download: "", inProgress: false, screenshots: ["/site1.png"] as string[] },
|
"security-consultancy": { order: 2, carouselOrder: 4, inCarousel: true, tags: ["React", "Node.js", "Express", "JavaScript"], live: true, type: "client" as const, url: "https://obzor.rs/", github: "", download: "", inProgress: false, screenshots: ["/site1.png"] as string[] },
|
||||||
"ecommerce-platform": { order: 2, carouselOrder: 5, inCarousel: true, tags: ["React", "Express.js", "Docker", "CI/CD"], live: true, type: "client" as const, url: "https://kupitri.com", github: "", download: "", inProgress: false, screenshots: ["/site2.png"] as string[] },
|
"ecommerce-platform": { order: 3, carouselOrder: 5, inCarousel: true, tags: ["React", "Express.js", "Docker", "CI/CD"], live: true, type: "client" as const, url: "https://kupitri.com", github: "", download: "", inProgress: false, screenshots: ["/site2.png"] as string[] },
|
||||||
"pramoal": { order: 3, carouselOrder: 3, inCarousel: true, tags: ["Next.js", "Tailwind CSS", "SEO"], live: true, type: "client" as const, url: "https://pramoal.rs", github: "", download: "", inProgress: false, screenshots: ["/pramoal.png"] as string[] },
|
"pramoal": { order: 1, carouselOrder: 3, inCarousel: true, tags: ["Next.js", "Tailwind CSS", "SEO"], live: true, type: "client" as const, url: "https://pramoal.rs", github: "", download: "", inProgress: false, screenshots: ["/pramoal.png"] as string[] },
|
||||||
"mobile-companion": { order: 4, carouselOrder: 3, inCarousel: false, tags: ["Java", "Spring Boot", "React Native", "PostgreSQL"], live: false, type: "client" as const, url: "", github: "", download: "", inProgress: true, screenshots: ["/tba.png"] as string[] },
|
"mobile-companion": { order: 4, carouselOrder: 3, inCarousel: false, tags: ["Java", "Spring Boot", "React Native", "PostgreSQL"], live: false, type: "client" as const, url: "", github: "", download: "", inProgress: true, screenshots: ["/tba.png"] as string[] },
|
||||||
"business-landing": { order: 5, carouselOrder: 4, inCarousel: false, tags: ["Next.js", "Tailwind CSS"], live: false, type: "client" as const, url: "", github: "", download: "", inProgress: true, screenshots: ["/tba.png"] as string[] },
|
"business-landing": { order: 5, carouselOrder: 4, inCarousel: false, tags: ["Next.js", "Tailwind CSS"], live: false, type: "client" as const, url: "", github: "", download: "", inProgress: true, screenshots: ["/tba.png"] as string[] },
|
||||||
"etf-oglasi": { order: 1, carouselOrder: 1, inCarousel: true, tags: ["React Native", "Node.js"], live: false, type: "personal" as const, url: "", github: "https://git.ksan.dev/ksan/etf-oglasi", download: "https://git.ksan.dev/ksan/etf-oglasi/releases/tag/mobile-v6", inProgress: false, screenshots: ["/etfoglasi.png", "/etf2.png", "/etfoglasiapp.jpg", "/etf1.png"] as string[] },
|
"etf-oglasi": { order: 1, carouselOrder: 1, inCarousel: true, tags: ["React Native", "Node.js"], live: false, type: "personal" as const, url: "", github: "https://git.ksan.dev/ksan/etf-oglasi", download: "https://git.ksan.dev/ksan/etf-oglasi/releases/tag/mobile-v6", inProgress: false, screenshots: ["/etfoglasi.png", "/etf2.png", "/etfoglasiapp.jpg", "/etf1.png"] as string[] },
|
||||||
@@ -34,7 +34,6 @@ export const dictionaries = {
|
|||||||
en: {
|
en: {
|
||||||
nav: { features: "Features", projects: "Projects", services: "Services", about: "About", contact: "Contact" },
|
nav: { features: "Features", projects: "Projects", services: "Services", about: "About", contact: "Contact" },
|
||||||
hero: {
|
hero: {
|
||||||
badge: "Available for freelance & full-time",
|
|
||||||
titleLine1: "Full-stack engineering,", titleLine2: "end to end.",
|
titleLine1: "Full-stack engineering,", titleLine2: "end to end.",
|
||||||
subtitle: "From idea to production-ready software. I build and deploy end-to-end systems — including web applications, backend services, and APIs — into production.",
|
subtitle: "From idea to production-ready software. I build and deploy end-to-end systems — including web applications, backend services, and APIs — into production.",
|
||||||
cta: "Start a project", ctaSecondary: "See what I do",
|
cta: "Start a project", ctaSecondary: "See what I do",
|
||||||
@@ -272,6 +271,7 @@ export const dictionaries = {
|
|||||||
messageLabel: "Message", messagePlaceholder: "Tell me about your project...",
|
messageLabel: "Message", messagePlaceholder: "Tell me about your project...",
|
||||||
send: "Send message", sending: "Sending...", avgResponse: "Average response time: under 24h",
|
send: "Send message", sending: "Sending...", avgResponse: "Average response time: under 24h",
|
||||||
successTitle: "Message sent.", successMessage: "Thanks for reaching out — I'll get back to you within 24 hours.", sendAnother: "Send another message",
|
successTitle: "Message sent.", successMessage: "Thanks for reaching out — I'll get back to you within 24 hours.", sendAnother: "Send another message",
|
||||||
|
phoneLabel: "Phone",
|
||||||
responseTime: "Response time", responseValue: "Usually within 24h",
|
responseTime: "Response time", responseValue: "Usually within 24h",
|
||||||
location: "Location", locationValue: "Banja Luka, Bosnia and Herzegovina",
|
location: "Location", locationValue: "Banja Luka, Bosnia and Herzegovina",
|
||||||
},
|
},
|
||||||
@@ -284,7 +284,6 @@ export const dictionaries = {
|
|||||||
sr: {
|
sr: {
|
||||||
nav: { features: "Vještine", projects: "Projekti", services: "Usluge", about: "O meni", contact: "Kontakt" },
|
nav: { features: "Vještine", projects: "Projekti", services: "Usluge", about: "O meni", contact: "Kontakt" },
|
||||||
hero: {
|
hero: {
|
||||||
badge: "Dostupan za freelance i stalni posao",
|
|
||||||
titleLine1: "Full-stack inženjering,", titleLine2: "end-to-end",
|
titleLine1: "Full-stack inženjering,", titleLine2: "end-to-end",
|
||||||
subtitle: "Od ideje do produkcijski spremnog softvera. Razvijam i deploy-ujem end-to-end sisteme — od web aplikacija i backend servisa do API-ja — u produkcijsko okruženje.",
|
subtitle: "Od ideje do produkcijski spremnog softvera. Razvijam i deploy-ujem end-to-end sisteme — od web aplikacija i backend servisa do API-ja — u produkcijsko okruženje.",
|
||||||
cta: "Započni projekat", ctaSecondary: "Pogledaj usluge",
|
cta: "Započni projekat", ctaSecondary: "Pogledaj usluge",
|
||||||
@@ -490,6 +489,7 @@ export const dictionaries = {
|
|||||||
messageLabel: "Poruka", messagePlaceholder: "Ispričajte mi o svom projektu...",
|
messageLabel: "Poruka", messagePlaceholder: "Ispričajte mi o svom projektu...",
|
||||||
send: "Pošalji poruku", sending: "Slanje...", avgResponse: "Prosječno vrijeme odgovora: ispod 24h",
|
send: "Pošalji poruku", sending: "Slanje...", avgResponse: "Prosječno vrijeme odgovora: ispod 24h",
|
||||||
successTitle: "Poruka poslata.", successMessage: "Hvala na poruci — javiću vam se u roku od 24 sata.", sendAnother: "Pošalji novu poruku",
|
successTitle: "Poruka poslata.", successMessage: "Hvala na poruci — javiću vam se u roku od 24 sata.", sendAnother: "Pošalji novu poruku",
|
||||||
|
phoneLabel: "Telefon",
|
||||||
responseTime: "Vrijeme odgovora", responseValue: "Obično ispod 24h",
|
responseTime: "Vrijeme odgovora", responseValue: "Obično ispod 24h",
|
||||||
location: "Lokacija", locationValue: "Banja Luka, Bosna i Hercegovina",
|
location: "Lokacija", locationValue: "Banja Luka, Bosna i Hercegovina",
|
||||||
},
|
},
|
||||||
|
|||||||
Reference in New Issue
Block a user