diff --git a/README.md b/README.md index 9771f63..390bc2f 100644 --- a/README.md +++ b/README.md @@ -54,7 +54,37 @@ ## ๐Ÿ— ์„ค๊ณ„ ๋ฐ ๊ตฌํ˜„ - ### ๐Ÿ“‚ ํ”„๋กœ์ ํŠธ ๊ตฌ์กฐ - - ํ”„๋กœ์ ํŠธ์˜ ์ฃผ์š” ๋””๋ ‰ํ† ๋ฆฌ ๊ตฌ์กฐ์™€ ์„ค๋ช…์„ ํฌํ•จํ•ฉ๋‹ˆ๋‹ค. + +``` +๐Ÿ“ฆ ํ”„๋กœ์ ํŠธ ๋ฃจํŠธ + โ”ฃ ๐Ÿ“‚src + โ”ƒ โ”ฃ ๐Ÿ“‚assets + โ”ƒ โ”ƒ โ”ฃ ๐Ÿ“‚data + โ”ƒ โ”ƒ โ”ฃ ๐Ÿ“‚fonts + โ”ƒ โ”ƒ โ”ฃ ๐Ÿ“‚Icons + โ”ƒ โ”ƒ โ”ƒ โ”— ๐Ÿ“‚akoming + โ”ƒ โ”ƒ โ”ฃ ๐Ÿ“‚images + โ”ƒ โ”ƒ โ”— ๐Ÿ“‚styles + โ”ƒ โ”ฃ ๐Ÿ“‚components # ๊ณต์šฉ ์ปดํฌ๋„ŒํŠธ + โ”ƒ โ”ƒ โ”ฃ ๐Ÿ“‚common + โ”ƒ โ”ƒ โ”— ๐Ÿ“‚layout + โ”ƒ โ”ฃ ๐Ÿ“‚router # Vue Router + โ”ƒ โ”ฃ ๐Ÿ“‚store # Vuex + โ”ƒ โ”ฃ ๐Ÿ“‚views + โ”ƒ โ”ƒ โ”ฃ ๐Ÿ“‚akopolio # ์•„์ฝ”ํด๋ฆฌ์˜ค ๊ด€๋ จ ํŽ˜์ด์ง€ + โ”ƒ โ”ƒ โ”ฃ ๐Ÿ“‚calendar # ํ•™์‚ฌ ์ผ์ • ์บ˜๋ฆฐ๋” ๊ด€๋ จ ํŽ˜์ด์ง€ + โ”ƒ โ”ƒ โ”ฃ ๐Ÿ“‚feed # ํ”ผ๋“œ ๊ด€๋ จ ํŽ˜์ด์ง€ + โ”ƒ โ”ƒ โ”ฃ ๐Ÿ“‚login # ๋กœ๊ทธ์ธ, ํšŒ์›๊ฐ€์ž…, ๋งˆ์ดํŽ˜์ด์ง€ ๊ด€๋ จ ํŽ˜์ด์ง€ + โ”ƒ โ”ƒ โ”ฃ ๐Ÿ“‚mainpage # ๋ฉ”์ธ ํŽ˜์ด์ง€ ๊ด€๋ จ ํŒŒ์ผ + โ”ƒ โ”ƒ โ”— ๐Ÿ“œNotFound.vue # 404 ์—๋Ÿฌ ํŽ˜์ด์ง€ + โ”ฃ ๐Ÿ“‚public + โ”ฃ ๐Ÿ“‚docs # ๋ณด๊ณ ์„œ ๋“ฑ ๋ฌธ์„œ ํด๋” + โ”ƒ โ”— ๐Ÿ“œREADME.md + โ”ฃ ๐Ÿ“œApp.vue + โ”ฃ ๐Ÿ“œmain.js +``` + + - ### ๐Ÿงฉ ๋‹ค์ด์–ด๊ทธ๋žจ ์•„ํ‚คํ…์ฒ˜ ๋‹ค์ด์–ด๊ทธ๋žจ, ์„œ๋น„์Šค ํ๋ฆ„, ๋ฐ์ดํ„ฐ ํ๋ฆ„ ๋“ฑ์„ ๊ทธ๋ฆผ์œผ๋กœ ํ‘œํ˜„ํ•ฉ๋‹ˆ๋‹ค. @@ -69,8 +99,9 @@ ![osori](https://github.com/user-attachments/assets/d90a2ae9-aac0-4ba0-92bf-fd08abee8d4b) -- ### ๐Ÿ“‘ API ๋ช…์„ธ์„œ - - ๊ฐ API์˜ ์„ค๋ช…, ์š”์ฒญ ๋ฐ ์‘๋‹ต ์˜ˆ์‹œ๋ฅผ ํฌํ•จํ•ฉ๋‹ˆ๋‹ค. +- ### ๐Ÿ“‘ API ๋ช…์„ธ์„œ ์ผ๋ถ€ +     ![1](https://github.com/user-attachments/assets/21191f05-1f77-4c98-878c-f3b5ddaa6f99) +
@@ -105,9 +136,15 @@ ## โ–ถ ์‹คํ–‰ ๋ฐฉ๋ฒ• -1. **ํ™˜๊ฒฝ ์„ค์ •**: ํ”„๋กœ์ ํŠธ ์‹คํ–‰์„ ์œ„ํ•œ ํ•„์ˆ˜ ํ™˜๊ฒฝ ๋ณ€์ˆ˜ ๋ฐ ์„ค์ • ์ •๋ณด๋ฅผ ํฌํ•จํ•ฉ๋‹ˆ๋‹ค. -2. **์˜์กด์„ฑ ์„ค์น˜**: ํ”„๋กœ์ ํŠธ์˜ ์ข…์†์„ฑ์„ ์„ค์น˜ํ•˜๋Š” ๋‹จ๊ณ„์ž…๋‹ˆ๋‹ค. +1. **ํ™˜๊ฒฝ ์„ค์ •**: Node.js, npm, vue-cli๋ฅผ ์„ค์น˜ํ•ฉ๋‹ˆ๋‹ค. + ```bash + npm install -g @vue/cli +2. **์˜์กด์„ฑ ์„ค์น˜**:
+ ```bash + npm install 3. **ํ”„๋กœ์ ํŠธ ์‹คํ–‰**: ์‹คํ–‰ ๋ช…๋ น์–ด๋กœ ํ”„๋กœ์ ํŠธ๋ฅผ ์‹œ์ž‘ํ•ฉ๋‹ˆ๋‹ค. + ```bash + npm run dev
diff --git "a/docs/\355\232\214\354\235\230\353\241\235.md" "b/docs/\355\232\214\354\235\230\353\241\235.md" index 7d5556e..c66493a 100644 --- "a/docs/\355\232\214\354\235\230\353\241\235.md" +++ "b/docs/\355\232\214\354\235\230\353\241\235.md" @@ -15,11 +15,12 @@ | 8์ฐจ | 2024๋…„ 10์›” 16์ผ | ์ •๊ธฐ ํšŒ์˜ | ์ด์†Œ์€, ์ตœ๋ฏผ, ์ •์ง€์›, ์ •์˜ˆ๋นˆ | ์ด์†Œ์€ | https://www.notion.so/8-12db4ba0516b81178342cc75df07750b | | 9์ฐจ | 2024๋…„ 10์›” 21์ผ | ์ •๊ธฐ ํšŒ์˜ | ์ด์†Œ์€, ์ตœ๋ฏผ, ์ •์ง€์›, ์ •์˜ˆ๋นˆ | ์ •์ง€์› | https://www.notion.so/9-12db4ba0516b8164b602fd248747296b | | 10์ฐจ | 2024๋…„ 10์›” 23์ผ | ์ •๊ธฐ ํšŒ์˜ | ์ด์†Œ์€, ์ตœ๋ฏผ, ์ •์ง€์›, ์ •์˜ˆ๋นˆ | ์ตœ๋ฏผ | https://www.notion.so/10-12db4ba0516b81d9a131f2c52ae5ee89 | -| 11์ฐจ | 2024๋…„ 10์›” 28์ผ | ์ •๊ธฐ ํšŒ์˜ | ์ด์†Œ์€, ์ตœ๋ฏผ, ์ •์ง€์›, ์ •์˜ˆ๋นˆ | ์ •์˜ˆ๋นˆ | https://www.notion.so/11-12db4ba0516b8071b0f8fcce55a7a442?pvs=4 | -| 12์ฐจ | 2024๋…„ 10์›” 30์ผ | ์ •๊ธฐ ํšŒ์˜ | ์ด์†Œ์€, ์ตœ๋ฏผ, ์ •์ง€์›, ์ •์˜ˆ๋นˆ | ์ด์†Œ์€ | https://www.notion.so/12-bf84f851b63442adba1b69159a772725?pvs=4 | -| 13์ฐจ | 2024๋…„ 11์›” 4์ผ | ์ •๊ธฐ ํšŒ์˜ | ์ด์†Œ์€, ์ตœ๋ฏผ, ์ •์ง€์›, ์ •์˜ˆ๋นˆ | ์ •์ง€์› | https://www.notion.so/13-a6297b09e7bd45fa904862463bca54c4?pvs=4 | -| 14์ฐจ | 2024๋…„ 11์›” 6์ผ | ์ •๊ธฐ ํšŒ์˜ | ์ด์†Œ์€, ์ตœ๋ฏผ, ์ •์ง€์›, ์ •์˜ˆ๋นˆ | ์ตœ๋ฏผ | https://www.notion.so/14-416a0ab074c54e1f945a72cd3c3acb18?pvs=4 | -| 15์ฐจ | 2024๋…„ 11์›” 11์ผ | ์ •๊ธฐ ํšŒ์˜ | ์ด์†Œ์€, ์ตœ๋ฏผ, ์ •์ง€์›, ์ •์˜ˆ๋นˆ | ์ •์˜ˆ๋นˆ | https://www.notion.so/15-29633aca525242d983483ebc20b8871d?pvs=4 | -| 16์ฐจ | 2024๋…„ 11์›” 18์ผ | ์ •๊ธฐ ํšŒ์˜ | ์ด์†Œ์€, ์ตœ๋ฏผ, ์ •์ง€์›, ์ •์˜ˆ๋นˆ | ์ด์†Œ์€ | https://www.notion.so/16-dce780571dbe4f9a84e4bb58be834e66?pvs=4 | -| 17์ฐจ | 2024๋…„ 11์›” 20์ผ | ์ •๊ธฐ ํšŒ์˜ | ์ด์†Œ์€, ์ตœ๋ฏผ, ์ •์ง€์›, ์ •์˜ˆ๋นˆ | ์ •์ง€์› | https://www.notion.so/17-476981be247b4d339ff70ae25a91d80e?pvs=4 | - +| 11์ฐจ | 2024๋…„ 10์›” 28์ผ | ์ •๊ธฐ ํšŒ์˜ | ์ด์†Œ์€, ์ตœ๋ฏผ, ์ •์ง€์›, ์ •์˜ˆ๋นˆ | ์ •์˜ˆ๋นˆ | https://www.notion.so/11-12db4ba0516b8071b0f8fcce55a7a442 | +| 12์ฐจ | 2024๋…„ 10์›” 30์ผ | ์ •๊ธฐ ํšŒ์˜ | ์ด์†Œ์€, ์ตœ๋ฏผ, ์ •์ง€์›, ์ •์˜ˆ๋นˆ | ์ด์†Œ์€ | https://www.notion.so/12-bf84f851b63442adba1b69159a772725 | +| 13์ฐจ | 2024๋…„ 11์›” 4์ผ | ์ •๊ธฐ ํšŒ์˜ | ์ด์†Œ์€, ์ตœ๋ฏผ, ์ •์ง€์›, ์ •์˜ˆ๋นˆ | ์ •์ง€์› | https://www.notion.so/13-a6297b09e7bd45fa904862463bca54c4 | +| 14์ฐจ | 2024๋…„ 11์›” 6์ผ | ์ •๊ธฐ ํšŒ์˜ | ์ด์†Œ์€, ์ตœ๋ฏผ, ์ •์ง€์›, ์ •์˜ˆ๋นˆ | ์ตœ๋ฏผ | https://www.notion.so/14-416a0ab074c54e1f945a72cd3c3acb18 | +| 15์ฐจ | 2024๋…„ 11์›” 11์ผ | ์ •๊ธฐ ํšŒ์˜ | ์ด์†Œ์€, ์ตœ๋ฏผ, ์ •์ง€์›, ์ •์˜ˆ๋นˆ | ์ •์˜ˆ๋นˆ | https://www.notion.so/15-29633aca525242d983483ebc20b8871d | +| 16์ฐจ | 2024๋…„ 11์›” 18์ผ | ์ •๊ธฐ ํšŒ์˜ | ์ด์†Œ์€, ์ตœ๋ฏผ, ์ •์ง€์›, ์ •์˜ˆ๋นˆ | ์ด์†Œ์€ | https://www.notion.so/16-dce780571dbe4f9a84e4bb58be834e66 | +| 17์ฐจ | 2024๋…„ 11์›” 20์ผ | ์ •๊ธฐ ํšŒ์˜ | ์ด์†Œ์€, ์ตœ๋ฏผ, ์ •์ง€์›, ์ •์˜ˆ๋นˆ | ์ •์ง€์› | https://www.notion.so/17-476981be247b4d339ff70ae25a91d80e | +| 18์ฐจ | 2024๋…„ 11์›” 27์ผ | ์ •๊ธฐ ํšŒ์˜ | ์ด์†Œ์€, ์ตœ๋ฏผ, ์ •์ง€์›, ์ •์˜ˆ๋นˆ | ์ตœ๋ฏผ | https://www.notion.so/17-476981be247b4d339ff70ae25a91d80e | +| 19์ฐจ | 2024๋…„ 12์›” 4์ผ | ์ •๊ธฐ ํšŒ์˜ | ์ด์†Œ์€, ์ตœ๋ฏผ, ์ •์ง€์›, ์ •์˜ˆ๋นˆ | ์ •์˜ˆ๋นˆ | https://www.notion.so/17-476981be247b4d339ff70ae25a91d80e | diff --git a/src/router/index.js b/src/router/index.js index 739e8c0..f35e74f 100644 --- a/src/router/index.js +++ b/src/router/index.js @@ -7,7 +7,6 @@ import FeedLayout from '@/components/layout/FeedLayout.vue' import akopolioCreate from '@/views/akopolio/create/akopolioCreate.vue' import akopolioMain from '@/views/akopolio/main/akopolioMain.vue' - // ์ž๋™ ์ž„ํฌํŠธ ํ•จ์ˆ˜ (src/views ๋‚ด์˜ ๋ชจ๋“  .vue ํŒŒ์ผ์„ ์ž„ํฌํŠธ) function importAllViews() { const viewFiles = require.context('@/views', true, /\.vue$/) @@ -81,8 +80,7 @@ const routes = [ path: 'edit/:id', name: 'akopolioEdit', component: importedViews['akopolioEdit'] // ์ž๋™ ์ž„ํฌํŠธ ์ ์šฉ - }, - + } ] }, { @@ -138,6 +136,40 @@ const router = createRouter({ routes }) -//๋ผ์šฐํ„ฐ ๊ฐ€๋“œ ์„ค์ •(์„ธ์…˜ ๊ธฐ๋ฐ˜ ์ฟ ๊ธฐ, ๋‚˜์ค‘์— ์ˆ˜์ • ํ•„์š”) -// meta: { requiresAuth: true } // ์ธ์ฆ์ด ํ•„์š”ํ•œ ํŽ˜์ด์ง€ +//๋ผ์šฐํ„ฐ ๊ฐ€๋“œ ์„ค์ • +// ๊ธ€๋กœ๋ฒŒ ๊ฐ€๋“œ ์ถ”๊ฐ€ +router.beforeEach(async (to, from, next) => { + const isAuthPage = to.matched.some((record) => + record.path.startsWith('/auth') + ) + + try { + // ์„ธ์…˜ ์ƒํƒœ ํ™•์ธ API ํ˜ธ์ถœ + const response = await fetch( + `${process.env.VUE_APP_BE_API_URL}/api/quests/status`, + { + method: 'GET', + credentials: 'include' // ์„ธ์…˜ ์ฟ ํ‚ค ํฌํ•จ + } + ) + + if (response.ok) { + if (isAuthPage) { + next('/main') // ์ด๋ฏธ ์ธ์ฆ๋œ ์ƒํƒœ๋ผ๋ฉด ๋ฉ”์ธ ํŽ˜์ด์ง€๋กœ ์ด๋™ + } else { + next() // ์ •์ƒ์ ์œผ๋กœ ํŽ˜์ด์ง€ ์ด๋™ + } + } else { + if (isAuthPage) { + next() // ์ธ์ฆ ๊ฒฝ๋กœ๋กœ๋Š” ์ ‘๊ทผ ๊ฐ€๋Šฅ + } else { + next('/auth/login') // ์ธ์ฆ๋˜์ง€ ์•Š์•˜์œผ๋ฉด ๋กœ๊ทธ์ธ ํŽ˜์ด์ง€๋กœ ์ด๋™ + } + } + } catch (error) { + console.error('Error during authentication check:', error) + next('/auth/login') // ์˜ค๋ฅ˜ ๋ฐœ์ƒ ์‹œ ๋กœ๊ทธ์ธ ํŽ˜์ด์ง€๋กœ ์ด๋™ + } +}) + export default router diff --git a/src/store/index.js b/src/store/index.js index f605fac..ca3228e 100644 --- a/src/store/index.js +++ b/src/store/index.js @@ -1,60 +1,61 @@ -import { createStore } from 'vuex'; -import auth from '../views/test/auth.js'; // auth ๋ชจ๋“ˆ import -import login from './modules/login.js'; // ๋กœ๊ทธ์ธ ๋ชจ๋“ˆ import -import { v4 as uuidv4 } from 'uuid'; // UUID๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ๊ณ ์œ  ID ์ƒ์„ฑ +import { createStore } from 'vuex' +import login from './modules/login.js' // ๋กœ๊ทธ์ธ ๋ชจ๋“ˆ import +import { v4 as uuidv4 } from 'uuid' // UUID๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ๊ณ ์œ  ID ์ƒ์„ฑ // ๋กœ์ปฌ ์Šคํ† ๋ฆฌ์ง€์—์„œ ํฌํŠธํด๋ฆฌ์˜ค ๊ฐ€์ ธ์˜ค๊ธฐ const getStoredPortfolios = () => { - const storedPortfolios = localStorage.getItem('portfolios'); - return storedPortfolios ? JSON.parse(storedPortfolios) : []; -}; + const storedPortfolios = localStorage.getItem('portfolios') + return storedPortfolios ? JSON.parse(storedPortfolios) : [] +} const store = createStore({ state: { - portfolios: getStoredPortfolios(), // ๋กœ์ปฌ ์Šคํ† ๋ฆฌ์ง€์—์„œ ํฌํŠธํด๋ฆฌ์˜ค ์ดˆ๊ธฐํ™” + portfolios: getStoredPortfolios() // ๋กœ์ปฌ ์Šคํ† ๋ฆฌ์ง€์—์„œ ํฌํŠธํด๋ฆฌ์˜ค ์ดˆ๊ธฐํ™” }, mutations: { ADD_PORTFOLIO(state, portfolio) { - const newPortfolio = { ...portfolio, id: uuidv4() }; // ๊ณ ์œ  ID ์ถ”๊ฐ€ - state.portfolios.push(newPortfolio); // ํฌํŠธํด๋ฆฌ์˜ค ์ถ”๊ฐ€ - localStorage.setItem('portfolios', JSON.stringify(state.portfolios)); // ๋กœ์ปฌ ์Šคํ† ๋ฆฌ์ง€์— ์ €์žฅ + const newPortfolio = { ...portfolio, id: uuidv4() } // ๊ณ ์œ  ID ์ถ”๊ฐ€ + state.portfolios.push(newPortfolio) // ํฌํŠธํด๋ฆฌ์˜ค ์ถ”๊ฐ€ + localStorage.setItem('portfolios', JSON.stringify(state.portfolios)) // ๋กœ์ปฌ ์Šคํ† ๋ฆฌ์ง€์— ์ €์žฅ }, DELETE_PORTFOLIO(state, portfolioId) { - state.portfolios = state.portfolios.filter(portfolio => portfolio.id !== portfolioId); - localStorage.setItem('portfolios', JSON.stringify(state.portfolios)); // ๋กœ์ปฌ ์Šคํ† ๋ฆฌ์ง€์— ์‚ญ์ œ ํ›„ ์ €์žฅ + state.portfolios = state.portfolios.filter( + (portfolio) => portfolio.id !== portfolioId + ) + localStorage.setItem('portfolios', JSON.stringify(state.portfolios)) // ๋กœ์ปฌ ์Šคํ† ๋ฆฌ์ง€์— ์‚ญ์ œ ํ›„ ์ €์žฅ }, - // ์ˆ˜์ • ๊ธฐ๋Šฅ์„ ์œ„ํ•œ UPDATE_PORTFOLIO ๋ฎคํ…Œ์ด์…˜ ์ถ”๊ฐ€ - UPDATE_PORTFOLIO(state, updatedPortfolio) { - const index = state.portfolios.findIndex(portfolio => portfolio.id === updatedPortfolio.id); + // ์ˆ˜์ • ๊ธฐ๋Šฅ์„ ์œ„ํ•œ UPDATE_PORTFOLIO ๋ฎคํ…Œ์ด์…˜ ์ถ”๊ฐ€ + UPDATE_PORTFOLIO(state, updatedPortfolio) { + const index = state.portfolios.findIndex( + (portfolio) => portfolio.id === updatedPortfolio.id + ) if (index !== -1) { - state.portfolios.splice(index, 1, updatedPortfolio); // ๊ธฐ์กด ํ•ญ๋ชฉ์„ ์—…๋ฐ์ดํŠธ๋œ ํ•ญ๋ชฉ์œผ๋กœ ๊ต์ฒด - localStorage.setItem('portfolios', JSON.stringify(state.portfolios)); // ๋กœ์ปฌ ์Šคํ† ๋ฆฌ์ง€์— ์—…๋ฐ์ดํŠธ ํ›„ ์ €์žฅ + state.portfolios.splice(index, 1, updatedPortfolio) // ๊ธฐ์กด ํ•ญ๋ชฉ์„ ์—…๋ฐ์ดํŠธ๋œ ํ•ญ๋ชฉ์œผ๋กœ ๊ต์ฒด + localStorage.setItem('portfolios', JSON.stringify(state.portfolios)) // ๋กœ์ปฌ ์Šคํ† ๋ฆฌ์ง€์— ์—…๋ฐ์ดํŠธ ํ›„ ์ €์žฅ } - }, + } }, actions: { addPortfolio({ commit }, portfolio) { - commit('ADD_PORTFOLIO', portfolio); // mutation ํ˜ธ์ถœ + commit('ADD_PORTFOLIO', portfolio) // mutation ํ˜ธ์ถœ }, deletePortfolio({ commit }, portfolioId) { - commit('DELETE_PORTFOLIO', portfolioId); - }, - // ์ˆ˜์ • ๊ธฐ๋Šฅ์„ ์œ„ํ•œ updatePortfolio ์•ก์…˜ ์ถ”๊ฐ€ - updatePortfolio({ commit }, updatedPortfolio) { - commit('UPDATE_PORTFOLIO', updatedPortfolio); // UPDATE_PORTFOLIO ๋ฎคํ…Œ์ด์…˜ ํ˜ธ์ถœ + commit('DELETE_PORTFOLIO', portfolioId) }, + // ์ˆ˜์ • ๊ธฐ๋Šฅ์„ ์œ„ํ•œ updatePortfolio ์•ก์…˜ ์ถ”๊ฐ€ + updatePortfolio({ commit }, updatedPortfolio) { + commit('UPDATE_PORTFOLIO', updatedPortfolio) // UPDATE_PORTFOLIO ๋ฎคํ…Œ์ด์…˜ ํ˜ธ์ถœ + } }, getters: { getPortfolios(state) { - return state.portfolios; // ํฌํŠธํด๋ฆฌ์˜ค ๋ชฉ๋ก ๋ฐ˜ํ™˜ - }, + return state.portfolios // ํฌํŠธํด๋ฆฌ์˜ค ๋ชฉ๋ก ๋ฐ˜ํ™˜ + } }, modules: { - login, // ๋กœ๊ทธ์ธ ๋ชจ๋“ˆ - auth, // auth ๋ชจ๋“ˆ - }, -}); - -export default store; - + login // ๋กœ๊ทธ์ธ ๋ชจ๋“ˆ + // auth ๋ชจ๋“ˆ + } +}) +export default store diff --git a/src/views/akopolio/Edit/akopolioEdit.vue b/src/views/akopolio/Edit/akopolioEdit.vue index 3bbea85..58bbe6f 100644 --- a/src/views/akopolio/Edit/akopolioEdit.vue +++ b/src/views/akopolio/Edit/akopolioEdit.vue @@ -29,14 +29,14 @@
- +
+ {{ tag }} +
@@ -75,16 +75,21 @@
- - + +
X
- -
+
์ €์žฅํ•˜๊ธฐ
+ @@ -155,7 +160,7 @@ textarea { font-size: 12px; } -button { +.tag-div { display: inline-block; margin: 3px; padding: 5px 10px; @@ -165,8 +170,13 @@ button { border: 1px solid #eec092; } -button.active { - background-color: #f6b87a; +.tag-div.active { + background-color: #f7c088; +} + +.tag-div:hover { + background-color: #f7c088; + cursor: pointer; } /* ๋ถ„์•ผ ์„ค์ • ๋ฐ•์Šค */ @@ -208,12 +218,14 @@ button.active { font-size: 0.875rem; font-weight: 500; border-radius: 9999px; + text-align: center; transition: background-color 0.3s ease; margin-bottom: 20px; } .save-button:hover { background-color: #e5a769; + cursor: pointer; } .experience-container h3, @@ -269,16 +281,15 @@ label { top: 5px; right: 5px; color: black; - border: none; - background: none; /* ๋ฐฐ๊ฒฝ์ƒ‰ ์ œ๊ฑฐ */ - font-size: 16px; /* X ์•„์ด์ฝ˜์ด ๋” ์ž˜ ๋ณด์ด๋„๋ก ํฌ๊ธฐ ์กฐ์ • */ + background: none; + font-size: 15px; cursor: pointer; - transition: color 0.3s; /* ์ƒ‰์ƒ ์ „ํ™˜ ์• ๋‹ˆ๋ฉ”์ด์…˜ ์ถ”๊ฐ€ */ + transition: color 0.3s; } .delete-image-btn:hover { - color: white; + color:#d9d9d9; } @@ -302,12 +313,10 @@ label { object-fit: contain; /* ์ด๋ฏธ์ง€๊ฐ€ ์ปจํ…Œ์ด๋„ˆ ๋‚ด์—์„œ ๋น„์œจ์„ ์œ ์ง€ํ•˜๋ฉด์„œ ํฌ๊ธฐ ์กฐ์ • */ } -/* ๊ธฐ๋ณธ input[type="file"] ์ˆจ๊ธฐ๊ธฐ */ input[type="file"] { display: none; } -/* ์ปค์Šคํ…€ ๋ฒ„ํŠผ ์Šคํƒ€์ผ */ .custom-file-upload { background-color: #faf5f0; color: #f3ab62; diff --git a/src/views/akopolio/Edit/edit.js b/src/views/akopolio/Edit/edit.js index 3a5437b..6f6b641 100644 --- a/src/views/akopolio/Edit/edit.js +++ b/src/views/akopolio/Edit/edit.js @@ -84,13 +84,17 @@ export default { textarea.style.height = `${textarea.scrollHeight}px`; }; - const fetchPortfolioById = async (id) => { + // ํฌํŠธํด๋ฆฌ์˜ค ๋ฐ์ดํ„ฐ ๊ฐ€์ ธ์˜ค๊ธฐ + const fetchPortfolioById = async (portfolioId) => { try { - const apiUrl = `${process.env.VUE_APP_BE_API_URL}/api/portfolios/${id}`; - console.log('Fetching portfolio from URL:', apiUrl); + const apiUrl = `${process.env.VUE_APP_BE_API_URL}/api/portfolios/${portfolioId}`; + console.log('Fetching portfolio from URL:', apiUrl); // API URL ์ถœ๋ ฅ - const response = await fetch(apiUrl); - console.log('Response status:', response.status); + const response = await fetch(apiUrl, { + method: 'GET', + credentials: 'include', + }); + console.log('Response status:', response.status); // ์ƒํƒœ ์ฝ”๋“œ ํ™•์ธ if (!response.ok) { console.error(`Response status: ${response.status}, ${response.statusText}`); @@ -100,6 +104,7 @@ export default { const data = await response.json(); console.log('Received portfolio data:', data); + // ํฌํŠธํด๋ฆฌ์˜ค ๋ฐ์ดํ„ฐ ํ• ๋‹น portfolio.value = { baseInfo: data.baseInfo || {}, experience: data.experience || { situation: '', task: '', action: '', result: '' }, @@ -107,7 +112,22 @@ export default { photoUrls: data.photoUrls || [], }; - images.value = portfolio.value.photoUrls || []; + // ๊ฐ ๋ณ€์ˆ˜์— ํฌํŠธํด๋ฆฌ์˜ค ๋ฐ์ดํ„ฐ ํ• ๋‹น + activityName.value = portfolio.value.baseInfo.name || ''; // ํ™œ๋™๋ช… + activityDate.value = portfolio.value.baseInfo.startDate || ''; // ํ™œ๋™์ผ (startDate๋กœ ๋ณ€๊ฒฝ) + star.value = portfolio.value.experience || { situation: '', task: '', action: '', result: '' }; // STAR ๋ชจ๋ธ + pmi.value = portfolio.value.pmi || { plus: '', minus: '', interesting: '' }; // PMI ๋ชจ๋ธ + images.value = portfolio.value.photoUrls.map((imageUrl) => { + return { + previewUrl: imageUrl, // ์„œ๋ฒ„์—์„œ ์ œ๊ณตํ•˜๋Š” URL์„ ๋ฏธ๋ฆฌ๋ณด๊ธฐ URL๋กœ ์‚ฌ์šฉ + name: imageUrl.split('/').pop(), // ํŒŒ์ผ ์ด๋ฆ„์„ ์ถ”์ถœ + size: 0, // ๊ธฐ์กด ์ด๋ฏธ์ง€๋Š” ํŒŒ์ผ ํฌ๊ธฐ ํ•„์š” ์—†์Œ + containerWidth: '300px', // ๊ธฐ๋ณธ ํฌ๊ธฐ ์„ค์ • + containerHeight: '300px', // ๊ธฐ๋ณธ ํฌ๊ธฐ ์„ค์ • + }; + }); + selectedTags.value = portfolio.value.baseInfo.tags || []; + } catch (error) { console.error('Error fetching portfolio:', error); alert('ํฌํŠธํด๋ฆฌ์˜ค๋ฅผ ๊ฐ€์ ธ์˜ค๋Š” ์ค‘ ์˜ค๋ฅ˜๊ฐ€ ๋ฐœ์ƒํ–ˆ์Šต๋‹ˆ๋‹ค.'); @@ -124,7 +144,7 @@ export default { } const newImagesPromises = selectedFiles.map((file) => { - const previewUrl = URL.createObjectURL(file); + const previewUrl = URL.createObjectURL(file); // ์ƒˆ๋กœ ์ถ”๊ฐ€๋œ ์ด๋ฏธ์ง€๋Š” ๋ฏธ๋ฆฌ๋ณด๊ธฐ URL ์ƒ์„ฑ const imageElement = new Image(); imageElement.src = previewUrl; @@ -171,7 +191,9 @@ export default { }; const removeImage = (index) => { - URL.revokeObjectURL(images.value[index].previewUrl); + if (images.value[index].previewUrl) { + URL.revokeObjectURL(images.value[index].previewUrl); // ์ƒ์„ฑํ•œ URL์„ ํ•ด์ œ + } images.value.splice(index, 1); }; @@ -219,6 +241,7 @@ export default { return; } + try { const response = await axios.put( `${process.env.VUE_APP_BE_API_URL}/api/portfolios/${id}`, @@ -237,7 +260,7 @@ export default { minus: pmi.value.minus, interesting: pmi.value.interesting, }, - photoUrls: images.value.map(image => image.name), + photoUrls: images.value.map(image => image.url), }, { headers: { @@ -273,6 +296,7 @@ export default { selectedTags.value = []; await fetchUserData(); await fetchPortfolioById(portfolioId); + }); return { diff --git a/src/views/akopolio/create/akopolioCreate.vue b/src/views/akopolio/create/akopolioCreate.vue index 29ddaee..5cca151 100644 --- a/src/views/akopolio/create/akopolioCreate.vue +++ b/src/views/akopolio/create/akopolioCreate.vue @@ -29,14 +29,15 @@
- +
+ {{ tag }} +
@@ -105,14 +106,14 @@
- +
X
- +
์ €์žฅํ•˜๊ธฐ
@@ -183,7 +184,7 @@ textarea { font-size: 12px; } -button { +.tag-item { display: inline-block; margin: 3px; padding: 5px 10px; @@ -191,12 +192,18 @@ button { background-color: white; transition: background-color 0.3s; border: 1px solid #eec092; + cursor: pointer; } -button.active { +.tag-item.active { background-color: #f6b87a; } +.tag-item:hover { + background-color: #f6b87a; + cursor: pointer; +} + /* ๋ถ„์•ผ ์„ค์ • ๋ฐ•์Šค */ .category-box { background-color: white; @@ -236,12 +243,14 @@ button.active { font-size: 0.875rem; font-weight: 500; border-radius: 9999px; + text-align: center; transition: background-color 0.3s ease; margin-bottom: 20px; } .save-button:hover { background-color: #e5a769; + cursor: pointer; } h3 { diff --git a/src/views/akopolio/detail/akopolioDetail.vue b/src/views/akopolio/detail/akopolioDetail.vue index e53ee7d..3720fc6 100644 --- a/src/views/akopolio/detail/akopolioDetail.vue +++ b/src/views/akopolio/detail/akopolioDetail.vue @@ -4,11 +4,11 @@
- - +
@@ -17,11 +17,11 @@

ํ™œ๋™๋ช…

-

{{ portfolio ? portfolio.title : '' }}

+

{{ portfolio ? portfolio.name : '' }}

ํ™œ๋™์ผ

-

{{ portfolio ? portfolio.createdDate : '' }}

+

{{ portfolio ? portfolio.startDate : '' }}

๋ถ„์•ผ ์„ค์ •

@@ -36,22 +36,22 @@

๊ฒฝํ—˜ (STAR)

-
+

Situation

-

{{ portfolio.star.situation || '์ƒํ™ฉ ์ •๋ณด๊ฐ€ ์—†์Šต๋‹ˆ๋‹ค.' }}

+

{{ portfolio.experience.situation || '์ƒํ™ฉ ์ •๋ณด๊ฐ€ ์—†์Šต๋‹ˆ๋‹ค.' }}

Task

-

{{ portfolio.star.task || '๋‚ด์šฉ์ด ์—†์Šต๋‹ˆ๋‹ค.' }}

+

{{ portfolio.experience.task || '๋‚ด์šฉ์ด ์—†์Šต๋‹ˆ๋‹ค.' }}

Action

-

{{ portfolio.star.action || '๋‚ด์šฉ์ด ์—†์Šต๋‹ˆ๋‹ค.' }}

+

{{ portfolio.experience.action || '๋‚ด์šฉ์ด ์—†์Šต๋‹ˆ๋‹ค.' }}

Result

-

{{ portfolio.star.result || '๋‚ด์šฉ์ด ์—†์Šต๋‹ˆ๋‹ค.' }}

+

{{ portfolio.experience.result || '๋‚ด์šฉ์ด ์—†์Šต๋‹ˆ๋‹ค.' }}

@@ -122,24 +122,29 @@ .edit-button, .delete-button { display: flex; + align-items: center; + justify-content: center; padding: 5px 10px; border-radius: 10px; - border: none; cursor: pointer; font-size: 10px; gap: 4px; + background-color: white; } .edit-button { - background-color: white; color: black; } .delete-button { - background-color: white; color: red; } +.edit-button:hover, +.delete-button:hover { + background-color: #f2eeee; +} + .image-upload-container, .experience-container, .pmi-container { diff --git a/src/views/akopolio/detail/detail.js b/src/views/akopolio/detail/detail.js index f916125..e77ef83 100644 --- a/src/views/akopolio/detail/detail.js +++ b/src/views/akopolio/detail/detail.js @@ -51,16 +51,19 @@ export default { console.log("Portfolio ID:", portfolioId); - // ํฌํŠธํด๋ฆฌ์˜ค ๋ฐ์ดํ„ฐ ๊ฐ€์ ธ์˜ค๊ธฐ - const fetchPortfolioById = async (portfolioId) => { - try { - const apiUrl = `${process.env.VUE_APP_BE_API_URL}/api/portfolios/${portfolioId}`; - console.log('Fetching portfolio from URL:', apiUrl); // API URL ์ถœ๋ ฅ - - // Fetch ์š”์ฒญ - const response = await fetch(apiUrl); - console.log('Response status:', response.status); // ์ƒํƒœ ์ฝ”๋“œ ํ™•์ธ - + // ํฌํŠธํด๋ฆฌ์˜ค ๋ฐ์ดํ„ฐ ๊ฐ€์ ธ์˜ค๊ธฐ + const fetchPortfolioById = async (portfolioId) => { + try { + const apiUrl = `${process.env.VUE_APP_BE_API_URL}/api/portfolios/${portfolioId}` + console.log('Fetching portfolio from URL:', apiUrl) // API URL ์ถœ๋ ฅ + + // Fetch ์š”์ฒญ + const response = await fetch(apiUrl, { + method: 'GET', + credentials: 'include' + }) + console.log('Response status:', response.status) // ์ƒํƒœ ์ฝ”๋“œ ํ™•์ธ + if (!response.ok) { console.error(`Response status: ${response.status}, ${response.statusText}`); // ์˜ˆ์™ธ ์ฒ˜๋ฆฌ๋ฅผ ํ†ตํ•ด ์‚ฌ์šฉ์ž์—๊ฒŒ ์ƒ์„ธํ•œ ์—๋Ÿฌ ๋ฉ”์‹œ์ง€ ์ œ๊ณต @@ -78,21 +81,20 @@ export default { // ์‘๋‹ต ๋ฐ์ดํ„ฐ ํ™•์ธ console.log('Received portfolio data:', data); - // ํฌํŠธํด๋ฆฌ์˜ค ๋ฐ์ดํ„ฐ๋ฅผ ๊ตฌ์กฐ์— ๋งž๊ฒŒ ์ €์žฅ portfolio.value = { - baseInfo: data.baseInfo || {}, // ๊ธฐ๋ณธ ์ •๋ณด ์ €์žฅ - experience: data.experience || {}, // ๊ฒฝํ—˜ ์ •๋ณด ์ €์žฅ - pmi: data.pmi || {}, // PMI ์ •๋ณด ์ €์žฅ - photoUrls: data.photoUrls || [], // ์‚ฌ์ง„ URL ๋ฐฐ์—ด ์ €์žฅ + name: data.baseInfo.name, // ํ™œ๋™๋ช… + startDate: data.baseInfo.startDate, // ํ™œ๋™์ผ + tags: data.baseInfo.tags || [], // ํƒœ๊ทธ + experience: data.experience || { situation: '', task: '', action: '', result: '' }, + pmi: data.pmi || { plus: '', minus: '', interesting: '' }, + photoUrls: data.photoUrls || [], // ์ด๋ฏธ์ง€ }; - // ์ด๋ฏธ์ง€ ๋ฐ์ดํ„ฐ ๋”ฐ๋กœ ์ €์žฅ - images.value = portfolio.value.photoUrls; - + images.value = data.photoUrls || []; } catch (error) { console.error('Error fetching portfolio:', error); alert('ํฌํŠธํด๋ฆฌ์˜ค๋ฅผ ๊ฐ€์ ธ์˜ค๋Š” ์ค‘ ์˜ค๋ฅ˜๊ฐ€ ๋ฐœ์ƒํ–ˆ์Šต๋‹ˆ๋‹ค.'); - portfolio.value = null; // ์˜ค๋ฅ˜ ๋ฐœ์ƒ ์‹œ ์ดˆ๊ธฐํ™” + portfolio.value = null; images.value = []; } }; @@ -109,8 +111,11 @@ export default { // ๋ฐฑ์—”๋“œ API ์—ฐ๋™ const response = await fetch( `${process.env.VUE_APP_BE_API_URL}/api/portfolios/${portfolioId}`, - { method: 'DELETE' } - ); + { + method: 'DELETE', + credentials: 'include' + } + ) if (!response.ok) { throw new Error(`Failed to delete portfolio: ${response.statusText}`); @@ -139,4 +144,4 @@ export default { handleDeletePortfolio, }; }, -}; +}; \ No newline at end of file diff --git a/src/views/akopolio/main/akopolioMain.vue b/src/views/akopolio/main/akopolioMain.vue index 8f6d145..74b2264 100644 --- a/src/views/akopolio/main/akopolioMain.vue +++ b/src/views/akopolio/main/akopolioMain.vue @@ -10,7 +10,7 @@ @input="applyFilters" placeholder="ํ™œ๋™๋ช…์„ ์ž…๋ ฅํ•˜์„ธ์š” (๋‘ ๊ธ€์ž ์ด์ƒ)" /> - +
์ดˆ๊ธฐํ™”
@@ -33,14 +33,14 @@
- +
@@ -75,13 +75,13 @@ @change-page="handlePageChanged" /> - +
@@ -153,7 +153,7 @@ input[type='date'] { font-size: 12px; } -button { +.tag-container div { display: inline-block; margin: 3px; padding: 5px 10px; @@ -161,12 +161,18 @@ button { background-color: white; transition: background-color 0.3s; border: 1px solid #eec092; + cursor: pointer; } -button.active { +.tag-container div.active { background-color: #f6b87a; } +.tag-container div:hover { + background-color: #f6b87a; + cursor: pointer; +} + .filter-container { background-color: white; padding: 15px; @@ -284,12 +290,11 @@ button.active { margin-left: 10px; /* ์˜ค๋ฅธ์ชฝ ์—ฌ๋ฐฑ */ background-color: #f4b28c; color: black; - border: none; padding: 6px 11px; border-radius: 5px; cursor: pointer; font-size: 13px; - border-radius: 8px; + text-align: center; } .reset-btn:hover { diff --git a/src/views/akopolio/main/main.js b/src/views/akopolio/main/main.js index 6c6a72b..cbecde1 100644 --- a/src/views/akopolio/main/main.js +++ b/src/views/akopolio/main/main.js @@ -45,6 +45,7 @@ export default { }; }, computed: { + filteredPortfolioList() { let filteredList = this.portfolioList; diff --git a/src/views/akopolio/paginationNav.vue b/src/views/akopolio/paginationNav.vue index 8b3cdc3..8730f06 100644 --- a/src/views/akopolio/paginationNav.vue +++ b/src/views/akopolio/paginationNav.vue @@ -1,21 +1,27 @@ @@ -28,11 +34,10 @@ export default { computed: { visiblePages() { const pages = []; - const maxVisible = 5; // ์ตœ๋Œ€ ํ‘œ์‹œํ•  ํŽ˜์ด์ง€ ์ˆ˜ + const maxVisible = 5; let startPage = Math.max(1, this.currentPage - Math.floor(maxVisible / 2)); let endPage = Math.min(this.totalPages, startPage + maxVisible - 1); - // ๋ ํŽ˜์ด์ง€๊ฐ€ ๋ถ€์กฑํ•  ๋•Œ ์‹œ์ž‘ ํŽ˜์ด์ง€ ์กฐ์ • if (endPage - startPage < maxVisible - 1) { startPage = Math.max(1, endPage - maxVisible + 1); } @@ -60,21 +65,25 @@ export default { margin-top: 20px; } -button { +.page-item { margin: 0 5px; padding: 5px; - cursor: pointer; - background: none; - border: none; font-size: 16px; + cursor: pointer; + user-select: none; } -button.active{ +.page-item.active { font-weight: bold; } -button:disabled { +.page-item.disabled { cursor: not-allowed; opacity: 0.5; } - \ No newline at end of file + +.page-item:not(.disabled):hover { + background-color: none; +} + + diff --git a/src/views/calendar/CalendarMainScript.js b/src/views/calendar/CalendarMainScript.js index bf3958e..27eb27a 100644 --- a/src/views/calendar/CalendarMainScript.js +++ b/src/views/calendar/CalendarMainScript.js @@ -1,4 +1,4 @@ -import { ref, computed, onMounted } from 'vue' +import { ref, computed } from 'vue' import axios from 'axios' import { format, @@ -20,41 +20,32 @@ export const isScheduleOpen = ref(false) export const currentYear = computed(() => format(currentDate.value, 'yyyy')) export const currentMonth = computed(() => format(currentDate.value, 'M')) -// ์ž„์‹œ ํ•™์‚ฌ ์ผ์ • ๋ฐ์ดํ„ฐ -const temporaryEvents = [ - { title: '๊ฐœ๊ฐ•์ผ', startDate: '2024-03-01', endDate: '2024-03-01' }, - { title: '์ข…๊ฐ•์ผ', startDate: '2024-06-30', endDate: '2024-06-30' }, - { title: '์ค‘๊ฐ„๊ณ ์‚ฌ', startDate: '2024-04-15', endDate: '2024-04-19' }, - { title: '๊ธฐ๋ง๊ณ ์‚ฌ', startDate: '2024-06-15', endDate: '2024-06-19' }, - { title: '์ค‘๊ฐ„๊ณ ์‚ฌ', startDate: '2024-10-21', endDate: '2024-10-25' } -] - // ํ•™์‚ฌ ์ผ์ • ๋ฐ์ดํ„ฐ ์ €์žฅ์†Œ export const academicEvents = ref([]) // ๋ฐฑ์—”๋“œ์—์„œ ํ•™์‚ฌ ์ผ์ • ๊ฐ€์ ธ์˜ค๊ธฐ export const fetchAcademicEvents = async () => { try { - console.log( - 'API ์š”์ฒญ URL:', - `${process.env.VUE_APP_BE_API_URL}/api/calendar` - ) - const response = await axios.get( - `${process.env.VUE_APP_BE_API_URL}/api/calendar`, - { - params: { - year: currentYear.value, - month: currentMonth.value - } - } - ) - academicEvents.value = response.data || [] + const apiUrl = `${process.env.VUE_APP_BE_API_URL}/api/academic-events/${currentYear.value}/${currentMonth.value}` + console.log('API ์š”์ฒญ URL:', apiUrl) + + const response = await axios.get(apiUrl) + + if (response.status === 200 && response.data) { + academicEvents.value = response.data.map((event) => ({ + title: event.eventTitle, + department: event.department, + startDate: event.startDate, + endDate: event.endDate + })) + console.log('ํ•™์‚ฌ ์ผ์ • ๋ฐ์ดํ„ฐ:', academicEvents.value) + } else { + console.warn('ํ•™์‚ฌ ์ผ์ • ๋ฐ์ดํ„ฐ๋ฅผ ๊ฐ€์ ธ์˜ค๋Š” ๋ฐ ์‹คํŒจํ–ˆ์Šต๋‹ˆ๋‹ค.') + academicEvents.value = [] + } } catch (error) { - console.log( - '์„œ๋ฒ„์— ์—ฐ๊ฒฐํ•  ์ˆ˜ ์—†์–ด ์ž„์‹œ ๋ฐ์ดํ„ฐ๋ฅผ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค:', - error.message - ) - academicEvents.value = [...temporaryEvents] + console.error('ํ•™์‚ฌ ์ผ์ • ๋ฐ์ดํ„ฐ ๊ฐ€์ ธ์˜ค๊ธฐ ์˜ค๋ฅ˜:', error.message) + academicEvents.value = [] } } @@ -106,12 +97,15 @@ export const hasEvent = (day) => { const selectedDateStr = `${currentYear.value}-${String( currentMonth.value ).padStart(2, '0')}-${String(day).padStart(2, '0')}` - return academicEvents.value.some((event) => + + const result = academicEvents.value.some((event) => isWithinInterval(parseISO(selectedDateStr), { start: parseISO(event.startDate), end: parseISO(event.endDate) }) ) + + return result } export const selectedEvents = computed(() => { diff --git a/src/views/calendar/CalendarMainView.vue b/src/views/calendar/CalendarMainView.vue index bf39f61..2f3c6ca 100644 --- a/src/views/calendar/CalendarMainView.vue +++ b/src/views/calendar/CalendarMainView.vue @@ -85,7 +85,8 @@ onMounted(() => { class="day-button" :class="{ selected: day === selectedDay, - 'sunday-saturday': isSundayOrSaturday(day) + 'sunday-saturday': isSundayOrSaturday(day), + 'has-event': hasEvent(day) }" v-for="day in week" :key="day" @@ -100,7 +101,16 @@ onMounted(() => { class="schedule-popup" v-if="isScheduleOpen && selectedEvents.length > 0" > - + +
@@ -219,7 +229,7 @@ onMounted(() => { .schedule-popup { position: fixed; - bottom: 0; + bottom: -100%; /* ์‹œ์ž‘ ์œ„์น˜: ํ™”๋ฉด ์•„๋ž˜ */ left: 0; right: 0; background-color: #ffffff; @@ -229,6 +239,9 @@ onMounted(() => { max-height: 60vh; width: 395px; margin: 0 auto; + box-shadow: 0 -4px 6px rgba(0, 0, 0, 0.1); + animation: slide-up 0.3s ease-out forwards; /* ๋ถ€๋“œ๋Ÿฌ์šด ์œ„๋กœ ์ด๋™ ์• ๋‹ˆ๋ฉ”์ด์…˜ */ + z-index: 1000; } .link-button { @@ -252,4 +265,56 @@ onMounted(() => { .link-button:hover { background-color: #f1cdb1; } +.day-button.has-event::after { + content: ''; + display: block; + width: 6px; + height: 6px; + background-color: #b3b3b3; + border-radius: 50%; + margin: 0 auto; + margin-top: 4px; +} + +@keyframes slide-up { + from { + bottom: -100%; /* ์ดˆ๊ธฐ ์ƒํƒœ */ + } + to { + bottom: 0; /* ์ตœ์ข… ์ƒํƒœ */ + } +} + +.popup-header { + display: flex; + justify-content: space-between; + align-items: center; + margin-bottom: 1rem; +} + +.popup-header h2 { + font-size: 1.25rem; + font-weight: bold; + color: #4a4a4a; +} + +.close-button { + background: none; + border: none; + font-size: 1.5rem; + font-weight: bold; + color: #b3b3b3; + cursor: pointer; + transition: color 0.3s; +} + +.close-button:hover { + color: #ff7f00; +} + +.popup-content { + display: flex; + flex-direction: column; + gap: 1rem; +} diff --git a/src/views/mainpage/MainpageStyled.css b/src/views/mainpage/MainpageStyled.css deleted file mode 100644 index 26690ee..0000000 --- a/src/views/mainpage/MainpageStyled.css +++ /dev/null @@ -1,130 +0,0 @@ -/* ์™ธ๋ถ€ ์ปจํ…Œ์ด๋„ˆ */ -.page-container { - min-height: 100vh; - background-color: #fff9f2; - font-family: 'NanumSquareRound', sans-serif; - display: flex; - justify-content: center; -} - -/* ๋ชจ๋ฐ”์ผ ์ปจํ…Œ์ด๋„ˆ */ -.mobile-container { - width: 395px; - min-width: 340px; - background-color: #fae8da; - min-height: 100vh; - position: relative; - overflow-y: auto; -} - -/* ๋ฉ”์ธ ์ปจํ…์ธ  */ -.main-content { - display: flex; - flex-direction: column; - padding: 6rem 1.5rem 6rem; - font-family: 'NanumSquareRound', sans-serif; -} - -.main-content .title { - margin-bottom: 70px; - font-size: 1.25rem; - font-weight: 500; - text-align: center; - color: #4a4a4a; - font-family: 'UhBeeSehyun', sans-serif; -} - -/* ์Šคํƒฌํ”„ ์˜์—ญ */ -.stamp-container { - position: relative; - width: 390px; - height: 520px; - margin: 0 auto; -} - -.stamp-container .stamp { - position: absolute; - width: 95px; - height: 95px; - display: flex; - justify-content: center; - align-items: center; -} - -.stamp-container .stamp img { - width: 100%; - height: 100%; -} - -/* ํ•  ์ผ ํ‘œ์‹œ ์˜์—ญ */ -.task-container { - margin-top: -80px; - margin-bottom: 3rem; - display: flex; - flex-direction: column; - align-items: center; - gap: 0.75rem; -} - -.task-container .task-row { - display: flex; - gap: 0.75rem; - width: 100%; - max-width: 290px; -} - -.task-container .task-row .task { - display: flex; - align-items: center; - justify-content: space-between; - flex: 1; - height: 40px; - padding: 0 1rem; - background-color: white; - border-radius: 17px; -} - -.task-container .task-row .task span { - font-size: 0.875rem; - font-family: 'NanumSquareRound', sans-serif; - color: var(--task-color, #b3b3b3); -} - -.task-container .task-row .task img { - width: 20px; - height: 20px; - filter: var(--task-filter, grayscale(100%)); -} - -/* ์•„์ฝ” ์ด๋ฏธ์ง€ ์˜์—ญ */ -.ako-image-container { - text-align: center; - display: flex; - flex-direction: column; - align-items: center; - margin-top: 2.5rem; -} - -.ako-image-container .ako-status { - display: flex; - align-items: center; - margin-bottom: 0.5rem; -} - -.ako-image-container .ako-status img { - width: 32px; - height: 32px; - margin-right: 0.5rem; -} - -.ako-image-container .ako-status p { - font-size: 0.875rem; - color: #757575; - font-family: 'NanumSquareRound', sans-serif; -} - -.ako-image-container .ako-image { - width: 256px; - height: 256px; - margin: 0 auto; -} diff --git a/src/views/mainpage/MainpageView.vue b/src/views/mainpage/MainpageView.vue index eab74ce..86f1d7a 100644 --- a/src/views/mainpage/MainpageView.vue +++ b/src/views/mainpage/MainpageView.vue @@ -49,7 +49,12 @@ }" > {{ task.name }} - +
@@ -63,7 +68,12 @@ }" > {{ task.name }} - +
@@ -88,7 +98,6 @@ - + diff --git a/src/views/test/AboutView.vue b/src/views/test/AboutView.vue deleted file mode 100644 index 3fa2807..0000000 --- a/src/views/test/AboutView.vue +++ /dev/null @@ -1,5 +0,0 @@ - diff --git a/src/views/test/ErrorMessage.vue b/src/views/test/ErrorMessage.vue deleted file mode 100644 index 95385a2..0000000 --- a/src/views/test/ErrorMessage.vue +++ /dev/null @@ -1,30 +0,0 @@ - - - - - - diff --git a/src/views/test/HelloWorld.vue b/src/views/test/HelloWorld.vue deleted file mode 100644 index 75cbd09..0000000 --- a/src/views/test/HelloWorld.vue +++ /dev/null @@ -1,138 +0,0 @@ - - - - - - diff --git a/src/views/test/HomeView.vue b/src/views/test/HomeView.vue deleted file mode 100644 index 270fa07..0000000 --- a/src/views/test/HomeView.vue +++ /dev/null @@ -1,18 +0,0 @@ - - - diff --git a/src/views/test/NotFound2.vue b/src/views/test/NotFound2.vue deleted file mode 100644 index c971c97..0000000 --- a/src/views/test/NotFound2.vue +++ /dev/null @@ -1,29 +0,0 @@ - - - - - - diff --git a/src/views/test/PortfolioByTag.vue b/src/views/test/PortfolioByTag.vue deleted file mode 100644 index e9cd24a..0000000 --- a/src/views/test/PortfolioByTag.vue +++ /dev/null @@ -1,165 +0,0 @@ - - - - - diff --git a/src/views/test/PortfolioCreate.vue b/src/views/test/PortfolioCreate.vue deleted file mode 100644 index 3a39f9a..0000000 --- a/src/views/test/PortfolioCreate.vue +++ /dev/null @@ -1,202 +0,0 @@ - - - - - diff --git a/src/views/test/PortfolioTest.vue b/src/views/test/PortfolioTest.vue deleted file mode 100644 index c32f984..0000000 --- a/src/views/test/PortfolioTest.vue +++ /dev/null @@ -1,280 +0,0 @@ - - - - - - - diff --git a/src/views/test/Profile.vue b/src/views/test/Profile.vue deleted file mode 100644 index 5a8f5da..0000000 --- a/src/views/test/Profile.vue +++ /dev/null @@ -1,143 +0,0 @@ - - - - - diff --git a/src/views/test/SignIn.vue b/src/views/test/SignIn.vue deleted file mode 100644 index bb86d7b..0000000 --- a/src/views/test/SignIn.vue +++ /dev/null @@ -1,226 +0,0 @@ - - - - - diff --git a/src/views/test/SignUpForm.vue b/src/views/test/SignUpForm.vue deleted file mode 100644 index bcb6b3f..0000000 --- a/src/views/test/SignUpForm.vue +++ /dev/null @@ -1,195 +0,0 @@ - - - - - diff --git a/src/views/test/SignUpForm2.vue b/src/views/test/SignUpForm2.vue deleted file mode 100644 index ba563f6..0000000 --- a/src/views/test/SignUpForm2.vue +++ /dev/null @@ -1,287 +0,0 @@ - - - - - diff --git a/src/views/test/TaliwindResopon.vue b/src/views/test/TaliwindResopon.vue deleted file mode 100644 index aeaa5b8..0000000 --- a/src/views/test/TaliwindResopon.vue +++ /dev/null @@ -1,114 +0,0 @@ - - - - - - - diff --git a/src/views/test/VerifyEmail.vue b/src/views/test/VerifyEmail.vue deleted file mode 100644 index 7efdd32..0000000 --- a/src/views/test/VerifyEmail.vue +++ /dev/null @@ -1,208 +0,0 @@ - - - - - diff --git a/src/views/test/WeeklyCalenderTest.vue b/src/views/test/WeeklyCalenderTest.vue deleted file mode 100644 index 298da47..0000000 --- a/src/views/test/WeeklyCalenderTest.vue +++ /dev/null @@ -1,25 +0,0 @@ - - - diff --git a/src/views/test/auth.js b/src/views/test/auth.js deleted file mode 100644 index f570c59..0000000 --- a/src/views/test/auth.js +++ /dev/null @@ -1,72 +0,0 @@ -import axios from 'axios' - -const state = { - user: null, - isAuthenticated: false -} - -const mutations = { - login(state, user) { - state.user = user - state.isAuthenticated = true - }, - logout(state) { - state.user = null - state.isAuthenticated = false - } -} - -const actions = { - async login({ commit }, { email, password, rememberMe = false }) { - try { - const response = await axios.post( - 'http://localhost:8080/api/users/login', - { - email, - password - } - ) - const user = response.data.user - commit('login', user) - - //remeber me ๋กœ๊ทธ์ธ ์ƒํƒœ ์œ ์ง€ ๋กœ์ง - if (rememberMe) { - // ๋กœ๊ทธ์ธ ์ƒํƒœ ์œ ์ง€ ์ฒดํฌ ์‹œ ๋กœ์ปฌ ์Šคํ† ๋ฆฌ์ง€์— ์ €์žฅ - localStorage.setItem('user', JSON.stringify(user)) - } else { - // ์ฒดํฌ ์•ˆํ•œ ๊ฒฝ์šฐ ์„ธ์…˜ ์Šคํ† ๋ฆฌ์ง€์— ์ €์žฅ - sessionStorage.setItem('user', JSON.stringify(user)) - } - - //localStorage.setItem('user', JSON.stringify(user)) - return { success: true } // ๋กœ๊ทธ์ธ ์„ฑ๊ณต ์‹œ - } catch (error) { - console.log(error.response) - const errorMessage = error.response?.data?.message || '๋กœ๊ทธ์ธ ์‹คํŒจ' - return { success: false, message: errorMessage } // ์—๋Ÿฌ ๋ฐœ์ƒ ์‹œ ์—๋Ÿฌ ๋ฉ”์‹œ์ง€ ๋ฐ˜ํ™˜ - } - }, - logout({ commit }) { - commit('logout') - localStorage.removeItem('user') - sessionStorage.removeItem('user') // ์„ธ์…˜ ์Šคํ† ๋ฆฌ์ง€์—์„œ๋„ ์‚ญ์ œ - }, - initializeStore({ commit }) { - const user = JSON.parse(localStorage.getItem('user')) - if (user) { - commit('login', user) - } - } -} - -const getters = { - isAuthenticated: (state) => state.isAuthenticated, - user: (state) => state.user -} - -export default { - state, - mutations, - actions, - getters -} diff --git a/src/views/test/posts.js b/src/views/test/posts.js deleted file mode 100644 index e69de29..0000000 diff --git a/src/views/test/tags.js b/src/views/test/tags.js deleted file mode 100644 index e69de29..0000000 diff --git a/src/views/test/testrouter.js b/src/views/test/testrouter.js deleted file mode 100644 index 22e8e46..0000000 --- a/src/views/test/testrouter.js +++ /dev/null @@ -1,126 +0,0 @@ -/* eslint-disable */ -import { createRouter, createWebHashHistory } from 'vue-router' -import AuthLayout from '@/components/layout/AuthLayout.vue' // ์ค‘์ฒฉ ๋ผ์šฐํŒ…์˜ ๋ถ€๋ชจ ๋ ˆ์ด์•„์›ƒ -import PortfolioLayout from '@/components/layout/PortfolioLayout.vue' // ์ค‘์ฒฉ ๋ผ์šฐํŒ…์˜ ๋ถ€๋ชจ ๋ ˆ์ด์•„์›ƒ - -// ์ž๋™ ์ž„ํฌํŠธ ํ•จ์ˆ˜ (src/views ๋‚ด์˜ ๋ชจ๋“  .vue ํŒŒ์ผ์„ ์ž„ํฌํŠธ) -function importAllViews() { - const viewFiles = require.context('@/views', true, /\.vue$/) - const views = {} - - // ๊ฐ ํŒŒ์ผ์„ ์ˆœํšŒํ•˜๋ฉด์„œ ์ž„ํฌํŠธ - viewFiles.keys().forEach((filePath) => { - const viewName = filePath - .split('/') - .pop() // ํŒŒ์ผ ์ด๋ฆ„๋งŒ ์ถ”์ถœ - .replace('.vue', '') // .vue ํ™•์žฅ์ž ์ œ๊ฑฐ - - // ์ปดํฌ๋„ŒํŠธ ์ด๋ฆ„๊ณผ ํ•ด๋‹น ์ปดํฌ๋„ŒํŠธ๋ฅผ ๋งตํ•‘ - views[viewName] = viewFiles(filePath).default - }) - - return views -} - -// ์ž๋™์œผ๋กœ ์ž„ํฌํŠธ๋œ ๋ชจ๋“  Vue ์ปดํฌ๋„ŒํŠธ ๊ฐ์ฒด -const importedViews = importAllViews() - -const routes = [ - { - path: '/', - name: 'home', - component: importedViews['HomeView'] // ์ž๋™ ์ž„ํฌํŠธ ์ ์šฉ - }, - { - path: '/about', - name: 'about', - component: importedViews['AboutView'] // ์ž๋™ ์ž„ํฌํŠธ ์ ์šฉ - }, - { - path: '/auth', - component: AuthLayout, // ๋ถ€๋ชจ ๋ ˆ์ด์•„์›ƒ - children: [ - { - path: 'signin', - name: 'signin', - component: importedViews['SignIn'] // ์ž๋™ ์ž„ํฌํŠธ ์ ์šฉ - }, - { - path: 'signupform', - name: 'signupform', - component: importedViews['SignUpForm'] // ์ž๋™ ์ž„ํฌํŠธ ์ ์šฉ - }, - { - path: 'verifyemail', - name: 'verifyemail', - component: importedViews['VerifyEmail'] // ์ž๋™ ์ž„ํฌํŠธ ์ ์šฉ - }, - { - path: 'signupform2', - name: 'SignUpForm2', - component: importedViews['SignUpForm2'] // ์ž๋™ ์ž„ํฌํŠธ ์ ์šฉ - }, - { - path: 'signup', - name: 'SignupView', - component: importedViews['SignupView'] // ์ž๋™ ์ž„ํฌํŠธ ์ ์šฉ - }, - { - path: 'login', - name: 'LoginView', - component: importedViews['LoginView'] // ์ž๋™ ์ž„ํฌํŠธ ์ ์šฉ - } - ] - }, - { - path: '/profile', - name: 'profile', - component: importedViews['Profile'], // ์ž๋™ ์ž„ํฌํŠธ ์ ์šฉ - meta: { requiresAuth: true } // ์ธ์ฆ์ด ํ•„์š”ํ•œ ํŽ˜์ด์ง€ - }, - { - path: '/portfolios', - component: PortfolioLayout, // ๊ณตํ†ต ๋ ˆ์ด์•„์›ƒ ์ปดํฌ๋„ŒํŠธ - children: [ - { - path: 'new', - name: 'CreatePortfolio', - component: importedViews['PortfolioCreate'] // ์ž๋™ ์ž„ํฌํŠธ ์ ์šฉ - }, - { - path: 'tag', - name: 'SearchByTag', - component: importedViews['PortfolioByTag'] // ์ž๋™ ์ž„ํฌํŠธ ์ ์šฉ - }, - { - path: 'test', - name: 'Test', - component: importedViews['PortfolioTest'] // ์ž๋™ ์ž„ํฌํŠธ ์ ์šฉ - } - ] - }, - { - path: '/responsivetest', - name: 'TaliwindResopon', - component: importedViews['TaliwindResopon'] // ์ž๋™ ์ž„ํฌํŠธ ์ ์šฉ - }, - { - path: '/weeklycalendertest', - name: 'WeeklyCalenderTest', - component: importedViews['WeeklyCalenderTest'] // ์ž๋™ ์ž„ํฌํŠธ ์ ์šฉ - }, - { - path: '/:catchAll(.*)', - name: 'NotFound', - component: importedViews['NotFound'] // ์ž๋™ ์ž„ํฌํŠธ ์ ์šฉ - } -] - -const router = createRouter({ - history: createWebHashHistory('/akoming/'), // Hash ๋ชจ๋“œ๋ฅผ ์‚ฌ์šฉ - routes -}) - -//๋ผ์šฐํ„ฐ ๊ฐ€๋“œ ์„ค์ •(์„ธ์…˜ ๊ธฐ๋ฐ˜ ์ฟ ๊ธฐ, ๋‚˜์ค‘์— ์ˆ˜์ • ํ•„์š”) - -export default router