diff --git a/src/app/(frontend)/PastorsTable.tsx b/src/app/(frontend)/PastorsTable.tsx index b87a8af..6bc1fc1 100644 --- a/src/app/(frontend)/PastorsTable.tsx +++ b/src/app/(frontend)/PastorsTable.tsx @@ -8,27 +8,206 @@ import { createPastor, updatePastor, uploadLetter } from './actions' export type PastorRow = { id: number name: string + churchName: string | null email: string | null telephone: string[] + place: string | null city: string | null state: string | null country: string | null countryName: string | null countryFlag: string + impactedPeople: number | null inTelegram: boolean notes: string | null letterUrl: string | null letterName: string | null } +const dash = + +type ColumnKey = + | 'name' + | 'churchName' + | 'email' + | 'telephone' + | 'place' + | 'city' + | 'state' + | 'country' + | 'impactedPeople' + | 'inTelegram' + | 'letter' + export function PastorsTable({ rows }: { rows: PastorRow[] }) { const [editing, setEditing] = useState(null) const [uploading, setUploading] = useState(null) const [creating, setCreating] = useState(false) + const columns: { + key: ColumnKey + label: string + align?: 'center' | 'right' + cell: (p: PastorRow) => React.ReactNode + }[] = [ + { + key: 'name', + label: 'Nombre', + cell: (p) => {p.name}, + }, + { + key: 'churchName', + label: 'Iglesia', + cell: (p) => {p.churchName || dash}, + }, + { + key: 'email', + label: 'Correo', + cell: (p) => + p.email ? ( + + {p.email} + + ) : ( + dash + ), + }, + { + key: 'telephone', + label: 'Teléfonos', + cell: (p) => + p.telephone.length ? ( +
+ {p.telephone.map((t, i) => ( + + {t} + + ))} +
+ ) : ( + dash + ), + }, + { + key: 'place', + label: 'Lugar', + cell: (p) => {p.place || dash}, + }, + { + key: 'city', + label: 'Ciudad', + cell: (p) => {p.city || dash}, + }, + { + key: 'state', + label: 'Estado', + cell: (p) => {p.state || dash}, + }, + { + key: 'country', + label: 'País', + cell: (p) => + p.countryName ? ( + + {p.countryFlag} {p.countryName} + + ) : ( + dash + ), + }, + { + key: 'impactedPeople', + label: 'Personas impactadas', + align: 'right', + cell: (p) => + p.impactedPeople === null ? dash : p.impactedPeople.toLocaleString('es'), + }, + { + key: 'inTelegram', + label: 'Telegram', + align: 'center', + cell: (p) => + p.inTelegram ? ( + + ) : ( + No + ), + }, + { + key: 'letter', + label: 'Carta', + cell: (p) => + p.letterUrl ? ( + + Descargar + + ) : ( + + ), + }, + ] + + // Column visibility — all shown by default; toggled via the "Columnas" menu. + const [visible, setVisible] = useState>( + () => Object.fromEntries(columns.map((c) => [c.key, true])) as Record, + ) + const shown = columns.filter((c) => visible[c.key]) + const alignClass = (a?: 'center' | 'right') => + a === 'center' ? 'text-center' : a === 'right' ? 'text-right' : '' + return ( <> -
+
+
+ +
    + {columns.map((c) => ( +
  • + +
  • + ))} +
+
@@ -43,96 +222,48 @@ export function PastorsTable({ rows }: { rows: PastorRow[] }) {
) : (
- - - - - - - - - - - - - - - {rows.map((p) => ( - - - - - - - - + + ))} + +
NombreCorreoTeléfonosCiudadPaísTelegramCartaAcciones
{p.name} - {p.email ? ( - - {p.email} - - ) : ( - - )} - - {p.telephone.length ? ( -
- {p.telephone.map((t, i) => ( - - {t} - - ))} -
- ) : ( - - )} -
{p.city || } - {p.countryName ? ( - - {p.countryFlag} {p.countryName} - - ) : ( - - )} - - {p.inTelegram ? ( - - ) : ( - No - )} - - {p.letterUrl ? ( - - Descargar - - ) : ( + + + + {shown.map((c) => ( + + ))} + + + + + {rows.map((p) => ( + + {shown.map((c) => ( + + ))} + - - - ))} - -
+ {c.label} + Acciones
+ {c.cell(p)} + - )} - - -
+
)} @@ -158,13 +289,18 @@ function PastorModal({ pastor, onClose }: { pastor: PastorRow | null; onClose: ( const [error, setError] = useState(null) const [name, setName] = useState(pastor?.name ?? '') + const [churchName, setChurchName] = useState(pastor?.churchName ?? '') const [email, setEmail] = useState(pastor?.email ?? '') const [phones, setPhones] = useState( pastor?.telephone.length ? pastor.telephone : [''], ) + const [place, setPlace] = useState(pastor?.place ?? '') const [city, setCity] = useState(pastor?.city ?? '') const [state, setState] = useState(pastor?.state ?? '') const [country, setCountry] = useState(pastor?.country ?? '') + const [impactedPeople, setImpactedPeople] = useState( + pastor?.impactedPeople != null ? String(pastor.impactedPeople) : '', + ) const [inTelegram, setInTelegram] = useState(pastor?.inTelegram ?? false) const [notes, setNotes] = useState(pastor?.notes ?? '') @@ -177,7 +313,19 @@ function PastorModal({ pastor, onClose }: { pastor: PastorRow | null; onClose: ( e.preventDefault() setError(null) startTransition(async () => { - const input = { name, email, telephone: phones, city, state, country, inTelegram, notes } + const input = { + name, + churchName, + email, + telephone: phones, + place, + city, + state, + country, + impactedPeople: impactedPeople.trim() === '' ? null : Number(impactedPeople), + inTelegram, + notes, + } const res = isCreate ? await createPastor(input) : await updatePastor(pastor.id, input) if (res?.ok) { router.refresh() @@ -213,6 +361,17 @@ function PastorModal({ pastor, onClose }: { pastor: PastorRow | null; onClose: ( required /> + + setChurchName(e.target.value)} + /> + @@ -252,6 +411,16 @@ function PastorModal({ pastor, onClose }: { pastor: PastorRow | null; onClose: (
+ + setPlace(e.target.value)} + /> + @@ -287,6 +456,18 @@ function PastorModal({ pastor, onClose }: { pastor: PastorRow | null; onClose: ( Código ISO de 2 letras + + setImpactedPeople(e.target.value)} + /> + En Telegram t.trim()).filter(Boolean), + churchName: data.churchName || undefined, + place: data.place || undefined, city: data.city || undefined, state: data.state || undefined, country: data.country ? data.country.trim().toUpperCase() : undefined, + impactedPeople: + data.impactedPeople === null || data.impactedPeople === undefined + ? undefined + : Number(data.impactedPeople), inTelegram: Boolean(data.inTelegram), notes: data.notes || undefined, }, @@ -53,9 +62,15 @@ export async function updatePastor(id: number, data: PastorUpdateInput) { name: data.name, email: data.email || undefined, telephone: (data.telephone ?? []).map((t) => t.trim()).filter(Boolean), + churchName: data.churchName || undefined, + place: data.place || undefined, city: data.city || undefined, state: data.state || undefined, country: data.country ? data.country.trim().toUpperCase() : undefined, + impactedPeople: + data.impactedPeople === null || data.impactedPeople === undefined + ? undefined + : Number(data.impactedPeople), inTelegram: Boolean(data.inTelegram), notes: data.notes || undefined, }, diff --git a/src/app/(frontend)/page.tsx b/src/app/(frontend)/page.tsx index 2aae637..c5748e8 100644 --- a/src/app/(frontend)/page.tsx +++ b/src/app/(frontend)/page.tsx @@ -66,13 +66,16 @@ export default async function HomePage({ return { id: p.id, name: p.name, + churchName: p.churchName ?? null, email: p.email ?? null, telephone: Array.isArray(p.telephone) ? p.telephone.filter(Boolean) : [], + place: p.place ?? null, city: p.city ?? null, state: p.state ?? null, country: p.country ?? null, countryName: localizedCountry(p.country), countryFlag: flag(p.country), + impactedPeople: p.impactedPeople ?? null, inTelegram: Boolean(p.inTelegram), notes: p.notes ?? null, letterUrl: letter?.url ?? null, diff --git a/src/collections/Pastors.ts b/src/collections/Pastors.ts index 9dcdc89..712aab6 100644 --- a/src/collections/Pastors.ts +++ b/src/collections/Pastors.ts @@ -20,6 +20,10 @@ export const Pastors: CollectionConfig = { label: 'Church Name', type: 'text', }, + { + name: 'place', + type: 'text', + }, { name: 'city', type: 'text', diff --git a/src/payload-types.ts b/src/payload-types.ts index 049c712..35dca7d 100644 --- a/src/payload-types.ts +++ b/src/payload-types.ts @@ -224,6 +224,7 @@ export interface Pastor { id: number; name: string; churchName?: string | null; + place?: string | null; city?: string | null; state?: string | null; /** @@ -428,6 +429,7 @@ export interface TagsSelect { export interface PastorsSelect { name?: T; churchName?: T; + place?: T; city?: T; state?: T; country?: T;