[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

@ -29,7 +29,7 @@ GET {{domain}}/api/yoga-single-services?filters[name][$eq]=service4
Accept: application/json Accept: application/json
### GET service page ### GET service page
GET {{domain}}/api/home?populate[common][fields][0]=*&populate[common][populate][logoImage][fields][0]=name&populate[common][populate][logoImage][fields][1]=mime&populate[common][populate][logoImage][fields][2]=url&populate[header][fields][0]=*&populate[header][populate][button][fields][0]=*&populate[header][populate][button][image][fields][0]=name&populate[header][populate][button][image][fields][1]=mime&populate[header][populate][button][image][fields][2]=url&populate[footer][fields][0]=*&populate[footer][populate][links][fields][0]=*&populate[footer][populate][contactUsEmail][fields][0]=*&populate[footer][populate][contactUsLocation][fields][0]=*&populate[footer][populate][contactUsPhoneNumber][fields][0]=*&populate[subscribeNow][fields][0]=*&populate[blogs][fields][0]=*&populate[blogs][populate][button][fields][0]=*&populate[blogs][populate][posts][fields][0]=name&populate[blogs][populate][posts][fields][1]=id&populate[blogs][populate][posts][fields][2]=header&populate[blogs][populate][posts][fields][3]=documentId&populate[blogs][populate][posts][populate][tags][fields][0]=*&populate[blogs][populate][posts][populate][teaserImage][fields][0]=name&populate[blogs][populate][posts][populate][teaserImage][fields][1]=mime&populate[blogs][populate][posts][populate][teaserImage][fields][2]=url&populate[feedbacks][fields][0]=*&populate[feedbacks][populate][feedbacks][fields][0]=*&populate[feedbacks][populate][feedbacks][populate][customerImage][fields][0]=name&populate[feedbacks][populate][feedbacks][populate][customerImage][fields][1]=mime&populate[feedbacks][populate][feedbacks][populate][customerImage][fields][2]=url&populate[ourServices][fields][0]=*&populate[ourServices][populate][services][fields][0]=*&populate[ourServices][populate][services][populate][image][fields][0]=name&populate[ourServices][populate][services][populate][image][fields][1]=mime&populate[ourServices][populate][services][populate][image][fields][2]=url&populate[aboutUs][fields][0]=*&populate[aboutUs][populate][image][fields][0]=name&populate[aboutUs][populate][image][fields][1]=mime&populate[aboutUs][populate][image][fields][2]=url&populate[contactUs][fields][0]=*&populate[prices][fields][0]=*&populate[prices][populate][prices][fields][0]=*&populate[prices][populate][prices][populate][icon][fields][0]=name&populate[prices][populate][prices][populate][icon][fields][1]=mime&populate[prices][populate][prices][populate][icon][fields][2]=url&populate[prices][populate][prices][populate][image][fields][0]=name&populate[prices][populate][prices][populate][image][fields][1]=mime&populate[prices][populate][prices][populate][image][fields][2]=url&populate[ourSpecialities][fields][0]=*&populate[ourSpecialities][populate][left1][fields][0]=*&populate[ourSpecialities][populate][left2][fields][0]=*&populate[ourSpecialities][populate][left3][fields][0]=*&populate[ourSpecialities][populate][left4][fields][0]=*&populate[ourSpecialities][populate][right1][fields][0]=*&populate[ourSpecialities][populate][right2][fields][0]=*&populate[ourSpecialities][populate][right3][fields][0]=*&populate[ourSpecialities][populate][right4][fields][0]=* GET {{domain}}/api/service-list-page?fields[0]=*&populate[services][fields][0]=*&populate[services][populate][image][fields][0]=name&populate[services][populate][image][fields][1]=mime&populate[services][populate][image][fields][2]=url&populate[common][fields][0]=*&populate[common][populate][logoImage][fields][0]=name&populate[common][populate][logoImage][fields][1]=mime&populate[common][populate][logoImage][fields][2]=url&populate[subscribeNow][fields][0]=*&populate[footer][fields][0]=*&populate[footer][populate][links][fields][0]=*&populate[footer][populate][contactUsEmail][fields][0]=*&populate[footer][populate][contactUsLocation][fields][0]=*&populate[footer][populate][contactUsPhoneNumber][fields][0]=*
Accept: application/json Accept: application/json

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 aboutQuery from "@/api/strapi/query/about.json";
import homeQuery from "@/api/strapi/query/home.json"; import homeQuery from "@/api/strapi/query/home.json";
import servicesQuery from "@/api/strapi/query/services.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 serviceQuery from "@/api/strapi/query/service.json";
import pricesQuery from "@/api/strapi/query/prices.json"; import pricesQuery from "@/api/strapi/query/prices.json";
import faqQuery from "@/api/strapi/query/faq.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 {YogaBlogPost_Plain} from "@/types/generated-strapi-interfaces/api/yoga-blog-post";
import {Home_Plain} from "@/types/generated-strapi-interfaces/api/home"; import {Home_Plain} from "@/types/generated-strapi-interfaces/api/home";
import {ServicesPage_Plain} from "@/types/generated-strapi-interfaces/api/services-page"; 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 {PricesPage_Plain} from "@/types/generated-strapi-interfaces/api/prices-page";
import {FaqPage_Plain} from "@/types/generated-strapi-interfaces/api/faq-page"; import {FaqPage_Plain} from "@/types/generated-strapi-interfaces/api/faq-page";
import {ContactPage_Plain} from "@/types/generated-strapi-interfaces/api/contact-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); 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[]>{ public getService(name: string): Promise<YogaSingleService_Plain[]>{
return this.getJson("/api/yoga-single-services?", { return this.getJson("/api/yoga-single-services?", {
filters: { 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', 'services' : 'Szolgáltatásaim',
'prices' : 'Áraim', 'prices' : 'Áraim',
'faq' : 'GYIK', 'faq' : 'GYIK',
'serviceList' : 'Szolgáltatások',
} }
if ( mapping.hasOwnProperty(path)){ if ( mapping.hasOwnProperty(path)){
return mapping[path]; return mapping[path];
@ -24,9 +25,6 @@ const NextBreadcrumb = () => {
const paths = usePathname() const paths = usePathname()
const pathNames = paths.split('/').filter( path => path ) const pathNames = paths.split('/').filter( path => path )
return ( return (
<div className="btn_wrapper"> <div className="btn_wrapper">
<span className="sub_home_span">{pathToBreadCrumbs( "/" )} </span> <span className="sub_home_span">{pathToBreadCrumbs( "/" )} </span>

View File

@ -1,5 +1,4 @@
"use client" "use client"
import {FC} from "react";
import YogaImageComponent from "@/components/yoga.image.component"; import YogaImageComponent from "@/components/yoga.image.component";
import clsx from "clsx"; import clsx from "clsx";
import Link from "next/link"; import Link from "next/link";
@ -11,12 +10,13 @@ export interface MenuItem{
active?: boolean, active?: boolean,
styleClass?: string; styleClass?: string;
} }
export interface Props { export interface Props {
menuItems: MenuItem[]; menuItems: MenuItem[];
imageSrc?: string; imageSrc?: string;
} }
const Nav: FC<Props> = ({menuItems, imageSrc}:Props) => { const Nav = ({menuItems, imageSrc}: Props) => {
return ( return (
<header> <header>
@ -36,7 +36,8 @@ const Nav: FC<Props> = ({menuItems, imageSrc}:Props) => {
</button> </button>
<div className="collapse navbar-collapse" id="navbarSupportedContent"> <div className="collapse navbar-collapse" id="navbarSupportedContent">
<ul className="navbar-nav"> <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> </ul>
</div> </div>
</nav> </nav>
@ -50,7 +51,8 @@ interface MenuItemProps{
menuItem: MenuItem, menuItem: MenuItem,
dropdownItem?: boolean, dropdownItem?: boolean,
} }
const MenuItemComponent: FC<MenuItemProps> = ({menuItem, dropdownItem}: MenuItemProps) => {
const MenuItemComponent = ({menuItem, dropdownItem}: MenuItemProps) => {
if (!menuItem) { if (!menuItem) {
return (<></>); return (<></>);
} }
@ -58,7 +60,8 @@ const MenuItemComponent: FC<MenuItemProps> = ({menuItem, dropdownItem}: MenuIte
return ( return (
// <li className="nav-item active"> // <li className="nav-item active">
<li className={clsx("nav-item", {"active": menuItem.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> </li>
); );
} }
@ -71,7 +74,8 @@ const MenuItemComponent: FC<MenuItemProps> = ({menuItem, dropdownItem}: MenuIte
<div className="dropdown-menu drop-down-content"> <div className="dropdown-menu drop-down-content">
<ul className="list-unstyled drop-down-pages"> <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> </ul>
</div> </div>

View File

@ -14,7 +14,7 @@ const OurServiceItemComponent = ({config: {header,description,image,name}}: Prop
if (!imageFile || !imageFile.url) { if (!imageFile || !imageFile.url) {
return null return null
} }
const path = '/services/' + name; const path = '/serviceList#' + name;
return ( return (
<div className={styles.serviceSlide}> <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', label: 'Szolgáltatásaink',
href: '/services' href: '/serviceList'
}, },
// { // {
// label: 'Oldalak', // label: 'Oldalak',
@ -34,6 +34,10 @@ export const MAIN_MENU:MenuItem[] = [
label: 'GY.I.K', label: 'GY.I.K',
href: '/faq' href: '/faq'
}, },
{
label: 'Szolgáltatásaink',
href: '/serviceList'
},
// { // {
// label: 'Rólam', // label: 'Rólam',
// href: '/team' // href: '/team'

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

@ -0,0 +1,40 @@
{
"kind": "singleType",
"collectionName": "service_list_pages",
"info": {
"singularName": "service-list-page",
"pluralName": "service-list-pages",
"displayName": "ServiceListPage"
},
"options": {
"draftAndPublish": true
},
"attributes": {
"header": {
"type": "string"
},
"description": {
"type": "text"
},
"subscribeNow": {
"type": "relation",
"relation": "oneToOne",
"target": "api::yoga-subscribe-now-component.yoga-subscribe-now-component"
},
"footer": {
"type": "relation",
"relation": "oneToOne",
"target": "api::yoga-footer.yoga-footer"
},
"common": {
"type": "relation",
"relation": "oneToOne",
"target": "api::yoga-common.yoga-common"
},
"services": {
"type": "relation",
"relation": "oneToMany",
"target": "api::yoga-single-service.yoga-single-service"
}
}
}

View File

@ -0,0 +1,7 @@
/**
* service-list-page controller
*/
import { factories } from '@strapi/strapi'
export default factories.createCoreController('api::service-list-page.service-list-page');

View File

@ -0,0 +1,7 @@
/**
* service-list-page router
*/
import { factories } from '@strapi/strapi';
export default factories.createCoreRouter('api::service-list-page.service-list-page');

View File

@ -0,0 +1,7 @@
/**
* service-list-page service
*/
import { factories } from '@strapi/strapi';
export default factories.createCoreService('api::service-list-page.service-list-page');

View File

@ -4,7 +4,7 @@
"info": { "info": {
"singularName": "services-page", "singularName": "services-page",
"pluralName": "services-pages", "pluralName": "services-pages",
"displayName": "Services", "displayName": "ServicesPage",
"description": "" "description": ""
}, },
"options": { "options": {

View File

@ -871,6 +871,52 @@ export interface ApiPricesPagePricesPage extends Struct.SingleTypeSchema {
}; };
} }
export interface ApiServiceListPageServiceListPage
extends Struct.SingleTypeSchema {
collectionName: 'service_list_pages';
info: {
displayName: 'ServiceListPage';
pluralName: 'service-list-pages';
singularName: 'service-list-page';
};
options: {
draftAndPublish: true;
};
attributes: {
common: Schema.Attribute.Relation<
'oneToOne',
'api::yoga-common.yoga-common'
>;
createdAt: Schema.Attribute.DateTime;
createdBy: Schema.Attribute.Relation<'oneToOne', 'admin::user'> &
Schema.Attribute.Private;
description: Schema.Attribute.Text;
footer: Schema.Attribute.Relation<
'oneToOne',
'api::yoga-footer.yoga-footer'
>;
header: Schema.Attribute.String;
locale: Schema.Attribute.String & Schema.Attribute.Private;
localizations: Schema.Attribute.Relation<
'oneToMany',
'api::service-list-page.service-list-page'
> &
Schema.Attribute.Private;
publishedAt: Schema.Attribute.DateTime;
services: Schema.Attribute.Relation<
'oneToMany',
'api::yoga-single-service.yoga-single-service'
>;
subscribeNow: Schema.Attribute.Relation<
'oneToOne',
'api::yoga-subscribe-now-component.yoga-subscribe-now-component'
>;
updatedAt: Schema.Attribute.DateTime;
updatedBy: Schema.Attribute.Relation<'oneToOne', 'admin::user'> &
Schema.Attribute.Private;
};
}
export interface ApiServicePageServicePage extends Struct.SingleTypeSchema { export interface ApiServicePageServicePage extends Struct.SingleTypeSchema {
collectionName: 'service_pages'; collectionName: 'service_pages';
info: { info: {
@ -917,7 +963,7 @@ export interface ApiServicesPageServicesPage extends Struct.SingleTypeSchema {
collectionName: 'services_pages'; collectionName: 'services_pages';
info: { info: {
description: ''; description: '';
displayName: 'Services'; displayName: 'ServicesPage';
pluralName: 'services-pages'; pluralName: 'services-pages';
singularName: 'services-page'; singularName: 'services-page';
}; };
@ -2604,6 +2650,7 @@ declare module '@strapi/strapi' {
'api::page.page': ApiPagePage; 'api::page.page': ApiPagePage;
'api::person.person': ApiPersonPerson; 'api::person.person': ApiPersonPerson;
'api::prices-page.prices-page': ApiPricesPagePricesPage; 'api::prices-page.prices-page': ApiPricesPagePricesPage;
'api::service-list-page.service-list-page': ApiServiceListPageServiceListPage;
'api::service-page.service-page': ApiServicePageServicePage; 'api::service-page.service-page': ApiServicePageServicePage;
'api::services-page.services-page': ApiServicesPageServicesPage; 'api::services-page.services-page': ApiServicesPageServicesPage;
'api::yoga-about-us-component.yoga-about-us-component': ApiYogaAboutUsComponentYogaAboutUsComponent; 'api::yoga-about-us-component.yoga-about-us-component': ApiYogaAboutUsComponentYogaAboutUsComponent;