Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
26 changes: 26 additions & 0 deletions src/app/find-help/organisation/[slug]/page.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
import { getOrganisationBySlug } from '@/utils/organisation';
import OrganisationOverview from '@/components/OrganisationPage/OrganisationOverview';
import OrganisationLocations from '@/components/OrganisationPage/OrganisationLocations';
import OrganisationServicesAccordion from '@/components/OrganisationPage/OrganisationServicesAccordion';
import OrganisationContactBlock from '@/components/OrganisationPage/OrganisationContactBlock';
import OrganisationFooter from '@/components/OrganisationPage/OrganisationFooter';
import { notFound } from 'next/navigation';

// eslint-disable-next-line @typescript-eslint/no-explicit-any
export default async function OrganisationPage(props: any) {
const { params }: { params: { slug: string } } = props;

const organisation = await getOrganisationBySlug(params.slug);

if (!organisation) return notFound();

return (
<main className="px-4 py-6 max-w-4xl mx-auto">
<OrganisationOverview organisation={organisation} />
<OrganisationLocations organisation={organisation} />
<OrganisationServicesAccordion organisation={organisation} />
<OrganisationContactBlock organisation={organisation} />
<OrganisationFooter />
</main>
);
}
18 changes: 18 additions & 0 deletions src/components/OrganisationPage/OrganisationContactBlock.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
'use client';
import React from 'react';
import type { OrganisationDetails } from '@/utils/organisation';

interface Props {
organisation: OrganisationDetails;
}

export default function OrganisationContactBlock({ organisation }: Props) {
return (
<section className="mb-6">
<h2 className="text-xl font-semibold mb-2">Contact</h2>
<p>
We do not currently have public contact details for {organisation.name}.
</p>
</section>
);
}
10 changes: 10 additions & 0 deletions src/components/OrganisationPage/OrganisationFooter.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
'use client';
import React from 'react';

export default function OrganisationFooter() {
return (
<footer className="mt-6 text-sm text-gray-600">
<p>Information provided by Street Support for demonstration purposes only.</p>
</footer>
);
}
29 changes: 29 additions & 0 deletions src/components/OrganisationPage/OrganisationLocations.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
'use client';
import React from 'react';
import type { OrganisationDetails } from '@/utils/organisation';
import GoogleMap from '@/components/MapComponent/GoogleMap';

interface Props {
organisation: OrganisationDetails;
}

export default function OrganisationLocations({ organisation }: Props) {
if (
organisation.latitude == null ||
organisation.longitude == null
) {
return null;
}

const center = { lat: organisation.latitude, lng: organisation.longitude };
const markers = [
{ id: organisation.id, lat: organisation.latitude, lng: organisation.longitude, title: organisation.name },
];

return (
<section className="mb-6">
<h2 className="text-xl font-semibold mb-2">Location</h2>
<GoogleMap center={center} markers={markers} zoom={14} />
</section>
);
}
31 changes: 31 additions & 0 deletions src/components/OrganisationPage/OrganisationOverview.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
'use client';
import React from 'react';
import type { OrganisationDetails } from '@/utils/organisation';

interface Props {
organisation: OrganisationDetails;
}

export default function OrganisationOverview({ organisation }: Props) {
const categories = Array.from(
new Set(organisation.services.map((s) => s.category))
);

return (
<section className="mb-6">
<h1 className="text-2xl font-bold mb-2">{organisation.name}</h1>
{categories.length > 0 && (
<div className="flex flex-wrap gap-2 mt-2">
{categories.map((cat) => (
<span
key={cat}
className="bg-brand-a text-white px-2 py-1 rounded text-sm"
>
{cat}
</span>
))}
</div>
)}
</section>
);
}
33 changes: 33 additions & 0 deletions src/components/OrganisationPage/OrganisationServicesAccordion.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
'use client';
import React from 'react';
import Accordion from '@/components/ui/Accordion';
import ServiceCard from '@/components/FindHelp/ServiceCard';
import type { OrganisationDetails } from '@/utils/organisation';

interface Props {
organisation: OrganisationDetails;
}

export default function OrganisationServicesAccordion({ organisation }: Props) {
const { groupedServices } = organisation;
const categories = Object.keys(groupedServices);

if (categories.length === 0) return null;

return (
<section className="mb-6">
<h2 className="text-xl font-semibold mb-4">Services</h2>
{categories.map((cat) => (
<Accordion key={cat} title={cat} className="mb-4">
<ul className="list-none p-0 m-0">
{groupedServices[cat].map((service) => (
<li key={service.id} className="mb-4">
<ServiceCard service={service} />
</li>
))}
</ul>
</Accordion>
))}
</section>
);
}
28 changes: 28 additions & 0 deletions src/utils/organisation.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
import providers from '@/data/service-providers.json';
import type { ServiceProvider, FlattenedService } from '@/types';

export interface OrganisationDetails extends ServiceProvider {
groupedServices: Record<string, FlattenedService[]>;
}

export function getOrganisationBySlug(slug: string): OrganisationDetails | null {
const list = providers as ServiceProvider[];
const provider = list.find((p) => p.slug === slug);
if (!provider) return null;

const grouped: Record<string, FlattenedService[]> = {};

if (Array.isArray(provider.services)) {
provider.services.forEach((s) => {
const cat = s.category || 'Other';
if (!grouped[cat]) grouped[cat] = [];
grouped[cat].push({
...s,
organisation: provider.name,
organisationSlug: provider.slug,
});
});
}

return { ...provider, groupedServices: grouped };
}
Loading