[yoga-15] improve service list rendering

This commit is contained in:
Schneider Roland 2025-09-10 10:49:34 +02:00
parent c0ca7108c7
commit 8fc0f924b8
11 changed files with 62 additions and 12 deletions

View File

@ -6,6 +6,9 @@
"populate": { "populate": {
"image": { "image": {
"fields": ["name","mime","url" ] "fields": ["name","mime","url" ]
},
"articleImage": {
"fields": ["name","mime","url" ]
} }
} }
}, },

View File

@ -5,6 +5,7 @@ import SubscribeComponent from "@/components/subscribe.component";
import strapiApi from "@/api/strapi/strapi-api"; import strapiApi from "@/api/strapi/strapi-api";
import SubHeaderComponent from "@/components/subHeader.component"; import SubHeaderComponent from "@/components/subHeader.component";
import SingleServiceComponent from "@/components/single.service.component"; import SingleServiceComponent from "@/components/single.service.component";
import {sortServicesByPriority} from "@/util/sorting";
export default async function Services() { export default async function Services() {
const { const {
@ -15,12 +16,13 @@ export default async function Services() {
common, common,
services services
} = await strapiApi.getServiceListPage(); } = await strapiApi.getServiceListPage();
console.info("ServiceListPage", services.length, services.map); let sortedServices = services ? [...services] : [];
sortedServices.sort( sortServicesByPriority )
return ( return (
<> <>
<SubHeaderComponent header={{header1:header,description}} common={common}/> <SubHeaderComponent header={{header1:header,description}} common={common}/>
{ {
services && services.length > 0 && services.map( (singleService,index) => { sortedServices.map( (singleService,index) => {
return ( return (
<SingleServiceComponent key={singleService.id} config={singleService} index={index}/> <SingleServiceComponent key={singleService.id} config={singleService} index={index}/>
) )

View File

@ -0,0 +1,5 @@
.rightImage {
border-top-left-radius: 60px;
border-bottom-right-radius: 60px;
margin: -150px 0 12px 12px;
}

View File

@ -1,6 +1,8 @@
import YogaImageComponent from "@/components/yoga.image.component"; import YogaImageComponent from "@/components/yoga.image.component";
import {BlockWithImageComponentProps} from "@/components/block.with.image.component"; import {BlockWithImageComponentProps} from "@/components/block.with.image.component";
import NextBlocksRenderer from "@/components/next.blocks.renderer"; import NextBlocksRenderer from "@/components/next.blocks.renderer";
import styles from './block.with.right.image.component.module.css';
import clsx from "clsx";
export default function BlockWithRightImage ({ export default function BlockWithRightImage ({
title,header, block,button, image: { title,header, block,button, image: {
@ -14,8 +16,11 @@ export default function BlockWithRightImage ({
<div className="container"> <div className="container">
<div className="mission_box"> <div className="mission_box">
<div className="row"> <div className="row">
<div className="col-lg-6 col-md-6 col-sm-12 col-xs-12" data-aos="fade-up"> <div className="col-lg-12 col-md-12 col-sm-12 col-xs-12" data-aos="fade-up">
<div className="mission_content"> <div className="mission_content">
<div className="mission_image">
<figure className="mb-0"><YogaImageComponent src={url} alt="" className={clsx("img-fluid", "float-right", styles.rightImage)} /></figure>
</div>
{title && <h5>{title}</h5>} {title && <h5>{title}</h5>}
{header && <h2>{header}</h2>} {header && <h2>{header}</h2>}
<NextBlocksRenderer content={ block } /> <NextBlocksRenderer content={ block } />
@ -24,11 +29,6 @@ export default function BlockWithRightImage ({
</div> </div>
</div> </div>
</div> </div>
<div className="col-lg-6 col-md-6 col-sm-12 col-xs-12">
<div className="mission_image">
<figure className="mb-0"><YogaImageComponent src={url} alt="" className="img-fluid" /></figure>
</div>
</div>
</div> </div>
</div> </div>
<figure className="mission_right_shape right_shape mb-0"> <figure className="mission_right_shape right_shape mb-0">

View File

@ -6,6 +6,7 @@ import "slick-carousel/slick/slick.css";
import "slick-carousel/slick/slick-theme.css"; import "slick-carousel/slick/slick-theme.css";
import Slider ,{Settings} from "react-slick"; import Slider ,{Settings} from "react-slick";
import OurServiceItemComponent from "@/components/our.services.item.component"; import OurServiceItemComponent from "@/components/our.services.item.component";
import {sortServicesByPriority} from "@/util/sorting";
export interface Props{ export interface Props{
@ -67,6 +68,8 @@ const OurServiceComponent = ({config: {title,header,description,services}}: Prop
} }
] ]
}; };
let sortedServices = services ? [...services] : [];
sortedServices.sort( sortServicesByPriority )
return ( return (
<section className="services_section"> <section className="services_section">
<div className="container"> <div className="container">
@ -88,7 +91,7 @@ const OurServiceComponent = ({config: {title,header,description,services}}: Prop
{/*</div>*/} {/*</div>*/}
<Slider {...settings}> <Slider {...settings}>
{services.map( {sortedServices.map(
itemConfig => itemConfig =>
<OurServiceItemComponent config={itemConfig} key={itemConfig.id} /> <OurServiceItemComponent config={itemConfig} key={itemConfig.id} />
)} )}

View File

@ -11,12 +11,12 @@ export interface Props {
} }
const SingleService = ({config,index}: Props) => { const SingleService = ({config,index}: Props) => {
if (!config || !config.article || !config.image) { if (!config || !config.article || !config.articleImage) {
return null; // or some fallback UI return null; // or some fallback UI
} }
const {article, image, id, header } = config; const {article, articleImage, id, header } = config;
const strapiFile = image as StrapiFile; const strapiFile = articleImage as StrapiFile;
const imageUrl = strapiApi.getImageUrl(strapiFile?.url); const imageUrl = strapiApi.getImageUrl(strapiFile?.url);
return ( return (

View File

@ -14,6 +14,8 @@ export interface YogaSingleService {
imageAlt?: string; imageAlt?: string;
name?: string; name?: string;
article?: any; article?: any;
articleImage?: { data: Media };
priority?: number;
locale: string; locale: string;
localizations?: { data: YogaSingleService[] }; localizations?: { data: YogaSingleService[] };
}; };
@ -27,6 +29,8 @@ export interface YogaSingleService_Plain {
imageAlt?: string; imageAlt?: string;
name?: string; name?: string;
article?: any; article?: any;
articleImage?: Media_Plain;
priority?: number;
locale: string; locale: string;
localizations?: YogaSingleService_Plain[]; localizations?: YogaSingleService_Plain[];
} }
@ -40,6 +44,8 @@ export interface YogaSingleService_NoRelations {
imageAlt?: string; imageAlt?: string;
name?: string; name?: string;
article?: any; article?: any;
articleImage?: number;
priority?: number;
locale: string; locale: string;
localizations?: YogaSingleService[]; localizations?: YogaSingleService[];
} }
@ -53,6 +59,8 @@ export interface YogaSingleService_AdminPanelLifeCycle {
imageAlt?: string; imageAlt?: string;
name?: string; name?: string;
article?: any; article?: any;
articleImage?: AdminPanelRelationPropertyModification<Media_Plain>;
priority?: number;
locale: string; locale: string;
localizations?: YogaSingleService[]; localizations?: YogaSingleService[];
} }

View File

@ -0,0 +1,7 @@
import {YogaSingleService_Plain} from "@/types/generated-strapi-interfaces/api/yoga-single-service";
export function sortServicesByPriority(a: YogaSingleService_Plain, b: YogaSingleService_Plain) {
const priorityA = a.priority ?? 0;
const priorityB = b.priority ?? 0;
return priorityA - priorityB;
}

View File

@ -14,6 +14,8 @@ export interface YogaSingleService {
imageAlt?: string; imageAlt?: string;
name?: string; name?: string;
article?: any; article?: any;
articleImage?: { data: Media };
priority?: number;
locale: string; locale: string;
localizations?: { data: YogaSingleService[] }; localizations?: { data: YogaSingleService[] };
}; };
@ -27,6 +29,8 @@ export interface YogaSingleService_Plain {
imageAlt?: string; imageAlt?: string;
name?: string; name?: string;
article?: any; article?: any;
articleImage?: Media_Plain;
priority?: number;
locale: string; locale: string;
localizations?: YogaSingleService_Plain[]; localizations?: YogaSingleService_Plain[];
} }
@ -40,6 +44,8 @@ export interface YogaSingleService_NoRelations {
imageAlt?: string; imageAlt?: string;
name?: string; name?: string;
article?: any; article?: any;
articleImage?: number;
priority?: number;
locale: string; locale: string;
localizations?: YogaSingleService[]; localizations?: YogaSingleService[];
} }
@ -53,6 +59,8 @@ export interface YogaSingleService_AdminPanelLifeCycle {
imageAlt?: string; imageAlt?: string;
name?: string; name?: string;
article?: any; article?: any;
articleImage?: AdminPanelRelationPropertyModification<Media_Plain>;
priority?: number;
locale: string; locale: string;
localizations?: YogaSingleService[]; localizations?: YogaSingleService[];
} }

View File

@ -74,6 +74,18 @@
}, },
"article": { "article": {
"type": "blocks" "type": "blocks"
},
"articleImage": {
"allowedTypes": [
"images",
"files"
],
"type": "media",
"multiple": false
},
"priority": {
"type": "integer",
"default": 100
} }
} }
} }

View File

@ -1840,6 +1840,7 @@ export interface ApiYogaSingleServiceYogaSingleService
}; };
attributes: { attributes: {
article: Schema.Attribute.Blocks; article: Schema.Attribute.Blocks;
articleImage: Schema.Attribute.Media<'images' | 'files'>;
buttonLink: Schema.Attribute.String & buttonLink: Schema.Attribute.String &
Schema.Attribute.SetPluginOptions<{ Schema.Attribute.SetPluginOptions<{
i18n: { i18n: {
@ -1884,6 +1885,7 @@ export interface ApiYogaSingleServiceYogaSingleService
localized: true; localized: true;
}; };
}>; }>;
priority: Schema.Attribute.Integer & Schema.Attribute.DefaultTo<100>;
publishedAt: Schema.Attribute.DateTime; publishedAt: Schema.Attribute.DateTime;
updatedAt: Schema.Attribute.DateTime; updatedAt: Schema.Attribute.DateTime;
updatedBy: Schema.Attribute.Relation<'oneToOne', 'admin::user'> & updatedBy: Schema.Attribute.Relation<'oneToOne', 'admin::user'> &