8000 Footers for tenants by rchlfryn · Pull Request #201 · NWACus/web · GitHub
[go: up one dir, main page]
More Web Proxy on the site http://driver.im/
Skip to content

Footers for tenants #201

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 13 commits into
base: main
Choose a base branch
from
Open
87 changes: 72 additions & 15 deletions src/Footer/Component.tsx
Original file line number Diff line number Diff line change
@@ -1,27 +1,84 @@
import { getCachedGlobal } from '@/utilities/getGlobals'
import configPromise from '@payload-config'
import Link from 'next/link'
import invariant from 'tiny-invariant'

import { CMSLink } from '@/components/Link'
import { Logo } from '@/components/Logo/Logo'
import { ImageMedia } from '@/components/Media/ImageMedia'
import { Icons } from '@/components/ui/icons'
import { getPayload } from 'payload'

export async function Footer({ center }: { center?: string }) {
< 10000 /td> const footerData = await getCachedGlobal('footer', 1)()
const payload = await getPayload({ config: configPromise })
const { docs: data } = await payload.find({
collection: 'footer',
depth: 10,
where: {
'tenant.slug': {
equals: center,
},
},
})
const { address, email, hashtag, footerLogo, name, phone, privacy, socialMedia, terms } =
data?.[0]

const navItems = footerData?.navItems || []
invariant(
typeof terms === 'object',
`Depth not set correctly when querying footer. Terms for tenant ${center} not an object.`,
)

invariant(
typeof privacy === 'object',
`Depth not set correctly when querying footer. Privacy for tenant ${center} not an object.`,
)
return (
<footer className="mt-auto border-t border-border bg-footer text-footer-foreground">
<div className="container py-8 gap-8 flex flex-col md:flex-row md:justify-between">
<Link className="flex items-center" href="/">
<Logo center={center} />
</Link>

<div className="flex flex-col-reverse items-start md:flex-row gap-4 md:items-center">
<nav className="flex flex-col md:flex-row gap-4">
{navItems.map(({ link }, i) => {
return <CMSLink className="text-footer-foreground" key={i} {...link} />
})}
</nav>
<div className="container py-8 gap-8 grid grid-cols-3">
<div>
<h4 className="font-medium text-xl mb-2">Stay updated!</h4>
<p>Sign up for our newsletter</p>
</div>
<div>
<Link className="flex items-center" href="/">
{footerLogo ? <ImageMedia resource={footerLogo} /> : <Logo center={center} />}
</Link>
</div>
<div>
<div className="flex flex-col items-start">
<h4 className="font-medium text-xl mb-2">{name}</h4>
{address && <div className="whitespace-pre-line">{address}</div>}
{phone && <a href={`tel:${phone}`}>{phone}</a>}
{email && (
<a className="mb-6 text-secondary underline" href={`mailto:${email}`}>
{email}
</a>
)}
{socialMedia && (
<div className="flex gap-x-4 mb-2">
{socialMedia.instagram && <Icons.instagram />}
{socialMedia.facebook && <Icons.facebook />}
{socialMedia.twitter && <Icons.twitter />}
{socialMedia.linkedin && <Icons.linkedin />}
{socialMedia.youtube && <Icons.youtube />}
</div>
)}
{hashtag && <p className="mb-4 text-secondary underline">{hashtag}</p>}
</div>
</div>
</div>
<div className="container text-center pb-8">
<p className="mb-2">All Content © 2017 – 2025 {name}</p>
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How did we come up with these dates, and who owns the copyright? Do we want the end date to be dynamic from new Date() so we don't need to update it?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These were in the mocks which appears to be taken from the current website. And it's common to use a span to show the years of publication. I typically just use new Date() to show the current year, but this might be a Rusty question.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Gotcha - yeah, let's check to see if we can be dynamic, that would be nice to have.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It would be nice to include this in a settings collection I think. Could default to just current year if there isn't a start year set. I don't know how we would refer to that. Content copyright starting year?

<div className="flex gap-x-2 justify-center">
{terms && (
<a href={`/${terms.slug}`} className="underline">
{terms.title}
</a>
)}
{terms && privacy && <div>|</div>}
{privacy && (
<a href={`/${privacy?.slug}`} className="underline">
{privacy?.title}
</a>
)}
</div>
</div>
</footer>
Expand Down
13 changes: 0 additions & 13 deletions src/Footer/RowLabel.tsx

This file was deleted.

32 changes: 0 additions & 32 deletions src/Footer/config.ts

This file was deleted.

2 changes: 0 additions & 2 deletions src/app/(payload)/admin/importMap.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@ import { default as default_55a7d1ebef7afeed563b856ae2e2 6D4E cbf4 } from '@/component
import { default as default_9d7720c4b50db35595dfefa592fabd33 } from '@/components/TenantSelector'
import { LinkLabelDescription as LinkLabelDescription_cc2cf53f1598892c0c926f3cb616a721 } from '@/fields/navLink/components/LinkLabelDescription'
import { SlugComponent as SlugComponent_92cc057d0a2abb4f6cf0307edf59f986 } from '@/fields/slug/SlugComponent'
import { RowLabel as RowLabel_1f6ff6ff633e3695d348f4f3c58f1466 } from '@/Footer/RowLabel'
import { TenantField as TenantField_1d0591e3cf4f332c83a86da13a0de59a } from '@payloadcms/plugin-multi-tenant/client'
import {
GlobalViewRedirect as GlobalViewRedirect_d6d5f193a167989e2ee7d14202901e62,
Expand Down Expand Up @@ -90,7 +89,6 @@ export const importMap = {
LinkLabelDescription_cc2cf53f1598892c0c926f3cb616a721,
'@payloadcms/plugin-search/client#LinkToDoc': LinkToDoc_aead06e4cbf6b2620c5c51c9ab283634,
'@payloadcms/plugin-search/client#ReindexButton': ReindexButton_aead06e4cbf6b2620c5c51c9ab283634,
'@/Footer/RowLabel#RowLabel': RowLabel_1f6ff6ff633e3695d348f4f3c58f1466,
'@payloadcms/plugin-multi-tenant/rsc#GlobalViewRedirect':
GlobalViewRedirect_d6d5f193a167989e2ee7d14202901e62,
'@/components/BeforeDashboard#default': default_1a7510af427896d367a49dbf838d2de6,
Expand Down
154 changes: 154 additions & 0 deletions src/collections/Footer/config.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,154 @@
import { accessByTenant } from '@/access/byTenant'
import { filterByTenant } from '@/access/filterByTenant'
import { contentHashField } from '@/fields/contentHashField'
import { tenantField } from '@/fields/tenantField'
import { generatePreviewPath } from '@/utilities/generatePreviewPath'
import type { CollectionConfig, TextFieldValidation } from 'payload'

const validateHashtag: TextFieldValidation = (value: string | null | undefined): string | true => {
return value
? /^#[A-Za-z0-9_](?:[A-Za-z0-9_]|(?:\.(?!\.))){0,28}[A-Za-z0-9_]$/.test(value) ||
`${value} is not a valid hashtag`
: true
}

const validateTelephone: TextFieldValidation = (
value: string | null | undefined,
): string | true => {
return value
? /^(\+1\s?|1\s?)?(\(\d{3}\)|\d{3})[\s.-]?\d{3}[\s.-]?\d{4}$/.test(value) ||
`${value} is not a valid phone number`
: true
}

export const Footer: CollectionConfig = {
slug: 'footer',
access: accessByTenant('footer'),
admin: {
// the GlobalViewRedirect will never allow a user to visit the list view of this collection but including this list filter as a precaution
baseListFilter: filterByTenant,
group: 'Globals',
livePreview: {
url: async ({ data, req, payload }) => {
let tenant = data.tenant

if (typeof tenant === 'number') {
tenant = await payload.findByID({
collection: 'tenants',
id: tenant,
depth: 2,
})
}

const path = generatePreviewPath({
slug: '',
collection: 'pages',
tenant,
req,
})

return path
},
},
},
fields: [
tenantField({ unique: true }),
{
name: 'footerLogo',
type: 'upload',
relationTo: 'media',
filterOptions: {
mimeType: { contains: 'image' },
},
},
{
name: 'name',
type: 'text',
required: true,
},
{
name: 'address',
type: 'textarea',
},
{
name: 'phone',
type: 'text',
validate: validateTelephone,
},
{
name: 'email',
type: 'email',
},
{
name: 'socialMedia',
type: 'group',
fields: [
{
type: 'row',
fields: [
{
name: 'instagram',
type: 'text',
admin: {
width: '33%',
},
},
{
name: 'facebook',
type: 'text',
admin: {
width: '33%',
},
},
{
name: 'twitter',
type: 'text',
admin: {
width: '33%',
},
},
],
},
{
type: 'row',
fields: [
{
name: 'linkedin',
type: 'text',
admin: {
width: '33%',
},
},
{
name: 'youtube',
type: 'text',
admin: {
width: '33%',
},
},
],
},
],
admin: {
description:
'Add link to social media page to have the icon appear in the footer. Leave the field blank if you do not want the icon to show.',
},
},
{
name: 'hashtag',
type: 'text',
validate: validateHashtag,
},
{
name: 'terms',
type: 'relationship',
relationTo: 'pages',
},
{
name: 'privacy',
type: 'relationship',
relationTo: 'pages',
},
contentHashField(),
],
}
Loading
0