[yoga-15] add new service-list-page

This commit is contained in:
Schneider Roland
2025-07-28 11:31:49 +02:00
parent e9aa0e795e
commit 6acf79e23d
17 changed files with 355 additions and 21 deletions

View File

@@ -0,0 +1,41 @@
{
"fields": ["*"],
"populate": {
"services": {
"fields": ["*"],
"populate": {
"image": {
"fields": ["name","mime","url" ]
}
}
},
"common": {
"fields": ["*"],
"populate": {
"logoImage": {
"fields": ["name","mime","url"]
}
}
},
"subscribeNow": {
"fields": ["*"]
},
"footer": {
"fields": ["*"],
"populate": {
"links": {
"fields": ["*"]
},
"contactUsEmail": {
"fields": ["*"]
},
"contactUsLocation": {
"fields": ["*"]
},
"contactUsPhoneNumber": {
"fields": ["*"]
}
}
}
}
}

View File

@@ -4,6 +4,7 @@ import qs from "qs";
import aboutQuery from "@/api/strapi/query/about.json";
import homeQuery from "@/api/strapi/query/home.json";
import servicesQuery from "@/api/strapi/query/services.json";
import serviceListPageQuery from "@/api/strapi/query/service-list.json";
import serviceQuery from "@/api/strapi/query/service.json";
import pricesQuery from "@/api/strapi/query/prices.json";
import faqQuery from "@/api/strapi/query/faq.json";
@@ -11,6 +12,7 @@ import contactQuery from "@/api/strapi/query/contact.json";
import {YogaBlogPost_Plain} from "@/types/generated-strapi-interfaces/api/yoga-blog-post";
import {Home_Plain} from "@/types/generated-strapi-interfaces/api/home";
import {ServicesPage_Plain} from "@/types/generated-strapi-interfaces/api/services-page";
import {ServiceListPage_Plain} from "@/types/generated-strapi-interfaces/api/service-list-page";
import {PricesPage_Plain} from "@/types/generated-strapi-interfaces/api/prices-page";
import {FaqPage_Plain} from "@/types/generated-strapi-interfaces/api/faq-page";
import {ContactPage_Plain} from "@/types/generated-strapi-interfaces/api/contact-page";
@@ -49,6 +51,10 @@ class StrapiApi{
return this.getJson("/api/service-page?",serviceQuery);
}
public getServiceListPage(): Promise<ServiceListPage_Plain>{
return this.getJson("/api/service-list-page?",serviceListPageQuery);
}
public getService(name: string): Promise<YogaSingleService_Plain[]>{
return this.getJson("/api/yoga-single-services?", {
filters: {

View File

@@ -0,0 +1,37 @@
import React from "react";
import AosComponent from "@/components/aos.component";
import FooterComponent from "@/components/footer.component";
import SubscribeComponent from "@/components/subscribe.component";
import strapiApi from "@/api/strapi/strapi-api";
import SubHeaderComponent from "@/components/subHeader.component";
import SingleServiceComponent from "@/components/single.service.component";
export default async function Services() {
const {
header,
description,
footer,
subscribeNow,
common,
services
} = await strapiApi.getServiceListPage();
console.info("ServiceListPage", services.length, services.map);
return (
<>
<SubHeaderComponent header={{header1:header,description}} common={common}/>
{
services && services.length > 0 && services.map( singleService => {
return (
<SingleServiceComponent key={singleService.id} config={singleService} />
)
})
}
{ subscribeNow && <SubscribeComponent config={subscribeNow} /> }
{ footer && <FooterComponent config={footer} /> }
<AosComponent />
</>
);
}
export const dynamic = 'force-dynamic'

View File

@@ -12,6 +12,7 @@ const pathToBreadCrumbs = (path: string) => {
'services' : 'Szolgáltatásaim',
'prices' : 'Áraim',
'faq' : 'GYIK',
'serviceList' : 'Szolgáltatások',
}
if ( mapping.hasOwnProperty(path)){
return mapping[path];
@@ -24,9 +25,6 @@ const NextBreadcrumb = () => {
const paths = usePathname()
const pathNames = paths.split('/').filter( path => path )
return (
<div className="btn_wrapper">
<span className="sub_home_span">{pathToBreadCrumbs( "/" )} </span>

View File

@@ -1,22 +1,22 @@
"use client"
import {FC} from "react";
import YogaImageComponent from "@/components/yoga.image.component";
import clsx from "clsx";
import Link from "next/link";
export interface MenuItem{
export interface MenuItem {
href?: string;
label: string;
children?: MenuItem[];
active?: boolean,
styleClass?: string;
}
export interface Props{
export interface Props {
menuItems: MenuItem[];
imageSrc?: string;
}
const Nav: FC<Props> = ({menuItems, imageSrc}:Props) => {
const Nav = ({menuItems, imageSrc}: Props) => {
return (
<header>
@@ -36,7 +36,8 @@ const Nav: FC<Props> = ({menuItems, imageSrc}:Props) => {
</button>
<div className="collapse navbar-collapse" id="navbarSupportedContent">
<ul className="navbar-nav">
{menuItems.map( (menuItem,index) => <MenuItemComponent key={"nav"+menuItem.href+"_"+index} menuItem={menuItem} />)}
{menuItems.map((menuItem, index) => <MenuItemComponent
key={"nav" + menuItem.href + "_" + index} menuItem={menuItem}/>)}
</ul>
</div>
</nav>
@@ -46,32 +47,35 @@ const Nav: FC<Props> = ({menuItems, imageSrc}:Props) => {
);
}
interface MenuItemProps{
interface MenuItemProps {
menuItem: MenuItem,
dropdownItem?: boolean,
}
const MenuItemComponent: FC<MenuItemProps> = ({menuItem, dropdownItem}: MenuItemProps) => {
if ( !menuItem ){
const MenuItemComponent = ({menuItem, dropdownItem}: MenuItemProps) => {
if (!menuItem) {
return (<></>);
}
if ( !menuItem.children || menuItem.children.length == 0 ){
if (!menuItem.children || menuItem.children.length == 0) {
return (
// <li className="nav-item active">
<li className={clsx("nav-item", {"active": menuItem.active})}>
<a className={clsx("nav-link", {"dropdown-item":dropdownItem},menuItem.styleClass)} href={menuItem.href}>{menuItem.label}</a>
<a className={clsx("nav-link", {"dropdown-item": dropdownItem}, menuItem.styleClass)}
href={menuItem.href!}>{menuItem.label}</a>
</li>
);
}
return (
<li className={clsx("nav-item", "dropdown",{"active": menuItem.active})}>
<li className={clsx("nav-item", "dropdown", {"active": menuItem.active})}>
<a className="nav-link dropdown-toggle dropdown-color navbar-text-color" href="#"
role="button" data-toggle="dropdown" aria-haspopup="true"
role="button" data-toggle="dropdown" aria-haspopup="true"
aria-expanded="false">{menuItem.label}</a>
<div className="dropdown-menu drop-down-content">
<ul className="list-unstyled drop-down-pages">
{
menuItem.children.map((item,index) => <MenuItemComponent key={"child_"+item.href+"_"+index} menuItem={item} dropdownItem={true}/>)
menuItem.children.map((item, index) => <MenuItemComponent
key={"child_" + item.href + "_" + index} menuItem={item} dropdownItem={true}/>)
}
</ul>
</div>

View File

@@ -14,7 +14,7 @@ const OurServiceItemComponent = ({config: {header,description,image,name}}: Prop
if (!imageFile || !imageFile.url) {
return null
}
const path = '/services/' + name;
const path = '/serviceList#' + name;
return (
<div className={styles.serviceSlide}>

View File

@@ -0,0 +1,32 @@
import {YogaSingleService_Plain} from "@/types/generated-strapi-interfaces/api/yoga-single-service";
import clsx from "clsx";
import NextBlocksRenderer from "@/components/next.blocks.renderer";
import {BlocksContent} from "@strapi/blocks-react-renderer";
import React from "react";
export interface Props {
config: YogaSingleService_Plain
}
const SingleService = ({config}: Props) => {
if (!config || !config.article) {
return null; // or some fallback UI
}
return (
<section id={config.name+""} className={clsx('mb-3')}>
<div className="container">
<div className={"row"}>
<div className={"col-lg-12 col-md-12 col-sm-12 col-xs-12"}>
<NextBlocksRenderer
content={config.article as BlocksContent}
/>
</div>
</div>
</div>
</section>
);
}
export default SingleService;

View File

@@ -0,0 +1,52 @@
// Interface automatically generated by schemas-to-ts
import { YogaSubscribeNowComponent } from './yoga-subscribe-now-component';
import { YogaFooter } from './yoga-footer';
import { YogaCommon } from './yoga-common';
import { YogaSingleService } from './yoga-single-service';
import { YogaSubscribeNowComponent_Plain } from './yoga-subscribe-now-component';
import { YogaFooter_Plain } from './yoga-footer';
import { YogaCommon_Plain } from './yoga-common';
import { YogaSingleService_Plain } from './yoga-single-service';
import { AdminPanelRelationPropertyModification } from '../common/AdminPanelRelationPropertyModification';
export interface ServiceListPage {
id: number;
attributes: {
createdAt: Date; updatedAt: Date; publishedAt?: Date; header?: string;
description?: string;
subscribeNow?: { data: YogaSubscribeNowComponent };
footer?: { data: YogaFooter };
common?: { data: YogaCommon };
services: { data: YogaSingleService[] };
};
}
export interface ServiceListPage_Plain {
id: number;
createdAt: Date; updatedAt: Date; publishedAt?: Date; header?: string;
description?: string;
subscribeNow?: YogaSubscribeNowComponent_Plain;
footer?: YogaFooter_Plain;
common?: YogaCommon_Plain;
services: YogaSingleService_Plain[];
}
export interface ServiceListPage_NoRelations {
id: number;
createdAt: Date; updatedAt: Date; publishedAt?: Date; header?: string;
description?: string;
subscribeNow?: number;
footer?: number;
common?: number;
services: number[];
}
export interface ServiceListPage_AdminPanelLifeCycle {
id: number;
createdAt: Date; updatedAt: Date; publishedAt?: Date; header?: string;
description?: string;
subscribeNow?: AdminPanelRelationPropertyModification<YogaSubscribeNowComponent_Plain>;
footer?: AdminPanelRelationPropertyModification<YogaFooter_Plain>;
common?: AdminPanelRelationPropertyModification<YogaCommon_Plain>;
services: AdminPanelRelationPropertyModification<YogaSingleService_Plain>;
}

View File

@@ -11,7 +11,7 @@ export const MAIN_MENU:MenuItem[] = [
},
{
label: 'Szolgáltatásaink',
href: '/services'
href: '/serviceList'
},
// {
// label: 'Oldalak',
@@ -34,6 +34,10 @@ export const MAIN_MENU:MenuItem[] = [
label: 'GY.I.K',
href: '/faq'
},
{
label: 'Szolgáltatásaink',
href: '/serviceList'
},
// {
// label: 'Rólam',
// href: '/team'