diff --git a/backend/composer.json b/backend/composer.json
index 510bf43..3b9808d 100644
--- a/backend/composer.json
+++ b/backend/composer.json
@@ -32,7 +32,8 @@
},
"autoload": {
"psr-4": {
- "modules\\": "modules/"
+ "modules\\": "modules/",
+ "backend\\": "."
}
},
"config": {
diff --git a/backend/config/app.php b/backend/config/app.php
index 385f401..3047579 100644
--- a/backend/config/app.php
+++ b/backend/config/app.php
@@ -24,4 +24,8 @@
return [
'id' => App::env('CRAFT_APP_ID') ?: 'CraftCMS',
+ 'modules' => [
+ 'authorinfo' => modules\authorinfo\Module::class,
+ ],
+ 'bootstrap' => ['authorinfo'],
];
diff --git a/backend/modules/authorinfo/Module.php b/backend/modules/authorinfo/Module.php
new file mode 100644
index 0000000..5431d36
--- /dev/null
+++ b/backend/modules/authorinfo/Module.php
@@ -0,0 +1,100 @@
+adminUser === null) {
+ $this->adminUser = User::find()
+ ->admin(true)
+ ->status(null)
+ ->orderBy(['elements.id' => SORT_ASC])
+ ->one();
+
+ if ($this->adminUser) {
+ Craft::info(
+ "Found admin user: ID: {$this->adminUser->id}, Name: {$this->adminUser->fullName}",
+ __METHOD__
+ );
+ } else {
+ Craft::warning('No admin user found', __METHOD__);
+ }
+ }
+
+ return $this->adminUser;
+ }
+
+ /**
+ * Handle the DefineGqlTypeFields event
+ */
+ public function handleDefineGqlTypeFields(DefineGqlTypeFieldsEvent $event): void
+ {
+ if ($event->typeName !== 'EntryInterface') {
+ return;
+ }
+
+ $event->fields['authorId'] = [
+ 'name' => 'authorId',
+ 'type' => Type::int(),
+ 'description' => 'The entry author\'s ID',
+ 'resolve' => function($source) {
+ try {
+ if ($source->getSection()->type === 'single') {
+ return $this->getAdminUser()?->id;
+ }
+ return $source->authorId;
+ } catch (\Throwable $e) {
+ Craft::error("Error resolving authorId: {$e->getMessage()}", __METHOD__);
+ return null;
+ }
+ }
+ ];
+
+ $event->fields['authorName'] = [
+ 'name' => 'authorName',
+ 'type' => Type::string(),
+ 'description' => 'The entry author\'s name',
+ 'resolve' => function($source) {
+ try {
+ if ($source->getSection()->type === 'single') {
+ return $this->getAdminUser()?->fullName;
+ }
+ return $source->getAuthor()?->fullName;
+ } catch (\Throwable $e) {
+ Craft::error("Error resolving authorName: {$e->getMessage()}", __METHOD__);
+ return null;
+ }
+ }
+ ];
+ }
+}
diff --git a/frontend/app.vue b/frontend/app.vue
index 38c2695..82edc16 100644
--- a/frontend/app.vue
+++ b/frontend/app.vue
@@ -8,7 +8,6 @@ const graphql = useGraphQL()
const { data: globalsData } = await useAsyncData('globals', async () => {
try {
const result = await graphql.query(GLOBALS_QUERY)
- console.log('GraphQL result:', result) // Debug log
return {
global: result?.globalEntries?.[0] || {},
pages: result?.pagesEntries || []
diff --git a/frontend/components/alert.vue b/frontend/components/alert.vue
index 7a08526..b4205a5 100644
--- a/frontend/components/alert.vue
+++ b/frontend/components/alert.vue
@@ -14,7 +14,7 @@
{{ page.title }}
diff --git a/frontend/components/postForm.vue b/frontend/components/postForm.vue
index c2fc434..5b29ea5 100644
--- a/frontend/components/postForm.vue
+++ b/frontend/components/postForm.vue
@@ -8,7 +8,6 @@ const config = useRuntimeConfig()
const graphql = useGraphQL()
const { addFlash } = useFlashes()
const message = ref('')
-const authorId = ref(config.public.ADMIN_USER_ID)
const loading = ref(false)
const emit = defineEmits(['post-submitted'])
@@ -18,6 +17,13 @@ const generateTitle = (text) => {
return `Post: ${words}${words ? '...' : ''}`
}
+const props = defineProps({
+ authorId: {
+ type: Number,
+ required: true
+ }
+})
+
const title = computed(() => generateTitle(message.value))
const submitPost = async () => {
@@ -27,15 +33,23 @@ const submitPost = async () => {
}
loading.value = true
try {
+ console.log('Submitting with:', {
+ title: title.value,
+ message: message.value,
+ authorId: props.authorId
+ })
+
const result = await graphql.query(CREATE_POST_MUTATION, {
title: title.value,
message: message.value,
- authorId: authorId.value
+ authorId: props.authorId.toString()
}, {
private: true
})
- if (!result?.save_posts_text_Entry) {
+ console.log('Mutation result:', result)
+
+ if (!result?.save_guestbookPosts_text_Entry) {
throw new Error('No data returned from the mutation')
}
@@ -43,8 +57,8 @@ const submitPost = async () => {
message.value = ''
emit('post-submitted')
} catch (err) {
- addFlash('Error posting message', 'error')
- console.error('Error creating post:', err.message)
+ addFlash(`Error posting message: ${err.message}`, 'error')
+ console.error('Error creating post:', err)
} finally {
loading.value = false
}
diff --git a/frontend/components/postList.vue b/frontend/components/postList.vue
new file mode 100644
index 0000000..c0b5e9c
--- /dev/null
+++ b/frontend/components/postList.vue
@@ -0,0 +1,77 @@
+
+
+
+
+ Loading...
+
+
+
+ {{ error.message }}
+
+
+
+
+
+ -
+
+
+
+
+
+
+
+
+
+
+
No entries yet. Create one using the form.
+
+
\ No newline at end of file
diff --git a/frontend/composables/usePaginatedData.js b/frontend/composables/usePaginatedData.js
index 6fae750..bedb313 100644
--- a/frontend/composables/usePaginatedData.js
+++ b/frontend/composables/usePaginatedData.js
@@ -38,6 +38,19 @@ export function usePaginatedData(fetchData, initialItemsPerPage = 3) {
}
}
+ const refresh = async () => {
+ loading.value = true
+ try {
+ const newData = await fetchData(currentPage.value, itemsPerPage.value)
+ data.value = newData
+ } catch (err) {
+ error.value = err
+ console.error('Error refreshing data:', err)
+ } finally {
+ loading.value = false
+ }
+ }
+
watch(() => route.query.page, async (newPage) => {
const page = parseInt(newPage) || 1
if (page !== currentPage.value) {
@@ -57,6 +70,7 @@ export function usePaginatedData(fetchData, initialItemsPerPage = 3) {
loading,
error,
updateCurrentPage,
- fetchPageData
+ fetchPageData,
+ refresh
}
}
\ No newline at end of file
diff --git a/frontend/nuxt.config.js b/frontend/nuxt.config.js
index 1533b11..5d27363 100644
--- a/frontend/nuxt.config.js
+++ b/frontend/nuxt.config.js
@@ -23,8 +23,7 @@ export default defineNuxtConfig({
AUTH_HEADER: process.env.AUTH_HEADER,
CRAFT_URL: process.env.CRAFT_URL,
BASE_URL: process.env.BASE_URL,
- SITE_NAME: process.env.SITE_NAME,
- ADMIN_USER_ID: process.env.ADMIN_USER_ID
+ SITE_NAME: process.env.SITE_NAME
}
},
vite: {
diff --git a/frontend/pages/blog/[slug].vue b/frontend/pages/blog/[slug].vue
index a53444e..77c5968 100644
--- a/frontend/pages/blog/[slug].vue
+++ b/frontend/pages/blog/[slug].vue
@@ -102,6 +102,9 @@ useHead(() => ({
+
+ By {{ currentPost.authorName }}
+
diff --git a/frontend/pages/guestbook.vue b/frontend/pages/guestbook.vue
index ca0897a..4250d43 100644
--- a/frontend/pages/guestbook.vue
+++ b/frontend/pages/guestbook.vue
@@ -1,11 +1,13 @@
+
Loading...
+
{{ error.message }}
+
-
- {{ content.title }}
- {{ content.pageSubheading }}
+
-
+
+
-
-
- -
-
-
-
-
-
-
-
-
-
-
- No entries yet. Create one using the form.
+
+
diff --git a/frontend/queries/blogPosts.mjs b/frontend/queries/blogPosts.mjs
index 808b8c5..a0b0a73 100644
--- a/frontend/queries/blogPosts.mjs
+++ b/frontend/queries/blogPosts.mjs
@@ -7,6 +7,8 @@ export const BLOG_POSTS_QUERY = `
title
pageSubheading
pageContent
+ authorName
+ authorId
postDate @formatDateTime(format: "F j, Y")
image {
alt
diff --git a/frontend/queries/guestbook.mjs b/frontend/queries/guestbook.mjs
index f0f62f2..b494bfe 100644
--- a/frontend/queries/guestbook.mjs
+++ b/frontend/queries/guestbook.mjs
@@ -1,22 +1,13 @@
export const GUESTBOOK_QUERY = `
- query Guestbook($limit: Int!, $offset: Int!) {
- guestbookEntries(limit: 1) {
+ query Guestbook {
+ guestbookEntries: entries(section: "guestbook", limit: 1) {
... on page_Entry {
id
+ title
pageContent
pageSubheading
- slug
- title
- }
- }
- guestbookPostsEntries(limit: $limit, offset: $offset) {
- ... on text_Entry {
- id
- title
- textBlock @markdown
- postDate @formatDateTime(format: "F j, Y")
+ authorId
}
}
- entryCount(section: "posts")
}
`
\ No newline at end of file
diff --git a/frontend/queries/guestbookPosts.mjs b/frontend/queries/guestbookPosts.mjs
new file mode 100644
index 0000000..d0845f6
--- /dev/null
+++ b/frontend/queries/guestbookPosts.mjs
@@ -0,0 +1,13 @@
+export const GUESTBOOK_POSTS_QUERY = `
+ query GuestbookPosts($limit: Int!, $offset: Int!) {
+ guestbookPostsEntries(limit: $limit, offset: $offset) {
+ ... on text_Entry {
+ id
+ title
+ textBlock @markdown
+ postDate @formatDateTime(format: "F j, Y")
+ }
+ }
+ entryCount(section: "posts")
+ }
+`
\ No newline at end of file