added social media links
This commit is contained in:
21
src/assets/icons/InstagramIcon.tsx
Normal file
21
src/assets/icons/InstagramIcon.tsx
Normal file
@@ -0,0 +1,21 @@
|
||||
import { forwardRef } from 'react'
|
||||
|
||||
import type { IconProps } from './types'
|
||||
|
||||
export const InstagramIcon = forwardRef<SVGSVGElement, IconProps>(
|
||||
function InstagramIcon(props, ref) {
|
||||
return (
|
||||
<svg
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
viewBox="0 0 24 24"
|
||||
width="48px"
|
||||
height="48px"
|
||||
ref={ref}
|
||||
{...props}
|
||||
>
|
||||
{' '}
|
||||
<path d="M 8 3 C 5.239 3 3 5.239 3 8 L 3 16 C 3 18.761 5.239 21 8 21 L 16 21 C 18.761 21 21 18.761 21 16 L 21 8 C 21 5.239 18.761 3 16 3 L 8 3 z M 18 5 C 18.552 5 19 5.448 19 6 C 19 6.552 18.552 7 18 7 C 17.448 7 17 6.552 17 6 C 17 5.448 17.448 5 18 5 z M 12 7 C 14.761 7 17 9.239 17 12 C 17 14.761 14.761 17 12 17 C 9.239 17 7 14.761 7 12 C 7 9.239 9.239 7 12 7 z M 12 9 A 3 3 0 0 0 9 12 A 3 3 0 0 0 12 15 A 3 3 0 0 0 15 12 A 3 3 0 0 0 12 9 z" />
|
||||
</svg>
|
||||
)
|
||||
}
|
||||
)
|
||||
18
src/assets/icons/TelegramIcon.tsx
Normal file
18
src/assets/icons/TelegramIcon.tsx
Normal file
@@ -0,0 +1,18 @@
|
||||
import { forwardRef } from 'react'
|
||||
|
||||
import type { IconProps } from './types'
|
||||
|
||||
export const TelegramIcon = forwardRef<SVGSVGElement, IconProps>(function TelegramIcon(props, ref) {
|
||||
return (
|
||||
<svg
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
viewBox="0 0 24 24"
|
||||
width="48px"
|
||||
height="48px"
|
||||
ref={ref}
|
||||
{...props}
|
||||
>
|
||||
<path d="M 20.302734 2.984375 C 20.013769 2.996945 19.748583 3.080055 19.515625 3.171875 C 19.300407 3.256634 18.52754 3.5814726 17.296875 4.0976562 C 16.06621 4.61384 14.435476 5.2982348 12.697266 6.0292969 C 9.2208449 7.4914211 5.314238 9.1361259 3.3125 9.9785156 C 3.243759 10.007156 2.9645852 10.092621 2.65625 10.328125 C 2.3471996 10.564176 2.0039062 11.076462 2.0039062 11.636719 C 2.0039062 12.088671 2.2295201 12.548966 2.5019531 12.8125 C 2.7743861 13.076034 3.0504903 13.199244 3.28125 13.291016 L 3.28125 13.289062 C 4.0612776 13.599827 6.3906939 14.531938 6.9453125 14.753906 C 7.1420423 15.343433 7.9865895 17.867278 8.1875 18.501953 L 8.1855469 18.501953 C 8.3275588 18.951162 8.4659791 19.243913 8.6582031 19.488281 C 8.7543151 19.610465 8.8690398 19.721184 9.0097656 19.808594 C 9.0637596 19.842134 9.1235454 19.868148 9.1835938 19.892578 C 9.191962 19.896131 9.2005867 19.897012 9.2089844 19.900391 L 9.1855469 19.894531 C 9.2029579 19.901531 9.2185841 19.911859 9.2363281 19.917969 C 9.2652427 19.927926 9.2852873 19.927599 9.3242188 19.935547 C 9.4612233 19.977694 9.5979794 20.005859 9.7246094 20.005859 C 10.26822 20.005859 10.601562 19.710937 10.601562 19.710938 L 10.623047 19.695312 L 12.970703 17.708984 L 15.845703 20.369141 C 15.898217 20.443289 16.309604 21 17.261719 21 C 17.829844 21 18.279025 20.718791 18.566406 20.423828 C 18.853787 20.128866 19.032804 19.82706 19.113281 19.417969 L 19.115234 19.416016 C 19.179414 19.085834 21.931641 5.265625 21.931641 5.265625 L 21.925781 5.2890625 C 22.011441 4.9067171 22.036735 4.5369631 21.935547 4.1601562 C 21.834358 3.7833495 21.561271 3.4156252 21.232422 3.2226562 C 20.903572 3.0296874 20.591699 2.9718046 20.302734 2.984375 z M 19.908203 5.1738281 C 19.799442 5.7198576 17.33401 18.105877 17.181641 18.882812 L 13.029297 15.041016 L 10.222656 17.414062 L 11 14.375 C 11 14.375 16.362547 8.9468594 16.685547 8.6308594 C 16.945547 8.3778594 17 8.2891719 17 8.2011719 C 17 8.0841719 16.939781 8 16.800781 8 C 16.675781 8 16.506016 8.1197812 16.416016 8.1757812 C 15.272368 8.8887854 10.401283 11.664685 8.0058594 13.027344 C 7.8617016 12.96954 5.6973962 12.100458 4.53125 11.634766 C 6.6055146 10.76177 10.161156 9.2658083 13.472656 7.8730469 C 15.210571 7.142109 16.840822 6.4570977 18.070312 5.9414062 C 19.108158 5.5060977 19.649538 5.2807035 19.908203 5.1738281 z M 17.152344 19.025391 C 17.152344 19.025391 17.154297 19.025391 17.154297 19.025391 C 17.154252 19.025621 17.152444 19.03095 17.152344 19.03125 C 17.153615 19.024789 17.15139 19.03045 17.152344 19.025391 z" />
|
||||
</svg>
|
||||
)
|
||||
})
|
||||
5
src/assets/icons/types.ts
Normal file
5
src/assets/icons/types.ts
Normal file
@@ -0,0 +1,5 @@
|
||||
import type { SVGAttributes } from 'react'
|
||||
|
||||
export type IconProps = SVGAttributes<SVGElement> & {
|
||||
className?: string
|
||||
}
|
||||
@@ -2,16 +2,27 @@
|
||||
import { useTranslations } from '@/i18n/utils'
|
||||
import { Image } from 'astro:assets'
|
||||
import logoSrc from '@/assets/logo.png'
|
||||
import type { z } from 'astro:content'
|
||||
import type { footerSchema } from '@/content.config'
|
||||
import type React from 'react'
|
||||
import { TelegramIcon } from '@/assets/icons/TelegramIcon'
|
||||
import { InstagramIcon } from '@/assets/icons/InstagramIcon'
|
||||
import type { IconProps } from '@/assets/icons/types'
|
||||
|
||||
type Props = {
|
||||
type Props = z.infer<typeof footerSchema> & {
|
||||
lang?: string
|
||||
}
|
||||
|
||||
const { lang } = Astro.props
|
||||
const SOCIAL_MEDIA_ICONS_MAP: Record<string, React.ComponentType<IconProps>> = {
|
||||
telegram: TelegramIcon,
|
||||
instagram: InstagramIcon,
|
||||
}
|
||||
|
||||
const { lang, socialMediaLinks } = Astro.props
|
||||
const t = useTranslations(lang)
|
||||
---
|
||||
|
||||
<footer id="contacts" class="flex flex-col items-center gap-4 md:gap-6 text-center">
|
||||
<footer id="contacts" class="flex flex-col items-center gap-4 text-center md:gap-6">
|
||||
<script
|
||||
is:inline
|
||||
type="text/javascript"
|
||||
@@ -19,11 +30,26 @@ const t = useTranslations(lang)
|
||||
async
|
||||
src="https://api-maps.yandex.ru/services/constructor/1.0/js/?um=constructor%3A069b17526dc83cbf87c488f13ae089eb3af0f8f74af57e1be82e183434693562&width=100%25&height=400&lang=ru_RU&scroll=true"
|
||||
></script>
|
||||
<div class="flex flex-col items-center gap-3 px-4 py-6 md:gap-4 md:px-6 md:py-8 text-center">
|
||||
<div class="flex flex-col items-center gap-3 px-4 py-6 text-center md:gap-4 md:px-6 md:py-8">
|
||||
<Image src={logoSrc} alt="logo" class="h-32 w-auto md:h-48" />
|
||||
<p class="text-light text-sm">
|
||||
© {new Date().getFullYear()}
|
||||
{t('footer.copyright')}
|
||||
</p>
|
||||
{
|
||||
socialMediaLinks && (
|
||||
<div class="flex gap-4 text-text-light">
|
||||
{socialMediaLinks.map(({ href, target, icon }) => {
|
||||
const Icon = SOCIAL_MEDIA_ICONS_MAP[icon]
|
||||
|
||||
return (
|
||||
<a href={href} target={target} rel="noopener noreferrer">
|
||||
<Icon className="fill-text hover:fill-text-light transition-all duration-300" />
|
||||
</a>
|
||||
)
|
||||
})}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
</div>
|
||||
</footer>
|
||||
|
||||
@@ -55,6 +55,19 @@ export const reviewsSchema = (image: ImageFunction) =>
|
||||
rating: z.number(),
|
||||
})
|
||||
|
||||
export const footerSchema = z.object({
|
||||
copyright: z.string().optional(),
|
||||
socialMediaLinks: z
|
||||
.array(
|
||||
z.object({
|
||||
icon: z.string(),
|
||||
href: z.string(),
|
||||
target: z.string().optional(),
|
||||
})
|
||||
)
|
||||
.optional(),
|
||||
})
|
||||
|
||||
const pages = defineCollection({
|
||||
schema: ({ image }) =>
|
||||
z.object({
|
||||
@@ -71,6 +84,7 @@ const pages = defineCollection({
|
||||
)
|
||||
.optional(),
|
||||
services: z.array(servicesSchema).optional(),
|
||||
footer: footerSchema.optional(),
|
||||
}),
|
||||
})
|
||||
|
||||
|
||||
@@ -131,4 +131,12 @@ reviews:
|
||||
imageAlt: 'timur-avatar'
|
||||
description: 'Знаток города 5 уровня'
|
||||
rating: 5
|
||||
footer:
|
||||
socialMediaLinks:
|
||||
- href: 'https://www.instagram.com/therealskill_studio?igsh=YzJvcTlvcHZhMDN5&utm_source=qr'
|
||||
icon: 'instagram'
|
||||
target: '_blank'
|
||||
- href: 'https://t.me/therealskill_studio'
|
||||
icon: 'telegram'
|
||||
target: '_blank'
|
||||
---
|
||||
|
||||
@@ -20,7 +20,7 @@ type Props = CollectionEntry<'pages'>['data']
|
||||
|
||||
const { lang } = Astro.params
|
||||
const page = await getEntry('pages', 'main')
|
||||
const { slider, coaches, services, hero, marquee, reviews } = page?.data || {}
|
||||
const { slider, coaches, services, hero, marquee, reviews, footer } = page?.data || {}
|
||||
const optimizedSlider = slider
|
||||
? await Promise.all(
|
||||
slider.map((slide) =>
|
||||
@@ -99,5 +99,5 @@ const t = useTranslations(lang)
|
||||
)
|
||||
}
|
||||
|
||||
<Footer lang={lang} />
|
||||
<Footer lang={lang} {...footer} />
|
||||
</BaseLayout>
|
||||
|
||||
Reference in New Issue
Block a user