diff --git a/frontend/index.html b/frontend/index.html
index bd14331..fcc4514 100644
--- a/frontend/index.html
+++ b/frontend/index.html
@@ -4,7 +4,14 @@
-
LaneBow - 볼링 클럽 매니저
+
+
+
+
+
+
+
+ LaneBow-레인보우
diff --git a/frontend/package-lock.json b/frontend/package-lock.json
index 2f6df79..8b7c695 100644
--- a/frontend/package-lock.json
+++ b/frontend/package-lock.json
@@ -18,6 +18,7 @@
"@tosspayments/payment-sdk": "^1.9.1",
"@vuelidate/core": "^2.0.3",
"@vuelidate/validators": "^2.0.4",
+ "@vueuse/head": "^2.0.0",
"axios": "^1.8.2",
"chart.js": "^4.4.8",
"dayjs": "^1.11.10",
@@ -1507,6 +1508,76 @@
"dev": true,
"license": "MIT"
},
+ "node_modules/@unhead/dom": {
+ "version": "1.11.20",
+ "resolved": "https://registry.npmjs.org/@unhead/dom/-/dom-1.11.20.tgz",
+ "integrity": "sha512-jgfGYdOH+xHJF/j8gudjsYu3oIjFyXhCWcgKaw3vQnT616gSqyqnGQGOItL+BQtQZACKNISwIfx5PuOtztMKLA==",
+ "license": "MIT",
+ "dependencies": {
+ "@unhead/schema": "1.11.20",
+ "@unhead/shared": "1.11.20"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/harlan-zw"
+ }
+ },
+ "node_modules/@unhead/schema": {
+ "version": "1.11.20",
+ "resolved": "https://registry.npmjs.org/@unhead/schema/-/schema-1.11.20.tgz",
+ "integrity": "sha512-0zWykKAaJdm+/Y7yi/Yds20PrUK7XabLe9c3IRcjnwYmSWY6z0Cr19VIs3ozCj8P+GhR+/TI2mwtGlueCEYouA==",
+ "license": "MIT",
+ "dependencies": {
+ "hookable": "^5.5.3",
+ "zhead": "^2.2.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/harlan-zw"
+ }
+ },
+ "node_modules/@unhead/shared": {
+ "version": "1.11.20",
+ "resolved": "https://registry.npmjs.org/@unhead/shared/-/shared-1.11.20.tgz",
+ "integrity": "sha512-1MOrBkGgkUXS+sOKz/DBh4U20DNoITlJwpmvSInxEUNhghSNb56S0RnaHRq0iHkhrO/cDgz2zvfdlRpoPLGI3w==",
+ "license": "MIT",
+ "dependencies": {
+ "@unhead/schema": "1.11.20",
+ "packrup": "^0.1.2"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/harlan-zw"
+ }
+ },
+ "node_modules/@unhead/ssr": {
+ "version": "1.11.20",
+ "resolved": "https://registry.npmjs.org/@unhead/ssr/-/ssr-1.11.20.tgz",
+ "integrity": "sha512-j6ehzmdWGAvv0TEZyLE3WBnG1ULnsbKQcLqBDh3fvKS6b3xutcVZB7mjvrVE7ckSZt6WwOtG0ED3NJDS7IjzBA==",
+ "license": "MIT",
+ "dependencies": {
+ "@unhead/schema": "1.11.20",
+ "@unhead/shared": "1.11.20"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/harlan-zw"
+ }
+ },
+ "node_modules/@unhead/vue": {
+ "version": "1.11.20",
+ "resolved": "https://registry.npmjs.org/@unhead/vue/-/vue-1.11.20.tgz",
+ "integrity": "sha512-sqQaLbwqY9TvLEGeq8Fd7+F2TIuV3nZ5ihVISHjWpAM3y7DwNWRU7NmT9+yYT+2/jw1Vjwdkv5/HvDnvCLrgmg==",
+ "license": "MIT",
+ "dependencies": {
+ "@unhead/schema": "1.11.20",
+ "@unhead/shared": "1.11.20",
+ "hookable": "^5.5.3",
+ "unhead": "1.11.20"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/harlan-zw"
+ },
+ "peerDependencies": {
+ "vue": ">=2.7 || >=3"
+ }
+ },
"node_modules/@vitejs/plugin-vue": {
"version": "5.2.3",
"resolved": "https://registry.npmjs.org/@vitejs/plugin-vue/-/plugin-vue-5.2.3.tgz",
@@ -1829,6 +1900,21 @@
}
}
},
+ "node_modules/@vueuse/head": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/@vueuse/head/-/head-2.0.0.tgz",
+ "integrity": "sha512-ykdOxTGs95xjD4WXE4na/umxZea2Itl0GWBILas+O4oqS7eXIods38INvk3XkJKjqMdWPcpCyLX/DioLQxU1KA==",
+ "license": "MIT",
+ "dependencies": {
+ "@unhead/dom": "^1.7.0",
+ "@unhead/schema": "^1.7.0",
+ "@unhead/ssr": "^1.7.0",
+ "@unhead/vue": "^1.7.0"
+ },
+ "peerDependencies": {
+ "vue": ">=2.7 || >=3"
+ }
+ },
"node_modules/adler-32": {
"version": "1.3.1",
"resolved": "https://registry.npmjs.org/adler-32/-/adler-32-1.3.1.tgz",
@@ -2901,6 +2987,15 @@
"url": "https://github.com/sponsors/sindresorhus"
}
},
+ "node_modules/packrup": {
+ "version": "0.1.2",
+ "resolved": "https://registry.npmjs.org/packrup/-/packrup-0.1.2.tgz",
+ "integrity": "sha512-ZcKU7zrr5GlonoS9cxxrb5HVswGnyj6jQvwFBa6p5VFw7G71VAHcUKL5wyZSU/ECtPM/9gacWxy2KFQKt1gMNA==",
+ "license": "MIT",
+ "funding": {
+ "url": "https://github.com/sponsors/harlan-zw"
+ }
+ },
"node_modules/parse-ms": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/parse-ms/-/parse-ms-4.0.0.tgz",
@@ -3342,6 +3437,21 @@
"url": "https://github.com/sponsors/sindresorhus"
}
},
+ "node_modules/unhead": {
+ "version": "1.11.20",
+ "resolved": "https://registry.npmjs.org/unhead/-/unhead-1.11.20.tgz",
+ "integrity": "sha512-3AsNQC0pjwlLqEYHLjtichGWankK8yqmocReITecmpB1H0aOabeESueyy+8X1gyJx4ftZVwo9hqQ4O3fPWffCA==",
+ "license": "MIT",
+ "dependencies": {
+ "@unhead/dom": "1.11.20",
+ "@unhead/schema": "1.11.20",
+ "@unhead/shared": "1.11.20",
+ "hookable": "^5.5.3"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/harlan-zw"
+ }
+ },
"node_modules/unicorn-magic": {
"version": "0.3.0",
"resolved": "https://registry.npmjs.org/unicorn-magic/-/unicorn-magic-0.3.0.tgz",
@@ -3792,6 +3902,15 @@
"funding": {
"url": "https://github.com/sponsors/sindresorhus"
}
+ },
+ "node_modules/zhead": {
+ "version": "2.2.4",
+ "resolved": "https://registry.npmjs.org/zhead/-/zhead-2.2.4.tgz",
+ "integrity": "sha512-8F0OI5dpWIA5IGG5NHUg9staDwz/ZPxZtvGVf01j7vHqSyZ0raHY+78atOVxRqb73AotX22uV1pXt3gYSstGag==",
+ "license": "MIT",
+ "funding": {
+ "url": "https://github.com/sponsors/harlan-zw"
+ }
}
}
}
diff --git a/frontend/package.json b/frontend/package.json
index 17ee4cd..35b4b5e 100644
--- a/frontend/package.json
+++ b/frontend/package.json
@@ -20,6 +20,7 @@
"@tosspayments/payment-sdk": "^1.9.1",
"@vuelidate/core": "^2.0.3",
"@vuelidate/validators": "^2.0.4",
+ "@vueuse/head": "^2.0.0",
"axios": "^1.8.2",
"chart.js": "^4.4.8",
"dayjs": "^1.11.10",
diff --git a/frontend/src/main.js b/frontend/src/main.js
index 0ce87ac..45f50b9 100644
--- a/frontend/src/main.js
+++ b/frontend/src/main.js
@@ -59,10 +59,11 @@ import TabPanel from 'primevue/tabpanel';
import TabList from 'primevue/tablist';
import Tab from 'primevue/tab';
import {ko} from 'primelocale/js/ko.js';
-
+import { createHead } from '@vueuse/head'
import AppHeader from './components/AppHeader.vue';
const app = createApp(App)
-
+const head = createHead()
+app.use(head)
// Register PrimeVue
app.use(PrimeVue, {
theme: {
diff --git a/frontend/src/views/event/EventPublicPage.vue b/frontend/src/views/event/EventPublicPage.vue
index 27c4290..7e0829d 100644
--- a/frontend/src/views/event/EventPublicPage.vue
+++ b/frontend/src/views/event/EventPublicPage.vue
@@ -259,7 +259,7 @@ import MemberListCard from '@/components/public/MemberListCard.vue';
import JoinDialog from '@/components/public/JoinDialog.vue';
import dayjs from 'dayjs';
import PublicEventService from '@/services/PublicEventService';
-import Panel from 'primevue/panel';
+import { useHead } from '@vueuse/head';
const route = useRoute();
const publicHash = route.params.publicHash;
@@ -282,6 +282,32 @@ const isReady = computed(() => event.value.status === 'ready');
const isActive = computed(() => event.value.status === 'active');
const isFinished = computed(() => event.value.status === 'completed');
+// description만 이벤트 정보로 동적으로 설정
+const eventDescriptionText = computed(() => {
+ const e = event.value || {};
+ let summary = '';
+ if (e.startDate) {
+ summary += `[기간] ${formatDate(e.startDate)}`;
+ if (e.endDate) summary += ` ~ ${formatDate(e.endDate)}`;
+ summary += '.\n';
+ }
+ if (e.description) summary += `[이벤트 내용] ${e.description}`;
+ if (e.location) summary += `[장소] ${e.location}.\n`;
+ if (e.registrationDeadline) summary += `[신청마감] ${formatDate(e.registrationDeadline)}.\n`;
+ if (e.maxParticipants) summary += `[참가인원] ${e.maxParticipants}명\n`;
+
+ return summary || '이벤트 정보가 없습니다.';
+});
+
+useHead({
+ meta: [
+ { title: event.value.title },
+ { property: 'og:title', content: event.value.title },
+ { name: 'description', content: eventDescriptionText },
+ { property: 'og:description', content: eventDescriptionText }
+ ]
+});
+
// 신청 마감일시 체크
const isRegistrationClosed = computed(() => {
if (!event.value.registrationDeadline) return false;