Add edit functionality for prayers and praises

This commit is contained in:
nmemmert committed 2025-10-23 16:51:11 -04:00
1 parent fdfc4f5f3d
commit aa3f42479f
2 files changed
+117 -55

No files matched your search

+1 -1
View File
@@ -1 +1 @@
if(!self.define){let e,s={};const n=(n,a)=>(n=new URL(n+".js",a).href,s[n]||new Promise(s=>{if("document"in self){const e=document.createElement("script");e.src=n,e.onload=s,document.head.appendChild(e)}else e=n,importScripts(n),s()}).then(()=>{let e=s[n];if(!e)throw new Error(`Module ${n} didn’t register its module`);return e}));self.define=(a,i)=>{const t=e||("document"in self?document.currentScript.src:"")||location.href;if(s[t])return;let c={};const f=e=>n(e,t),r={module:{uri:t},exports:c,require:f};s[t]=Promise.all(a.map(e=>r[e]||f(e))).then(e=>(i(...e),c))}}define(["./workbox-4754cb34"],function(e){"use strict";importScripts(),self.skipWaiting(),e.clientsClaim(),e.precacheAndRoute([{url:"/_next/static/Y4j-pLuzIB4ZdVSRsQP3m/_buildManifest.js",revision:"a91cb247fd17096d2ba17603cfdf5fe7"},{url:"/_next/static/Y4j-pLuzIB4ZdVSRsQP3m/_ssgManifest.js",revision:"b6652df95db52feb4daf4eca35380933"},{url:"/_next/static/chunks/104.b9111a893f0ad9d9.js",revision:"b9111a893f0ad9d9"},{url:"/_next/static/chunks/136-3bb757effc059d69.js",revision:"3bb757effc059d69"},{url:"/_next/static/chunks/139.678015000317a168.js",revision:"678015000317a168"},{url:"/_next/static/chunks/164f4fb6-a2df26e501616e62.js",revision:"a2df26e501616e62"},{url:"/_next/static/chunks/199.6d8b2513760bb8a6.js",revision:"6d8b2513760bb8a6"},{url:"/_next/static/chunks/2f0b94e8-4e6d0ae97e147ff2.js",revision:"4e6d0ae97e147ff2"},{url:"/_next/static/chunks/4bd1b696-b7529f9b306ab05d.js",revision:"b7529f9b306ab05d"},{url:"/_next/static/chunks/512-8d2b9de6fda25175.js",revision:"8d2b9de6fda25175"},{url:"/_next/static/chunks/646.30443a55a43a3bfb.js",revision:"30443a55a43a3bfb"},{url:"/_next/static/chunks/745-f204172863dcffd8.js",revision:"f204172863dcffd8"},{url:"/_next/static/chunks/7508b87c-580313408902bce8.js",revision:"580313408902bce8"},{url:"/_next/static/chunks/804.7f3d4655e2446c89.js",revision:"7f3d4655e2446c89"},{url:"/_next/static/chunks/931.6ff3e03b1cc8cdf1.js",revision:"6ff3e03b1cc8cdf1"},{url:"/_next/static/chunks/995.a093d11da39e25d3.js",revision:"a093d11da39e25d3"},{url:"/_next/static/chunks/ad2866b8.f49c70da33da3b7b.js",revision:"f49c70da33da3b7b"},{url:"/_next/static/chunks/app/_global-error/page-7ff1880bba064291.js",revision:"7ff1880bba064291"},{url:"/_next/static/chunks/app/_not-found/page-1123cfe416c748d0.js",revision:"1123cfe416c748d0"},{url:"/_next/static/chunks/app/api/send-email/route-7ff1880bba064291.js",revision:"7ff1880bba064291"},{url:"/_next/static/chunks/app/api/send-scheduled-emails/route-7ff1880bba064291.js",revision:"7ff1880bba064291"},{url:"/_next/static/chunks/app/layout-c9bbec85d61ab45b.js",revision:"c9bbec85d61ab45b"},{url:"/_next/static/chunks/app/page-20f1fcb41d90ea78.js",revision:"20f1fcb41d90ea78"},{url:"/_next/static/chunks/bc98253f.ac7fe72f9e73e374.js",revision:"ac7fe72f9e73e374"},{url:"/_next/static/chunks/dd8162e8-bea2cd35813297c3.js",revision:"bea2cd35813297c3"},{url:"/_next/static/chunks/framework-292291387d6b2e39.js",revision:"292291387d6b2e39"},{url:"/_next/static/chunks/main-7ddb690de3906442.js",revision:"7ddb690de3906442"},{url:"/_next/static/chunks/main-app-4f19d69ed4295336.js",revision:"4f19d69ed4295336"},{url:"/_next/static/chunks/next/dist/client/components/builtin/app-error-7ff1880bba064291.js",revision:"7ff1880bba064291"},{url:"/_next/static/chunks/next/dist/client/components/builtin/forbidden-7ff1880bba064291.js",revision:"7ff1880bba064291"},{url:"/_next/static/chunks/next/dist/client/components/builtin/global-error-bcba0732671665d2.js",revision:"bcba0732671665d2"},{url:"/_next/static/chunks/next/dist/client/components/builtin/not-found-7ff1880bba064291.js",revision:"7ff1880bba064291"},{url:"/_next/static/chunks/next/dist/client/components/builtin/unauthorized-7ff1880bba064291.js",revision:"7ff1880bba064291"},{url:"/_next/static/chunks/polyfills-42372ed130431b0a.js",revision:"846118c33b2c0e922d7b3a7676f81f6f"},{url:"/_next/static/chunks/webpack-8c242ea63ddea351.js",revision:"8c242ea63ddea351"},{url:"/_next/static/css/1d32dd5f31643a1d.css",revision:"1d32dd5f31643a1d"},{url:"/_next/static/media/4cf2300e9c8272f7-s.p.woff2",revision:"18bae71b1e1b2bb25321090a3b563103"},{url:"/_next/static/media/747892c23ea88013-s.woff2",revision:"a0761690ccf4441ace5cec893b82d4ab"},{url:"/_next/static/media/8d697b304b401681-s.woff2",revision:"cc728f6c0adb04da0dfcb0fc436a8ae5"},{url:"/_next/static/media/93f479601ee12b01-s.p.woff2",revision:"da83d5f06d825c5ae65b7cca706cb312"},{url:"/_next/static/media/9610d9e46709d722-s.woff2",revision:"7b7c0ef93df188a852344fc272fc096b"},{url:"/_next/static/media/ba015fad6dcf6784-s.woff2",revision:"8ea4f719af3312a055caf09f34c89a77"},{url:"/file.svg",revision:"d09f95206c3fa0bb9bd9fefabfd0ea71"},{url:"/firebase-messaging-sw.js",revision:"04d66892653ef67e1151f1ec6c02420b"},{url:"/globe.svg",revision:"2aaafa6a49b6563925fe440891e32717"},{url:"/icon-192x192.png",revision:"bbbd7efc0e31088ae0a3aeede7608534"},{url:"/icon-512x512.png",revision:"400538d76556a3a8ee4fd3dfda7bc092"},{url:"/locales/en/commonLine truncated if(!self.define){let e,s={};const n=(n,a)=>(n=new URL(n+".js",a).href,s[n]||new Promise(s=>{if("document"in self){const e=document.createElement("script");e.src=n,e.onload=s,document.head.appendChild(e)}else e=n,importScripts(n),s()}).then(()=>{let e=s[n];if(!e)throw new Error(`Module ${n} didn’t register its module`);return e}));self.define=(a,i)=>{const t=e||("document"in self?document.currentScript.src:"")||location.href;if(s[t])return;let c={};const r=e=>n(e,t),f={module:{uri:t},exports:c,require:r};s[t]=Promise.all(a.map(e=>f[e]||r(e))).then(e=>(i(...e),c))}}define(["./workbox-4754cb34"],function(e){"use strict";importScripts(),self.skipWaiting(),e.clientsClaim(),e.precacheAndRoute([{url:"/_next/static/AM_vEQgIshalV3dcCH-v2/_buildManifest.js",revision:"a91cb247fd17096d2ba17603cfdf5fe7"},{url:"/_next/static/AM_vEQgIshalV3dcCH-v2/_ssgManifest.js",revision:"b6652df95db52feb4daf4eca35380933"},{url:"/_next/static/chunks/104.b9111a893f0ad9d9.js",revision:"b9111a893f0ad9d9"},{url:"/_next/static/chunks/136-3bb757effc059d69.js",revision:"3bb757effc059d69"},{url:"/_next/static/chunks/139.678015000317a168.js",revision:"678015000317a168"},{url:"/_next/static/chunks/164f4fb6-a2df26e501616e62.js",revision:"a2df26e501616e62"},{url:"/_next/static/chunks/199.6d8b2513760bb8a6.js",revision:"6d8b2513760bb8a6"},{url:"/_next/static/chunks/2f0b94e8-4e6d0ae97e147ff2.js",revision:"4e6d0ae97e147ff2"},{url:"/_next/static/chunks/4bd1b696-b7529f9b306ab05d.js",revision:"b7529f9b306ab05d"},{url:"/_next/static/chunks/512-8d2b9de6fda25175.js",revision:"8d2b9de6fda25175"},{url:"/_next/static/chunks/646.30443a55a43a3bfb.js",revision:"30443a55a43a3bfb"},{url:"/_next/static/chunks/745-f204172863dcffd8.js",revision:"f204172863dcffd8"},{url:"/_next/static/chunks/7508b87c-580313408902bce8.js",revision:"580313408902bce8"},{url:"/_next/static/chunks/804.7f3d4655e2446c89.js",revision:"7f3d4655e2446c89"},{url:"/_next/static/chunks/931.6ff3e03b1cc8cdf1.js",revision:"6ff3e03b1cc8cdf1"},{url:"/_next/static/chunks/995.a093d11da39e25d3.js",revision:"a093d11da39e25d3"},{url:"/_next/static/chunks/ad2866b8.f49c70da33da3b7b.js",revision:"f49c70da33da3b7b"},{url:"/_next/static/chunks/app/_global-error/page-7ff1880bba064291.js",revision:"7ff1880bba064291"},{url:"/_next/static/chunks/app/_not-found/page-1123cfe416c748d0.js",revision:"1123cfe416c748d0"},{url:"/_next/static/chunks/app/api/send-email/route-7ff1880bba064291.js",revision:"7ff1880bba064291"},{url:"/_next/static/chunks/app/api/send-scheduled-emails/route-7ff1880bba064291.js",revision:"7ff1880bba064291"},{url:"/_next/static/chunks/app/layout-c9bbec85d61ab45b.js",revision:"c9bbec85d61ab45b"},{url:"/_next/static/chunks/app/page-db2e38321401f568.js",revision:"db2e38321401f568"},{url:"/_next/static/chunks/bc98253f.ac7fe72f9e73e374.js",revision:"ac7fe72f9e73e374"},{url:"/_next/static/chunks/dd8162e8-bea2cd35813297c3.js",revision:"bea2cd35813297c3"},{url:"/_next/static/chunks/framework-292291387d6b2e39.js",revision:"292291387d6b2e39"},{url:"/_next/static/chunks/main-7ddb690de3906442.js",revision:"7ddb690de3906442"},{url:"/_next/static/chunks/main-app-4f19d69ed4295336.js",revision:"4f19d69ed4295336"},{url:"/_next/static/chunks/next/dist/client/components/builtin/app-error-7ff1880bba064291.js",revision:"7ff1880bba064291"},{url:"/_next/static/chunks/next/dist/client/components/builtin/forbidden-7ff1880bba064291.js",revision:"7ff1880bba064291"},{url:"/_next/static/chunks/next/dist/client/components/builtin/global-error-bcba0732671665d2.js",revision:"bcba0732671665d2"},{url:"/_next/static/chunks/next/dist/client/components/builtin/not-found-7ff1880bba064291.js",revision:"7ff1880bba064291"},{url:"/_next/static/chunks/next/dist/client/components/builtin/unauthorized-7ff1880bba064291.js",revision:"7ff1880bba064291"},{url:"/_next/static/chunks/polyfills-42372ed130431b0a.js",revision:"846118c33b2c0e922d7b3a7676f81f6f"},{url:"/_next/static/chunks/webpack-8c242ea63ddea351.js",revision:"8c242ea63ddea351"},{url:"/_next/static/css/ad9b900c70cc4212.css",revision:"ad9b900c70cc4212"},{url:"/_next/static/media/4cf2300e9c8272f7-s.p.woff2",revision:"18bae71b1e1b2bb25321090a3b563103"},{url:"/_next/static/media/747892c23ea88013-s.woff2",revision:"a0761690ccf4441ace5cec893b82d4ab"},{url:"/_next/static/media/8d697b304b401681-s.woff2",revision:"cc728f6c0adb04da0dfcb0fc436a8ae5"},{url:"/_next/static/media/93f479601ee12b01-s.p.woff2",revision:"da83d5f06d825c5ae65b7cca706cb312"},{url:"/_next/static/media/9610d9e46709d722-s.woff2",revision:"7b7c0ef93df188a852344fc272fc096b"},{url:"/_next/static/media/ba015fad6dcf6784-s.woff2",revision:"8ea4f719af3312a055caf09f34c89a77"},{url:"/file.svg",revision:"d09f95206c3fa0bb9bd9fefabfd0ea71"},{url:"/firebase-messaging-sw.js",revision:"04d66892653ef67e1151f1ec6c02420b"},{url:"/globe.svg",revision:"2aaafa6a49b6563925fe440891e32717"},{url:"/icon-192x192.png",revision:"bbbd7efc0e31088ae0a3aeede7608534"},{url:"/icon-512x512.png",revision:"400538d76556a3a8ee4fd3dfda7bc092"},{url:"/locales/en/commonLine truncated
+116 -54
View File
@@ -46,6 +46,7 @@ export default function Home() {
const itemsPerPage = 10; const itemsPerPage = 10;
const { user, loading, logout, isAdmin } = useAuth(); const { user, loading, logout, isAdmin } = useAuth();
const [showLoadingScreen, setShowLoadingScreen] = useState(true); const [showLoadingScreen, setShowLoadingScreen] = useState(true);
const [editingPrayer, setEditingPrayer] = useState<Prayer | null>(null);
// Ensure loading screen shows for at least 5 seconds // Ensure loading screen shows for at least 5 seconds
useEffect(() => { useEffect(() => {
@@ -187,7 +188,7 @@ export default function Home() {
} }
try { try {
const newPrayerData = { const prayerData = {
userId: user.uid, userId: user.uid,
date: form.date, date: form.date,
type: form.type, type: form.type,
@@ -197,63 +198,76 @@ export default function Home() {
prayFor: form.prayFor, prayFor: form.prayFor,
reminderFrequency: form.reminderFrequency, reminderFrequency: form.reminderFrequency,
includeActiveSummary: form.includeActiveSummary, includeActiveSummary: form.includeActiveSummary,
archived: false, archived: editingPrayer ? editingPrayer.archived : false,
}; };
// Save to Firestore if (editingPrayer) {
const docRef = await addDoc(collection(db, 'prayers'), newPrayerData); // Update existing prayer
await updateDoc(doc(db, 'prayers', editingPrayer.id), prayerData);
// Add to local state with Firestore ID
const newPrayer: Prayer = {
id: docRef.id,
...newPrayerData,
};
setPrayers(prev => [...prev, newPrayer]);
// Store user reminder preferences in Firestore
if (form.reminderFrequency !== 'never') {
await setDoc(doc(db, 'users', user.uid), {
email: form.email,
reminderFrequency: form.reminderFrequency,
includeActiveSummary: form.includeActiveSummary,
lastEmailSent: null,
}, { merge: true });
console.log('✅ Reminder preferences saved'); // Update local state
} setPrayers(prev => prev.map(p =>
p.id === editingPrayer.id ? { ...p, ...prayerData } : p
// Send immediate email using EmailJS if reminder frequency is set ));
if (form.reminderFrequency !== 'never' && form.email) {
try { // Reset editing state
// EmailJS configuration - you'll need to set these up at emailjs.com setEditingPrayer(null);
const serviceId = process.env.NEXT_PUBLIC_EMAILJS_SERVICE_ID || 'your_service_id'; } else {
const templateId = process.env.NEXT_PUBLIC_EMAILJS_TEMPLATE_ID || 'your_template_id'; // Add new prayer
const publicKey = process.env.NEXT_PUBLIC_EMAILJS_PUBLIC_KEY || 'your_public_key'; const docRef = await addDoc(collection(db, 'prayers'), prayerData);
// Add to local state with Firestore ID
const newPrayer: Prayer = {
id: docRef.id,
...prayerData,
};
setPrayers(prev => [...prev, newPrayer]);
// Store user reminder preferences in Firestore
if (form.reminderFrequency !== 'never') {
await setDoc(doc(db, 'users', user.uid), {
email: form.email,
reminderFrequency: form.reminderFrequency,
includeActiveSummary: form.includeActiveSummary,
lastEmailSent: null,
}, { merge: true });
const templateParams = { console.log('✅ Reminder preferences saved');
to_email: form.email, }
from_name: 'Prayer App',
to_name: user.displayName || user.email?.split('@')[0] || 'Prayer User', // Send immediate email using EmailJS if reminder frequency is set
subject: `New ${form.type} added - ${form.reminderFrequency} reminders enabled`, if (form.reminderFrequency !== 'never' && form.email) {
message: `Date: ${form.date}\n\n${form.text}\n\nJournal: ${form.journal || 'None'}${form.prayFor ? `\n\nPraying for: ${form.prayFor}` : ''}`, try {
prayer_type: form.type, // EmailJS configuration - you'll need to set these up at emailjs.com
prayer_date: form.date, const serviceId = process.env.NEXT_PUBLIC_EMAILJS_SERVICE_ID || 'your_service_id';
prayer_text: form.text, const templateId = process.env.NEXT_PUBLIC_EMAILJS_TEMPLATE_ID || 'your_template_id';
prayer_journal: form.journal || 'None', const publicKey = process.env.NEXT_PUBLIC_EMAILJS_PUBLIC_KEY || 'your_public_key';
praying_for: form.prayFor || 'Not specified',
reminder_frequency: form.reminderFrequency, const templateParams = {
}; to_email: form.email,
from_name: 'Prayer App',
to_name: user.displayName || user.email?.split('@')[0] || 'Prayer User',
subject: `New ${form.type} added - ${form.reminderFrequency} reminders enabled`,
message: `Date: ${form.date}\n\n${form.text}\n\nJournal: ${form.journal || 'None'}${form.prayFor ? `\n\nPraying for: ${form.prayFor}` : ''}`,
prayer_type: form.type,
prayer_date: form.date,
prayer_text: form.text,
prayer_journal: form.journal || 'None',
praying_for: form.prayFor || 'Not specified',
reminder_frequency: form.reminderFrequency,
};
// Only send if EmailJS is properly configured // Only send if EmailJS is properly configured
if (serviceId !== 'your_service_id' && templateId !== 'your_template_id' && publicKey !== 'your_public_key') { if (serviceId !== 'your_service_id' && templateId !== 'your_template_id' && publicKey !== 'your_public_key') {
await emailjs.send(serviceId, templateId, templateParams, publicKey); await emailjs.send(serviceId, templateId, templateParams, publicKey);
console.log('✅ Email sent via EmailJS'); console.log('✅ Email sent via EmailJS');
} else { } else {
console.log('ℹ️ EmailJS not configured - email sending skipped (this is normal)'); console.log('ℹ️ EmailJS not configured - email sending skipped (this is normal)');
}
} catch (emailError) {
console.error('❌ EmailJS error:', emailError);
// Don't fail the prayer submission if email fails
} }
} catch (emailError) {
console.error('❌ EmailJS error:', emailError);
// Don't fail the prayer submission if email fails
} }
} }
@@ -408,6 +422,37 @@ export default function Home() {
} }
}; };
// Start editing a prayer
const startEditing = (prayer: Prayer) => {
setEditingPrayer(prayer);
setForm({
date: prayer.date,
type: prayer.type,
text: prayer.text,
journal: prayer.journal || '',
email: prayer.email,
prayFor: prayer.prayFor || '',
reminderFrequency: prayer.reminderFrequency || 'never',
includeActiveSummary: prayer.includeActiveSummary || false,
});
setActiveTab('add'); // Switch to add tab to show form
};
// Cancel editing
const cancelEditing = () => {
setEditingPrayer(null);
setForm({
date: new Date().toISOString().split('T')[0],
type: 'prayer',
text: '',
journal: '',
email: user?.email || '',
prayFor: '',
reminderFrequency: 'never',
includeActiveSummary: false,
});
};
if (loading || showLoadingScreen) { if (loading || showLoadingScreen) {
return ( return (
<div className="min-h-screen bg-gradient-to-br from-gray-900 via-black to-gray-800 flex items-center justify-center p-4"> <div className="min-h-screen bg-gradient-to-br from-gray-900 via-black to-gray-800 flex items-center justify-center p-4">
@@ -469,7 +514,8 @@ export default function Home() {
<div> <div>
<h1 className="text-3xl font-bold">Prayer App</h1> <h1 className="text-3xl font-bold">Prayer App</h1>
<p className="text-gray-400 text-sm mt-1"> <p className="text-gray-400 text-sm mt-1">
{activeTab === 'add' ? 'Add New Prayer or Praise' : {editingPrayer ? 'Edit Prayer or Praise' :
activeTab === 'add' ? 'Add New Prayer or Praise' :
activeTab === 'search' ? 'Search Results' : activeTab === 'search' ? 'Search Results' :
`${activeTab.charAt(0).toUpperCase() + activeTab.slice(1)} Prayers`} `${activeTab.charAt(0).toUpperCase() + activeTab.slice(1)} Prayers`}
</p> </p>
@@ -623,8 +669,17 @@ export default function Home() {
</div> </div>
<button type="submit" className="w-full p-4 bg-blue-600 hover:bg-blue-700 rounded text-lg font-semibold mt-6"> <button type="submit" className="w-full p-4 bg-blue-600 hover:bg-blue-700 rounded text-lg font-semibold mt-6">
Add Entry {editingPrayer ? 'Update Entry' : 'Add Entry'}
</button> </button>
{editingPrayer && (
<button
type="button"
onClick={cancelEditing}
className="w-full p-4 bg-gray-600 hover:bg-gray-700 rounded text-lg font-semibold mt-2"
>
Cancel Editing
</button>
)}
</form> </form>
)} )}
@@ -681,6 +736,13 @@ export default function Home() {
> >
🌍 Community 🌍 Community
</button> </button>
<button
onClick={() => startEditing(prayer)}
className="px-3 py-2 bg-yellow-600 hover:bg-yellow-700 text-white text-sm font-medium rounded-lg flex items-center gap-2 transition-all duration-200 shadow-md hover:shadow-lg"
title="Edit this prayer"
>
✏️ Edit
</button>
</div> </div>
</div> </div>
<p className="mb-2">{prayer.text}</p> <p className="mb-2">{prayer.text}</p>