├── .env.development
├── .env.production
├── .eslintrc.cjs
├── .github
├── ISSUE_TEMPLATE
│ ├── bug_report.yml
│ ├── feature_request.yml
│ └── improvement_plan.yml
├── pull_request_template.md
└── workflows
│ └── node.js.yml
├── .gitignore
├── .project
├── Docs
└── development-env-setting.md
├── LICENSE
├── README.md
├── index.html
├── jsconfig.json
├── package-lock.json
├── package.json
├── public
├── assets
│ └── images
│ │ ├── banner_m_01.png
│ │ ├── banner_m_02.png
│ │ ├── banner_w_01.png
│ │ ├── banner_w_02.png
│ │ ├── img_business_intro.png
│ │ ├── img_business_intro_m.png
│ │ ├── img_sample.png
│ │ ├── img_sample2.png
│ │ ├── img_simple_main.png
│ │ ├── img_template_intro.png
│ │ ├── logo_footer_m.png
│ │ ├── logo_footer_w.png
│ │ ├── logo_m.png
│ │ ├── logo_w.png
│ │ ├── map.png
│ │ ├── qrcode.png
│ │ ├── reply_arrow.gif
│ │ └── sample_pds_list.png
├── index.html
└── vite.svg
├── src
├── App.js
├── App.jsx
├── App.test.jsx
├── EgovMain.test.jsx
├── api
│ ├── egovFetch.js
│ └── egovFetch.jsx
├── assets
│ └── react.svg
├── components
│ ├── EgovAttachFile.jsx
│ ├── EgovCondition.jsx
│ ├── EgovContainer.jsx
│ ├── EgovError.jsx
│ ├── EgovFooter.jsx
│ ├── EgovHeader.jsx
│ ├── EgovImageGallery.jsx
│ ├── EgovInfoPopup.jsx
│ ├── EgovLeftNav.jsx
│ ├── EgovPaging.jsx
│ ├── EgovRadioButton.jsx
│ ├── EgovRadioButtonGroup.jsx
│ ├── EgovSelect.jsx
│ ├── EgovViewTemplate.jsx
│ ├── leftmenu
│ │ ├── EgovLeftNavAbout.jsx
│ │ ├── EgovLeftNavAdmin.jsx
│ │ ├── EgovLeftNavInform.jsx
│ │ ├── EgovLeftNavIntro.jsx
│ │ └── EgovLeftNavSupport.jsx
│ └── sns
│ │ ├── SnsKakaoBt.jsx
│ │ ├── SnsKakaoCallback.jsx
│ │ ├── SnsNaverBt.jsx
│ │ └── SnsNaverCallback.jsx
├── config.js
├── config
│ ├── index.js
│ └── index.jsx
├── constants
│ ├── code.js
│ ├── code.jsx
│ ├── url.js
│ └── url.jsx
├── css
│ ├── base.css
│ ├── component.css
│ ├── images
│ │ ├── bg_btn_calendar.png
│ │ ├── bg_ds_t2.png
│ │ ├── bg_form_chk.png
│ │ ├── bg_form_chk_on.png
│ │ ├── bg_form_rdo.png
│ │ ├── bg_form_rdo_on.png
│ │ ├── ico_address.png
│ │ ├── ico_allmenu.png
│ │ ├── ico_allmenu_close.png
│ │ ├── ico_arrow_black_36x20.png
│ │ ├── ico_arrow_gray_15x9.png
│ │ ├── ico_arrow_r_gray_4x7.png
│ │ ├── ico_arrow_r_gray_9x15.png
│ │ ├── ico_arrow_up_gray_16x9.png
│ │ ├── ico_bn01.png
│ │ ├── ico_bn02.png
│ │ ├── ico_bn03.png
│ │ ├── ico_bn04.png
│ │ ├── ico_call.png
│ │ ├── ico_close_black44.png
│ │ ├── ico_delete.png
│ │ ├── ico_down.png
│ │ ├── ico_error.png
│ │ ├── ico_file.png
│ │ ├── ico_home.png
│ │ ├── ico_mail.png
│ │ ├── ico_more.png
│ │ ├── ico_person.png
│ │ ├── ico_plus.png
│ │ ├── ico_prev.png
│ │ ├── ico_question.png
│ │ ├── ico_reply.png
│ │ ├── ico_req.png
│ │ ├── ico_search_b.png
│ │ ├── ico_service_intro1.png
│ │ ├── ico_service_intro2.png
│ │ ├── ico_subway.png
│ │ ├── ico_v.png
│ │ ├── icon_google.png
│ │ ├── icon_kakao.png
│ │ ├── icon_naver.png
│ │ └── logo.jpg
│ ├── layout.css
│ ├── page.css
│ └── response.css
├── index.js
├── js
│ └── ui.js
├── main.jsx
├── pages
│ ├── about
│ │ ├── EgovAboutHistory.jsx
│ │ ├── EgovAboutLocation.jsx
│ │ ├── EgovAboutOrganization.jsx
│ │ └── EgovAboutSite.jsx
│ ├── admin
│ │ ├── board
│ │ │ ├── EgovAdminBoardEdit.jsx
│ │ │ └── EgovAdminBoardList.jsx
│ │ ├── gallery
│ │ │ ├── EgovAdminGalleryDetail.jsx
│ │ │ ├── EgovAdminGalleryEdit.jsx
│ │ │ └── EgovAdminGalleryList.jsx
│ │ ├── manager
│ │ │ └── EgovAdminPasswordUpdate.jsx
│ │ ├── members
│ │ │ ├── EgovAdminMemberEdit.jsx
│ │ │ └── EgovAdminMemberList.jsx
│ │ ├── notice
│ │ │ ├── EgovAdminNoticeDetail.jsx
│ │ │ ├── EgovAdminNoticeEdit.jsx
│ │ │ └── EgovAdminNoticeList.jsx
│ │ ├── schedule
│ │ │ ├── EgovAdminScheduleDetail.jsx
│ │ │ ├── EgovAdminScheduleEdit.jsx
│ │ │ └── EgovAdminScheduleList.jsx
│ │ └── usage
│ │ │ ├── EgovAdminUsageEdit.jsx
│ │ │ └── EgovAdminUsageList.jsx
│ ├── inform
│ │ ├── daily
│ │ │ ├── EgovDailyDetail.jsx
│ │ │ └── EgovDailyList.jsx
│ │ ├── gallery
│ │ │ ├── EgovGalleryDetail.jsx
│ │ │ ├── EgovGalleryEdit.jsx
│ │ │ └── EgovGalleryList.jsx
│ │ ├── notice
│ │ │ ├── EgovNoticeDetail.jsx
│ │ │ ├── EgovNoticeEdit.jsx
│ │ │ └── EgovNoticeList.jsx
│ │ └── weekly
│ │ │ └── EgovWeeklyList.jsx
│ ├── intro
│ │ ├── EgovIntroService.jsx
│ │ └── EgovIntroWork.jsx
│ ├── login
│ │ ├── EgovLogin.jsx
│ │ └── EgovLoginContent.jsx
│ ├── main
│ │ └── EgovMain.jsx
│ ├── mypage
│ │ └── EgovMypageEdit.jsx
│ └── support
│ │ ├── apply
│ │ └── EgovSupportApply.jsx
│ │ ├── download
│ │ ├── EgovDownloadCreate.jsx
│ │ ├── EgovDownloadDetail.jsx
│ │ └── EgovDownloadList.jsx
│ │ └── qna
│ │ ├── EgovQnaDetail.jsx
│ │ └── EgovQnaList.jsx
├── reportWebVitals.js
├── routes
│ └── index.jsx
└── utils
│ ├── bbsFormVaildator.js
│ ├── bbsFormVaildator.jsx
│ ├── calc.js
│ ├── calc.jsx
│ └── storage.js
├── vite.config.js
└── vitest.setup.js
/.env.development:
--------------------------------------------------------------------------------
1 | # 필수 지정 값
2 |
3 | ## 절대경로 지정
4 | NODE_PATH=src/
5 |
6 | ## 절대경로 지정
7 | VITE_APP_EGOV_CONTEXT_URL=localhost:8080
8 |
9 | #SNS 간편로그인 변수
10 | VITE_APP_NAVER_CLIENTID=YOUR_CLIENT_ID
11 | VITE_APP_NAVER_CALLBACKURL=http://localhost:3000/login/naver/callback
12 | VITE_APP_STATE=egovframe
13 | VITE_APP_KAKAO_CLIENTID=YOUR_CLIENT_ID
14 | VITE_APP_KAKAO_CALLBACKURL=http://localhost:3000/login/kakao/callback
--------------------------------------------------------------------------------
/.env.production:
--------------------------------------------------------------------------------
1 | # 필수 지정 값
2 |
3 | ## 절대경로 지정
4 | NODE_PATH=src/
5 |
6 | ## 절대경로 지정
7 | VITE_EGOV_CONTEXT_URL=127.0.0.1:8080
8 |
9 | ## [보안] 소스맵 삭제
10 | GENERATE_SOURCEMAP=false
11 |
--------------------------------------------------------------------------------
/.eslintrc.cjs:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | root: true,
3 | env: { browser: true, es2020: true, node: true },
4 | extends: [
5 | "eslint:recommended",
6 | "plugin:react/recommended",
7 | "plugin:react/jsx-runtime",
8 | "plugin:react-hooks/recommended",
9 | ],
10 | ignorePatterns: ["dist", ".eslintrc.cjs"],
11 | parserOptions: { ecmaVersion: "latest", sourceType: "module" },
12 | settings: { react: { version: "18.2" } },
13 | plugins: ["react-refresh"],
14 | rules: {
15 | "react/jsx-no-target-blank": "off",
16 | "react/prop-types": ["off"],
17 | "react-refresh/only-export-components": [
18 | "warn",
19 | { allowConstantExport: true },
20 | ],
21 | },
22 | };
23 |
--------------------------------------------------------------------------------
/.github/ISSUE_TEMPLATE/bug_report.yml:
--------------------------------------------------------------------------------
1 | name: 버그 리포트 Bug report
2 | description: 오류 내용을 이슈로 등록하는 템플릿입니다. Template to register an error as an issue.
3 | title: "[Bug]: "
4 | labels: ["bug", "triage"]
5 | assignees:
6 | - rukegithub
7 | body:
8 | - type: markdown
9 | attributes:
10 | value: |
11 | 시간을 내어 버그 리포트를 작성해 주셔서 감사합니다. Thank you for taking the time to fill out a bug report.
12 | - type: input
13 | id: contact
14 | attributes:
15 | label: 연락처 Contact
16 | description: 추가 정보 필요 시, 연락할 수 있는 이메일을 적어 주세요. Please include an email where we can reach you if we need more information. (Optional)
17 | placeholder: 예) email@example.com
18 | validations:
19 | required: false
20 | - type: textarea
21 | id: what-happened
22 | attributes:
23 | label: 오류 내용 Error Description
24 | description: 오류 내용을 기입해 주세요. Please provide a description of the error.
25 | placeholder: Tell us what you see!
26 | value: "오류를 발견했어요. I found an error."
27 | validations:
28 | required: true
29 | - type: textarea
30 | id: reproduce
31 | attributes:
32 | label: 오류 재현 방법 How to reproduce the error
33 | description: 오류 발생을 재현하려면, 어떻게 해야하나요? How can we reproduce the error you reported?
34 | placeholder: 오류 재현 방법 How to reproduce the error
35 | value: "(다음은 예시이며, 내용을 덮어 써 주세요. The following is an example, please overwrite the content.)\n\n
36 | 1. 다음 메뉴를 선택한다. Select the following menu '...'\n
37 | 2. 다음 버튼을 클릭한다. Click the Next button. '....'\n
38 | 3. 다음 문구까지 스크롤 다운한다. Scroll down to the following phrase '....'\n
39 | 4. 오류를 확인한다. Check for errors."
40 | validations:
41 | required: false
42 | - type: textarea
43 | id: environment
44 | attributes:
45 | label: 환경정보 Environmental Information
46 | description: 오류가 발생한 환경정보를 작성해 주세요. Please describe the environment in which the error occurred.
47 | placeholder: 오류 환경정보 Error Environment Information
48 | value: " - OS정보 Operating System: \n
49 | - 표준프레임워크 버전 eGovFrame Version: \n
50 | - JDK(JRE) 정보: \n
51 | - WAS 정보: \n
52 | - DB 정보: \n
53 | - 기타 환경 정보 Other environmental information:"
54 | validations:
55 | required: false
56 | - type: dropdown
57 | id: browsers
58 | attributes:
59 | label: 어느 브라우저를 사용했나요? Which browser did you use?
60 | multiple: true
61 | options:
62 | - Chrome
63 | - Firefox
64 | - Microsoft Edge
65 | - Opera
66 | - Safari
67 | - Internet Explorer
68 | - Others
69 | - type: textarea
70 | id: logs
71 | attributes:
72 | label: 에러 로그 Error Logs
73 | description: 관련 에러 로그를 복사하여 붙여넣어 주세요. Please copy and paste the relevant error logs.
74 | render: shell
75 |
--------------------------------------------------------------------------------
/.github/ISSUE_TEMPLATE/feature_request.yml:
--------------------------------------------------------------------------------
1 | name: 기능 요구 Feature Request
2 | description: 기능 요구를 이슈로 등록하는 템플릿입니다. Suggest a new feature for improving eGovFrame.
3 | title: "[기능요구(Feature)]: "
4 | labels: ["feature"]
5 | assignees:
6 | - rukegithub
7 | body:
8 | - type: markdown
9 | attributes:
10 | value: |
11 | 시간을 내어 의견을 작성해 주셔서 감사합니다. Thank you for taking the time to fill out a request.
12 | - type: input
13 | id: contact
14 | attributes:
15 | label: 연락처 Contact
16 | description: 추가 정보 필요 시, 연락할 수 있는 이메일을 적어 주세요. Please include an email where we can reach you if we need more information. (Optional)
17 | placeholder: 예) email@example.com
18 | validations:
19 | required: false
20 | - type: input
21 | id: feature-title
22 | attributes:
23 | label: 추가 요청 기능명 Feature Name
24 | description: 추가를 원하는 기능명칭을 간략히 적어주세요. Write the title of the feature you'd like to add.
25 | placeholder: 예) 게시판 첨부기능 추가 Example) Adding a bulletin board attachment
26 | validations:
27 | required: true
28 | - type: textarea
29 | id: feature-request-details
30 | attributes:
31 | label: 기능 상세 설명 Feature Description
32 | description: 추가를 원하는 기능에 대해 상세히 기술해 주세요. Please describe in detail the features you would like to see added.
33 | placeholder: 추가를 원하는 기능은 다음과 같습니다. Here are the features I'd like to see added
34 | validations:
35 | required: true
36 | - type: textarea
37 | id: solution
38 | attributes:
39 | label: 솔루션 상세 Solution Details
40 | description: 위 기능을 구현하는데 도움이 되는 기술내용이 있으면 적어 주세요. If you have any technical details to help us implement the above features, please let us know.
41 | placeholder: 위 기능을 구현하는데 도움이 되는 기술내용은 다음과 같습니다. Here are some technical details to help you implement the above features.
42 | validations:
43 | required: false
44 | - type: input
45 | id: solution-url
46 | attributes:
47 | label: 솔루션 관련 URL Solution-related URLs
48 | description: 위 기능을 구현하는데 도움이 되는 웹사이트 주소가 있으면 적어 주세요. If you have a website address that can help us implement the above features, please write it down.
49 | placeholder: Example) egovframe.go.kr
50 | validations:
51 | required: false
52 |
--------------------------------------------------------------------------------
/.github/ISSUE_TEMPLATE/improvement_plan.yml:
--------------------------------------------------------------------------------
1 | name: 발전 방안 제안 Improvement Plan
2 | description: 발전 방안을 이슈로 등록하는 템플릿입니다. Suggest a new plan for improving eGovFrame.
3 | title: "[발전 방안 제안(Improvement Plan)]: "
4 | labels: ["Improvement"]
5 | assignees:
6 | - yongfire38
7 | body:
8 | - type: markdown
9 | attributes:
10 | value: |
11 | 시간을 내어 의견을 작성해 주셔서 감사합니다. Thank you for taking the time to fill out a request.
12 | - type: input
13 | id: idea-name
14 | attributes:
15 | label: 아이디어명 Idea Name
16 | validations:
17 | required: true
18 | - type: textarea
19 | id: idea-summary
20 | attributes:
21 | label: 아이디어 요약 Idea Summary
22 | description: 과제 내용을 300자 이내로 간결하게 요약 및 정의해 주세요 Please summarize and define your content in 300 characters or less
23 | placeholder: 예) 게시판 첨부기능 추가 Example) Adding a bulletin board attachment
24 | validations:
25 | required: true
26 | - type: textarea
27 | id: suggestion-background
28 | attributes:
29 | label: 제안배경 Suggestion Background
30 | description: 아이디어를 제안하게 된 배경 및 필요성을 기술해 주세요. Please describe the background and need for the idea.
31 | placeholder: 아이디어를 제안하게 된 배경은 다음과 같습니다. The background to suggesting the idea is as follows.
32 | validations:
33 | required: true
34 | - type: textarea
35 | id: expectations
36 | attributes:
37 | label: 기대효과 Expectations
38 | description: 아이디어의 실현 가능성과 예상되는 기대효과를 제시하여 주세요. Please describe the expected impact and outcome of the idea.
39 | placeholder: 해당 아이디어의 기대효과는 다음과 같습니다. Here are the expected effects of this idea.
40 | validations:
41 | required: false
42 | - type: textarea
43 | id: free-writing
44 | attributes:
45 | label: 자유기술 Free Writing
46 | description: 추가 기재하고 싶은 항목 및 내용을 자유롭게 기재하여 주세요. Please feel free to add anything else you'd like to include.
47 | validations:
48 | required: false
49 | - type: textarea
50 | id: reference
51 | attributes:
52 | label: 참고문헌 Reference
53 | description: 참고문헌이 있는 경우 작성하여 주세요. If you have references, please include them.
54 | validations:
55 | required: false
56 |
--------------------------------------------------------------------------------
/.github/pull_request_template.md:
--------------------------------------------------------------------------------
1 | ## 수정 사유 Reason for modification
2 |
3 | 소스를 수정한 사유가 무엇인지 체크해 주세요. Please check the reason you modified the source. ([X] X는 대문자여야 합니다.)
4 |
5 | - [x] 버그수정 Bug fixes
6 | - [ ] 기능개선 Enhancements
7 | - [ ] 기능추가 Adding features
8 | - [ ] 기타 Others
9 |
10 | ## 수정된 소스 내용 Modified source
11 |
12 | 검토자를 위해 수정된 소스 내용을 설명해 주세요. Please describe the modified source for reviewers.
13 |
14 | ## JUnit 테스트 JUnit tests
15 |
16 | 테스트를 완료하셨으면 다음 항목에 [대문자X]로 표시해 주세요. When you're done testing, check the following items.
17 |
18 | - [x] JUnit 테스트 JUnit tests
19 | - [x] 수동 테스트 Manual testing
20 |
21 | ## 테스트 브라우저 Test Browser
22 |
23 | 테스트를 진행한 브라우저를 선택해 주세요. Please select the browser(s) you ran the test on. (다중 선택 가능 you can select multiple) [X] X는 대문자여야 합니다.
24 |
25 | - [ ] Chrome
26 | - [ ] Firefox
27 | - [ ] Edge
28 | - [ ] Safari
29 | - [ ] Opera
30 | - [ ] Internet Explorer
31 | - [ ] 기타 Others
32 |
33 | ## 테스트 스크린샷 또는 캡처 영상 Test screenshots or captured video
34 |
35 | 테스트 전과 후의 스크린샷 또는 캡처 영상을 이곳에 첨부해 주세요. Please attach screenshots or video captures of your before and after tests here.
36 |
--------------------------------------------------------------------------------
/.github/workflows/node.js.yml:
--------------------------------------------------------------------------------
1 | # This workflow will do a clean installation of node dependencies, cache/restore them, build the source code and run tests across different versions of node
2 | # For more information see: https://docs.github.com/en/actions/automating-builds-and-tests/building-and-testing-nodejs
3 |
4 | name: Node.js CI
5 |
6 | on:
7 | push:
8 | branches: ["main"]
9 | pull_request:
10 | branches: ["main"]
11 |
12 | jobs:
13 | build:
14 | runs-on: ubuntu-latest
15 |
16 | strategy:
17 | matrix:
18 | node-version: [18.x]
19 | # See supported Node.js release schedule at https://nodejs.org/en/about/releases/
20 |
21 | steps:
22 | - uses: actions/checkout@v3
23 | - name: Use Node.js ${{ matrix.node-version }}
24 | uses: actions/setup-node@v3
25 | with:
26 | node-version: ${{ matrix.node-version }}
27 | cache: "npm"
28 | - run: npm ci
29 | - run: npm run build --if-present
30 | - name: Run tests
31 | run: npm run test:run
32 | env:
33 | NODE_ENV: test
34 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # See https://help.github.com/articles/ignoring-files/ for more about ignoring files.
2 |
3 | # dependencies
4 | /node_modules
5 | /.pnp
6 | .pnp.js
7 |
8 | # testing
9 | /coverage
10 |
11 | # production
12 | /build
13 | /dist
14 |
15 | # misc
16 | .DS_Store
17 | .env.local
18 | .env.development.local
19 | .env.test.local
20 | .env.production.local
21 |
22 | npm-debug.log*
23 | yarn-debug.log*
24 | yarn-error.log*
25 |
26 | # code
27 | .history
--------------------------------------------------------------------------------
/.project:
--------------------------------------------------------------------------------
1 |
2 |
3 | egovframe-template-simple-react
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
--------------------------------------------------------------------------------
/Docs/development-env-setting.md:
--------------------------------------------------------------------------------
1 | # 개발환경 초기화 Initialization
2 |
3 | 본 문서는 vite를 통해 처음 프로젝트를 생성하려고 할때 필요한 내용을 기술하였음.
4 |
5 | ## React 개발환경 초기화
6 |
7 | ### 1. 프로젝트 생성
8 |
9 | ```bash
10 | npm create vite@latest
11 | ```
12 |
13 | ### 2. 생성 확인
14 |
15 | ```bash
16 | npm run dev
17 | ```
18 |
19 | ### 3. 필요없는 파일 및 소스 삭제
20 |
21 | 구현에 필요 없는 파일 및 소스들을 삭제한다
22 |
23 | ## 개발 세팅
24 |
25 | ### 환경변수 설정
26 |
27 | - 최상위 디렉토리에 `.env.development` 파일을 만들어 준다.
28 |
29 | - `VITE_APP`으로 시작하는 key 값과 Value 값을 정해주고
30 |
31 | js 에서 `process.env.<키명> 으로 불러와 지는지 확인 한다.
32 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # 표준프레임워크 심플홈페이지 FrontEnd
2 |
3 | 
4 | 
5 | 
6 | 
7 | 
8 | 
9 |
10 | ※ 본 프로젝트는 기존 JSP 뷰 방식에서 벗어나 BackEnd와 FrontEnd를 분리하기 위한 예시 파일로 참고만 하시길 바랍니다.
11 |
12 | ## 프로젝트 소개
13 |
14 | ### 프로젝트 개요
15 |
16 | 단순 홈페이지 기능 구현 시 필수적인 부분만 사용 가능하도록 경량화 된 실행환경 제공
17 | 메인 페이지, 사용자 관리, 공지사항 관리, 게시판 관리, 안내 관리 기능을 제공
18 |
19 | ### 메뉴 구성
20 |
21 | 
22 |
23 | ## 참고 화면 및 메뉴 설명
24 |
25 | ### 메인 화면
26 |
27 | 
28 |
29 | 1. 최초 관리자 계정 설정은 **[ 로그인계정 : admin , 로그인암호 : 1 ]** 로 설정되어 있다.
30 | 2. 메인 화면 우측 상단의 **회원가입** 버튼을 통해 사용자 계정을 생성 가능하다.
31 | 3. 기본 기능이나 예시 메뉴를 실무적으로 추가 커스터마이징하여 활용할 수 있다.
32 |
33 | ### 로그인 화면
34 |
35 | 
36 |
37 | 1. 최초 관리자 계정을 통한 로그인이 가능하다.
38 | 2. **회원가입** 버튼을 통해 생성한 사용자 계정을 통한 로그인이 가능하다. (사용자 계정은 일부 메뉴 접근이 제한된다)
39 | 3. 로그인 창 하단의 소셜 로그인 버튼으로 네이버 및 카카오 계정으로 로그인이 가능하다. 이 경우의 권한은 사용자 계정과 동일하다.
40 | 4. 소셜 로그인 기능의 사용을 위해서는 사전에 **[네이버 개발자 센터](https://developers.naver.com/main/)** 및 **[카카오 개발자 센터](https://developers.kakao.com/)** 에서 Client ID와 Client Secret을 발급 받은 후 Callback URL을 프론트엔드와 백엔드 환경 설정 파일에 등록해야 한다.
41 | 5. 프론트엔드 환경 설정 파일은 본 애플리케이션의 `.env.development` (개발 환경) 및 `.env.production` (빌드 시 사용) 을 참고한다.
42 | 6. 백엔드 환경 설정 파일은 [심플 홈페이지 Backend](https://github.com/eGovFramework/egovframe-template-simple-backend.git) 의 `application.properties` 를 참고한다.
43 | 7. 네이버 소셜 로그인에 대한 상세 사항은 **[네이버 로그인 API 문서](https://developers.naver.com/docs/login/api/api.md)** 를 참조 가능하다.
44 | 8. 카카오 소셜 로그인에 대한 상세 사항은 **[카카오 로그인 API 문서](https://developers.kakao.com/docs/latest/ko/kakaologin/rest-api#kakaologin)** 를 참조 가능하다.
45 |
46 | ### 사이트 소개 화면
47 |
48 | 
49 |
50 | - **해당 화면 및 세부 메뉴 화면은 구성을 위한 샘플페이지가 제공되며 기능은 구현되지 않은 상태입니다.**
51 |
52 | 1. 세부메뉴 : 사이트소개, 연혁, 조직소개, 찾아오시는 길
53 | 2. 기능설명 : 예시 메뉴에 해당하는 항목으로 샘플 페이지 형태로 존재한다.
54 | 3. 활용방법 : 각 샘플 페이지에 대한 콘텐츠를 새로 구성하여 활용할 수 있다.
55 |
56 | ### 정보마당 화면
57 |
58 | 
59 |
60 | - **해당 화면 및 세부 메뉴 화면은 구성을 위한 샘플페이지가 제공되며 기능은 구현되지 않은 상태입니다.**
61 |
62 | 1. 세부메뉴 : 주요사업 소개, 대표서비스 소개
63 | 2. 기능설명 : 예시 메뉴에 해당하는 항목으로 샘플 페이지 형태로 존재한다.
64 | 3. 활용방법 : 각 샘플 페이지에 대한 콘텐츠를 새로 구성하여 활용할 수 있다.
65 |
66 | ### 고객지원 화면
67 |
68 | 
69 |
70 | - **해당 화면 및 세부 메뉴 화면은 구성을 위한 샘플페이지가 제공되며 기능은 구현되지 않은 상태입니다.**
71 |
72 | 1. 세부메뉴 : 자료실, 묻고답하기, 서비스신청
73 | 2. 기능설명 : 예시 메뉴에 해당하는 항목으로 샘플 페이지 형태로 존재한다.
74 | 3. 활용방법 : 각 샘플 페이지에 기능을 추가 개발 후 구성하여 활용할 수 있다.
75 |
76 | ### 알림마당 화면
77 |
78 | 
79 |
80 | 1. 세부메뉴 : 오늘의행사, 금주의행사, 공지사항, 사이트갤러리
81 | 2. 기능설명 : 공통컴포넌트 일정관리(부서일정)와 게시판 기능을 커스터마이징하여 사용한다.
82 | 3. 활용방법 : 관리자가 등록한 일정정보를 조회하거나 게시물을 조회할 수 있다.
83 |
84 | ### 사이트관리 화면
85 |
86 | 
87 |
88 | 1. 세부메뉴 : 일정관리, 게시판생성관리, 게시판사용관리, 공지사항관리, 사이트갤러리관리, 사이트관리자 암호변경, 회원관리
89 | 2. 기능설명 : 공통컴포넌트 일정관리(부서일정)과 게시판 기능을 커스터마이징하여 사용한다.
90 | 3. 활용방법 : 관리자로 로그인 한 후 일정정보를 등록하거나 게시물을 등록할 수 있다. (게시판 설정 가능)
91 |
92 | ## 환경 설정
93 |
94 | 프로젝트에서 사용된 환경 프로그램 정보는 다음과 같다.
95 |
96 | | 프로그램 명 | 버전 명 |
97 | | :---------- | :------- |
98 | | Node.js | v18.12.0 |
99 | | NPM | v8.19.2 |
100 |
101 | ## BackEnd 구동
102 |
103 | [심플 홈페이지 Backend](https://github.com/eGovFramework/egovframe-template-simple-backend.git) 소스를 받아 구동한다.
104 |
105 | ## FrontEnd 구동
106 |
107 | 아래 1 ~ 3의 과정을 따라서 진행한다.
108 |
109 | ### 1. 프로젝트의 생성
110 |
111 | Git에서 복제하여 설치 시 1-1. 을 참고한다.
112 |
113 | #### 1-1. Git에서 프로젝트 복제 및 모듈 설치
114 |
115 | Git에서 clone 한다.
116 |
117 | ```bash
118 | # 프로젝트 저장소를 로컬로 복제
119 | git clone https://github.com/[계정명]/egovframe-template-simple-react.git
120 |
121 | # 복제된 프로젝트 디렉토리로 이동
122 | cd egovframe-template-simple-react
123 |
124 | # node modules를 설치해 준다.
125 | npm install
126 | ```
127 |
128 | ### 2. 백엔드 프로젝트 설정
129 |
130 | 구동된 BackEnd 서버의 URL을 본 어플리케이션의 .env.development 파일의 VITE_EGOV_CONTEXT_URL에 설정해 준다.
131 | (단, 개발환경에서는 사용하는 환경변수 정보는 .env.development, build 시 사용하는 환경변수는 .env.production 에 기입해 준다.)
132 |
133 | ```bash
134 | # .env.development 예시
135 | VITE_APP_EGOV_CONTEXT_URL=localhost:8080
136 | ```
137 |
138 | ### 3. 프로젝트 실행 및 기타 명령어
139 |
140 | ```bash
141 | # 테스트용 리액트 서버를 실행할 때 아래 명령어를 사용한다.
142 | npm run dev
143 | ```
144 |
145 | ```bash
146 | # 빌드할 때에는 아래 명령어를 사용한다.
147 | npm run build
148 | ```
149 |
150 | ```bash
151 | # 로컬에서 미리보기할 때는 아래 명령어를 사용한다.
152 | npm run preview
153 | ```
154 |
155 | ```bash
156 | # 테스트 대상 파일 경로는 vite.config.js에 명시되어 있으며 디폴트로 EgovMain.jsx의 테스트를 실행한다.
157 | # watch 모드로 테스트를 실행할 경우에는 아래 명령어를 사용한다.
158 | npm run test
159 |
160 | # 일회성 테스트를 실행할 경우에는 아래 명령어를 사용한다.
161 | npm run test:run
162 | ```
163 |
164 | ---
165 |
166 | ### 참조
167 |
168 | 보다 상세한 설명은 아래의 문서를 확인한다.
169 |
170 | 1. [vite 공식 가이드 문서(한글)](https://vitejs-kr.github.io/guide/)
171 | 2. [개발환경 초기 설정](./Docs/development-env-setting.md)
172 |
--------------------------------------------------------------------------------
/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | React App
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/jsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "compilerOptions": {
3 | "baseUrl": "src/"
4 | },
5 | "include": [
6 | "src"
7 | ]
8 | }
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "egovframe-template-simple-react",
3 | "private": true,
4 | "version": "0.0.0",
5 | "type": "module",
6 | "dependencies": {
7 | "egovframe-template-simple-react": "file:",
8 | "qs": "^6.11.0",
9 | "react": "^18.3.1",
10 | "react-datepicker": "^4.8.0",
11 | "react-dom": "^18.3.1",
12 | "react-router-dom": "^6.4.0",
13 | "web-vitals": "^2.1.4"
14 | },
15 | "devDependencies": {
16 | "@babel/plugin-proposal-private-property-in-object": "^7.0.0",
17 | "@testing-library/jest-dom": "^5.17.0",
18 | "@testing-library/react": "^13.4.0",
19 | "@testing-library/user-event": "^13.5.0",
20 | "@types/react": "^18.3.3",
21 | "@types/react-dom": "^18.3.0",
22 | "@vitejs/plugin-react": "4.3.1",
23 | "@vitejs/plugin-react-swc": "^3.5.0",
24 | "eslint": "^8.57.0",
25 | "eslint-plugin-react": "^7.34.3",
26 | "eslint-plugin-react-hooks": "^4.6.2",
27 | "eslint-plugin-react-refresh": "^0.4.7",
28 | "react-scripts": "5.0.1",
29 | "vite": "^5.3.4",
30 | "vitest": "2.0.4"
31 | },
32 | "scripts": {
33 | "dev": "vite",
34 | "build": "vite build",
35 | "lint": "eslint . --ext js,jsx --report-unused-disable-directives --max-warnings 0",
36 | "preview": "vite preview",
37 | "test": "vitest",
38 | "test:run": "vitest run"
39 | },
40 | "proxy": "http://localhost:8080"
41 | }
42 |
--------------------------------------------------------------------------------
/public/assets/images/banner_m_01.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/eGovFramework/egovframe-template-simple-react/e6e9ef0391cea902b99141c20fafbc08d121425c/public/assets/images/banner_m_01.png
--------------------------------------------------------------------------------
/public/assets/images/banner_m_02.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/eGovFramework/egovframe-template-simple-react/e6e9ef0391cea902b99141c20fafbc08d121425c/public/assets/images/banner_m_02.png
--------------------------------------------------------------------------------
/public/assets/images/banner_w_01.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/eGovFramework/egovframe-template-simple-react/e6e9ef0391cea902b99141c20fafbc08d121425c/public/assets/images/banner_w_01.png
--------------------------------------------------------------------------------
/public/assets/images/banner_w_02.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/eGovFramework/egovframe-template-simple-react/e6e9ef0391cea902b99141c20fafbc08d121425c/public/assets/images/banner_w_02.png
--------------------------------------------------------------------------------
/public/assets/images/img_business_intro.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/eGovFramework/egovframe-template-simple-react/e6e9ef0391cea902b99141c20fafbc08d121425c/public/assets/images/img_business_intro.png
--------------------------------------------------------------------------------
/public/assets/images/img_business_intro_m.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/eGovFramework/egovframe-template-simple-react/e6e9ef0391cea902b99141c20fafbc08d121425c/public/assets/images/img_business_intro_m.png
--------------------------------------------------------------------------------
/public/assets/images/img_sample.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/eGovFramework/egovframe-template-simple-react/e6e9ef0391cea902b99141c20fafbc08d121425c/public/assets/images/img_sample.png
--------------------------------------------------------------------------------
/public/assets/images/img_sample2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/eGovFramework/egovframe-template-simple-react/e6e9ef0391cea902b99141c20fafbc08d121425c/public/assets/images/img_sample2.png
--------------------------------------------------------------------------------
/public/assets/images/img_simple_main.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/eGovFramework/egovframe-template-simple-react/e6e9ef0391cea902b99141c20fafbc08d121425c/public/assets/images/img_simple_main.png
--------------------------------------------------------------------------------
/public/assets/images/img_template_intro.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/eGovFramework/egovframe-template-simple-react/e6e9ef0391cea902b99141c20fafbc08d121425c/public/assets/images/img_template_intro.png
--------------------------------------------------------------------------------
/public/assets/images/logo_footer_m.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/eGovFramework/egovframe-template-simple-react/e6e9ef0391cea902b99141c20fafbc08d121425c/public/assets/images/logo_footer_m.png
--------------------------------------------------------------------------------
/public/assets/images/logo_footer_w.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/eGovFramework/egovframe-template-simple-react/e6e9ef0391cea902b99141c20fafbc08d121425c/public/assets/images/logo_footer_w.png
--------------------------------------------------------------------------------
/public/assets/images/logo_m.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/eGovFramework/egovframe-template-simple-react/e6e9ef0391cea902b99141c20fafbc08d121425c/public/assets/images/logo_m.png
--------------------------------------------------------------------------------
/public/assets/images/logo_w.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/eGovFramework/egovframe-template-simple-react/e6e9ef0391cea902b99141c20fafbc08d121425c/public/assets/images/logo_w.png
--------------------------------------------------------------------------------
/public/assets/images/map.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/eGovFramework/egovframe-template-simple-react/e6e9ef0391cea902b99141c20fafbc08d121425c/public/assets/images/map.png
--------------------------------------------------------------------------------
/public/assets/images/qrcode.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/eGovFramework/egovframe-template-simple-react/e6e9ef0391cea902b99141c20fafbc08d121425c/public/assets/images/qrcode.png
--------------------------------------------------------------------------------
/public/assets/images/reply_arrow.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/eGovFramework/egovframe-template-simple-react/e6e9ef0391cea902b99141c20fafbc08d121425c/public/assets/images/reply_arrow.gif
--------------------------------------------------------------------------------
/public/assets/images/sample_pds_list.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/eGovFramework/egovframe-template-simple-react/e6e9ef0391cea902b99141c20fafbc08d121425c/public/assets/images/sample_pds_list.png
--------------------------------------------------------------------------------
/public/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | React App
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
--------------------------------------------------------------------------------
/public/vite.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/App.js:
--------------------------------------------------------------------------------
1 | import RootRoutes from './routes';
2 | import React from 'react';
3 |
4 | import './css/base.css';
5 | import './css/layout.css';
6 | import './css/component.css';
7 | import './css/page.css';
8 | import './css/response.css';
9 |
10 | function App() {
11 |
12 | return (
13 |
14 |
15 |
16 |
17 |
18 | )
19 | }
20 |
21 | console.log("process.env.NODE_ENV", process.env.NODE_ENV);
22 | console.log("process.env.REACT_APP_EGOV_CONTEXT_URL", process.env.REACT_APP_EGOV_CONTEXT_URL);
23 |
24 | export default App;
25 |
--------------------------------------------------------------------------------
/src/App.jsx:
--------------------------------------------------------------------------------
1 | import RootRoutes from "@/routes";
2 | import React from "react";
3 | import { BrowserRouter as Router } from "react-router-dom";
4 |
5 | import "@/css/base.css";
6 | import "@/css/layout.css";
7 | import "@/css/component.css";
8 | import "@/css/page.css";
9 | import "@/css/response.css";
10 |
11 | function App() {
12 | return (
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 | );
21 | }
22 |
23 | export default App;
24 |
--------------------------------------------------------------------------------
/src/App.test.jsx:
--------------------------------------------------------------------------------
1 | import { describe, it, expect } from 'vitest';
2 |
3 | describe('App', () => {
4 | it('passes a simple test', () => {
5 | expect(true).toBe(true);
6 | });
7 | });
--------------------------------------------------------------------------------
/src/EgovMain.test.jsx:
--------------------------------------------------------------------------------
1 | import { render } from "@testing-library/react";
2 | import { MemoryRouter } from "react-router-dom";
3 | import { describe, it } from "vitest";
4 | import EgovMain from "@/pages/main/EgovMain";
5 |
6 | describe("EgovMain Component", () => {
7 | it("renders correctly", () => {
8 | render(
9 |
10 |
11 |
12 | );
13 | });
14 | });
15 |
--------------------------------------------------------------------------------
/src/api/egovFetch.js:
--------------------------------------------------------------------------------
1 | import { SERVER_URL } from "../config";
2 |
3 | import URL from "@/constants/url";
4 | import CODE from "@/constants/code";
5 | import { getSessionItem, setSessionItem } from "@/utils/storage";
6 |
7 | export function getQueryString(params) {
8 | return `?${Object.entries(params)
9 | .map((e) => e.join("="))
10 | .join("&")}`;
11 | }
12 |
13 | export function requestFetch(url, requestOptions, handler, errorHandler) {
14 | console.groupCollapsed("requestFetch");
15 | console.log("requestFetch [URL] : ", SERVER_URL + url);
16 | console.log("requestFetch [requestOption] : ", requestOptions);
17 |
18 | // Login 했을경우 JWT 설정
19 | const sessionUser = getSessionItem("loginUser");
20 | const sessionUserId = sessionUser?.id || null;
21 | const jToken = getSessionItem("jToken");
22 | if (sessionUserId != null && sessionUserId !== undefined) {
23 | if (!requestOptions["headers"]) requestOptions["headers"] = {};
24 | if (!requestOptions["headers"]["Authorization"])
25 | requestOptions["headers"]["Authorization"] = null;
26 | requestOptions["headers"]["Authorization"] = jToken;
27 | }
28 |
29 | //CORS ISSUE 로 인한 조치 - origin 및 credentials 추가
30 | // origin 추가
31 | if (!requestOptions["origin"]) {
32 | requestOptions = { ...requestOptions, origin: SERVER_URL };
33 | }
34 | // credentials 추가
35 | if (!requestOptions["credentials"]) {
36 | requestOptions = { ...requestOptions, credentials: "include" };
37 | }
38 |
39 | fetch(SERVER_URL + url, requestOptions)
40 | .then((response) => {
41 | // response Stream. Not completion object
42 | //console.log("requestFetch [Response Stream] ", response);
43 | return response.json();
44 | })
45 | .then((resp) => {
46 | if (Number(resp.resultCode) === Number(CODE.RCV_ERROR_AUTH)) {
47 | alert("Login Alert"); //index.jsx라우터파일에 jwtAuthentication 함수로 공통 인증을 사용하는 코드 추가로 alert 원상복구
48 | setSessionItem("loginUser", { id: "" });
49 | window.location.href = URL.LOGIN;
50 | return false;
51 | } else {
52 | return resp;
53 | }
54 | })
55 | .then((resp) => {
56 | console.groupCollapsed("requestFetch.then()");
57 | console.log("requestFetch [response] ", resp);
58 | if (typeof handler === "function") {
59 | handler(resp);
60 | } else {
61 | console.log("egov fetch handler not assigned!");
62 | }
63 | console.groupEnd("requestFetch.then()");
64 | })
65 | .catch((error) => {
66 | console.error("There was an error!", error);
67 | if (error === "TypeError: Failed to fetch") {
68 | alert("서버와의 연결이 원활하지 않습니다. 서버를 확인하세요.");
69 | }
70 |
71 | if (typeof errorHandler === "function") {
72 | errorHandler(error);
73 | } else {
74 | console.error("egov error handler not assigned!");
75 | alert("ERR : " + error.message);
76 | }
77 | })
78 | .finally(() => {
79 | console.log("requestFetch finally end");
80 | console.groupEnd("requestFetch");
81 | });
82 | }
83 |
--------------------------------------------------------------------------------
/src/api/egovFetch.jsx:
--------------------------------------------------------------------------------
1 | import { SERVER_URL } from "../config";
2 |
3 | import URL from "@/constants/url";
4 | import CODE from "@/constants/code";
5 |
6 | export function requestFetch(url, requestOptions, handler, errorHandler) {
7 | console.groupCollapsed("requestFetch");
8 | console.log("requestFetch [URL] : ", SERVER_URL + url);
9 | console.log("requestFetch [requestOption] : ", requestOptions);
10 |
11 | //CORS ISSUE 로 인한 조치 - origin 및 credentials 추가
12 | // origin 추가
13 | if (!requestOptions["origin"]) {
14 | requestOptions = { ...requestOptions, origin: SERVER_URL };
15 | }
16 | // credentials 추가
17 | if (!requestOptions["credentials"]) {
18 | requestOptions = { ...requestOptions, credentials: "include" };
19 | }
20 |
21 | fetch(SERVER_URL + url, requestOptions)
22 | .then((response) => {
23 | // response Stream. Not completion object
24 | //console.log("requestFetch [Response Stream] ", response);
25 | return response.json();
26 | })
27 | .then((resp) => {
28 | if (Number(resp.resultCode) === Number(CODE.RCV_ERROR_AUTH)) {
29 | alert("Login Alert"); //index.jsx라우터파일에 jwtAuthentication 함수로 공통 인증을 사용하는 코드 추가로 alert 원상복구
30 | sessionStorage.setItem("loginUser", JSON.stringify({ id: "" }));
31 | window.location.href = URL.LOGIN;
32 | return false;
33 | } else {
34 | return resp;
35 | }
36 | })
37 | .then((resp) => {
38 | console.groupCollapsed("requestFetch.then()");
39 | console.log("requestFetch [response] ", resp);
40 | if (typeof handler === "function") {
41 | handler(resp);
42 | } else {
43 | console.log("egov fetch handler not assigned!");
44 | }
45 | console.groupEnd("requestFetch.then()");
46 | })
47 | .catch((error) => {
48 | console.error("There was an error!", error);
49 | if (error === "TypeError: Failed to fetch") {
50 | alert("서버와의 연결이 원활하지 않습니다. 서버를 확인하세요.");
51 | }
52 |
53 | if (typeof errorHandler === "function") {
54 | errorHandler(error);
55 | } else {
56 | console.error("egov error handler not assigned!");
57 | alert("ERR : " + error.message);
58 | }
59 | })
60 | .finally(() => {
61 | console.log("requestFetch finally end");
62 | console.groupEnd("requestFetch");
63 | });
64 | }
65 |
--------------------------------------------------------------------------------
/src/assets/react.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/components/EgovAttachFile.jsx:
--------------------------------------------------------------------------------
1 | import React from "react";
2 | import { useNavigate } from "react-router-dom";
3 |
4 | import URL from "@/constants/url";
5 | import * as EgovNet from "@/api/egovFetch";
6 | import { SERVER_URL } from "@/config";
7 | import CODE from "@/constants/code";
8 |
9 | function EgovAttachFile({
10 | boardFiles,
11 | mode,
12 | fnChangeFile,
13 | fnDeleteFile,
14 | posblAtchFileNumber,
15 | }) {
16 | console.groupCollapsed("EgovAttachFile");
17 |
18 | // posblAtchFileNumber는 수정일 경우에만 값이 넘어오므로 방어 로직
19 | // 해당 컴포넌트는 스케줄 화면과 공유하며, 스케줄에서는 첨부파일을 1개 넣을 수 있으므로 디폴트 값을 1로 설정
20 | if (
21 | typeof posblAtchFileNumber == "undefined" ||
22 | posblAtchFileNumber == null
23 | ) {
24 | posblAtchFileNumber = 1;
25 | }
26 |
27 | const navigate = useNavigate();
28 |
29 | function onClickDownFile(atchFileId, fileSn) {
30 | window.open(
31 | SERVER_URL + "/file?atchFileId=" + atchFileId + "&fileSn=" + fileSn + ""
32 | );
33 | }
34 |
35 | function onClickDeleteFile(atchFileId, fileSn, fileIndex) {
36 | console.log("onClickDeleteFile Params : ", atchFileId, fileSn, fileIndex);
37 |
38 | const requestOptions = {
39 | method: "POST",
40 | headers: {
41 | "Content-type": "application/json",
42 | },
43 | body: JSON.stringify({
44 | atchFileId: atchFileId,
45 | fileSn: fileSn,
46 | }),
47 | };
48 | EgovNet.requestFetch(`/file`, requestOptions, function (resp) {
49 | console.log("===>>> board file delete= ", resp);
50 | if (Number(resp.resultCode) === Number(CODE.RCV_SUCCESS)) {
51 | // 성공
52 | console.log("Deleted fileIndex = ", fileIndex);
53 | // eslint-disable-next-line no-unused-vars
54 | const _deleteFile = boardFiles.splice(fileIndex, 1);
55 | const _boardFiles = Object.assign([], boardFiles);
56 | fnDeleteFile(_boardFiles);
57 | alert("첨부파일이 삭제되었습니다.");
58 | fnChangeFile({});
59 | } else {
60 | navigate(
61 | { pathname: URL.ERROR },
62 | { state: { msg: resp.resultMessage } }
63 | );
64 | }
65 | });
66 | }
67 |
68 | function onChangeFileInput(e) {
69 | console.log("===>>> e = " + e.target.files[0]);
70 | if (
71 | e.target.files.length + (boardFiles?.length || 0) >
72 | posblAtchFileNumber
73 | ) {
74 | alert("총 첨부파일 개수는 " + posblAtchFileNumber + " 까지 입니다.");
75 | e.target.value = null; // 파일 입력란 화면 초기화
76 | fnChangeFile({}); // 상위 컴포넌트의 저장된 값 초기화
77 | return false;
78 | }
79 | fnChangeFile(e.target.files);
80 | }
81 |
82 | let filesTag = [];
83 |
84 | if (boardFiles !== undefined) {
85 | boardFiles.forEach(function (item, index) {
86 | filesTag.push(
87 |
88 |
89 |
97 | {item.orignlFileNm}
98 |
99 | [{item.fileMg}byte]
100 |
101 |
102 | );
103 |
104 | if (mode === CODE.MODE_MODIFY) {
105 | filesTag.push(
106 |
107 | {
110 | onClickDeleteFile(item.atchFileId, item.fileSn, index);
111 | }}
112 | >
113 |
114 | );
115 | }
116 | filesTag.push( );
117 | });
118 | }
119 | console.log("filesTag : ", filesTag);
120 | console.groupEnd("EgovAttachFile");
121 |
122 | return (
123 |
124 | 첨부파일
125 |
126 |
127 | {filesTag}
128 | {mode === CODE.MODE_CREATE && (
129 | <>
130 | onChangeFileInput(e)}
136 | >
137 | 총 업로드 가능한 첨부파일 개수는 {posblAtchFileNumber} 개 입니다.
138 | >
139 | )}
140 | {/* 첨부파일 1개 당 filesTag는 3개 요소(span, button, br)를 가진다 */}
141 | {mode === CODE.MODE_MODIFY &&
142 | filesTag.length / 3 < posblAtchFileNumber && (
143 | <>
144 | onChangeFileInput(e)}
150 | >
151 | 현재 업로드 가능한 첨부파일 개수는{" "}
152 | {posblAtchFileNumber - filesTag.length / 3} 개 입니다.
153 | >
154 | )}
155 |
156 |
157 |
158 | );
159 | }
160 |
161 | export default EgovAttachFile;
162 |
--------------------------------------------------------------------------------
/src/components/EgovCondition.jsx:
--------------------------------------------------------------------------------
1 | import { Link } from "react-router-dom";
2 |
3 | function EgovCondition() {
4 | return (
5 |
6 |
7 |
8 |
9 |
10 | 전체
11 | 회의
12 | 세미나
13 | 강의
14 | 교육
15 | 기타
16 |
17 |
18 |
19 |
20 |
21 | 이전연도로이동
22 |
23 | 2021년
24 |
25 | 다음연도로이동
26 |
27 |
28 |
29 |
30 | 이전월로이동
31 |
32 | 8월
33 |
34 | 다음월로이동
35 |
36 |
37 |
38 |
39 | 이전주로이동
40 |
41 | 1주
42 |
43 | 다음주로이동
44 |
45 |
46 |
47 |
48 | );
49 | }
50 |
51 | export default EgovCondition;
52 |
--------------------------------------------------------------------------------
/src/components/EgovContainer.jsx:
--------------------------------------------------------------------------------
1 | import { Link } from "react-router-dom";
2 |
3 | import EgovLeftNav from "@/components/EgovLeftNav";
4 |
5 | function EgovContainer() {
6 | return (
7 |
8 |
9 | {/* */}
10 |
11 |
12 |
13 |
14 | Home
15 |
16 |
17 |
18 | 알림마당
19 |
20 | 오늘의 행사
21 |
22 |
23 | {/* */}
24 |
25 |
26 | {/* */}
27 |
28 | {/* */}
29 |
30 | {/* */}
31 |
32 |
33 |
알림마당
34 |
35 |
36 |
금주의 행사
37 |
38 | {/* */}
39 |
40 |
41 |
42 |
43 |
44 | 전체
45 | 회의
46 | 세미나
47 | 강의
48 | 교육
49 | 기타
50 |
51 |
52 |
53 |
54 |
55 | 이전연도로이동
56 |
57 | 2021년
58 |
59 | 다음연도로이동
60 |
61 |
62 |
63 |
64 | 이전월로이동
65 |
66 | 8월
67 |
68 | 다음월로이동
69 |
70 |
71 |
72 |
73 | 이전주로이동
74 |
75 | 1주
76 |
77 | 다음주로이동
78 |
79 |
80 |
81 |
82 | {/* */}
83 |
84 | {/* */}
85 |
86 |
87 | 날짜
88 | 시간
89 | 제목
90 | 담당자
91 |
92 |
93 | {/* */}
94 |
95 | 검색된 결과가 없습니다.
96 |
97 |
98 | {/* */}
99 |
100 |
2021년07월11일 일요일
101 |
11:00~12:30
102 |
103 | 전자정부표준프레임워크 금주의 행사안내입니다.
104 |
105 |
관리자
106 |
107 |
108 |
2021년07월11일 일요일
109 |
11:00~12:30
110 |
111 | 전자정부표준프레임워크 금주의 행사안내입니다.
112 |
113 |
관리자
114 |
115 |
116 |
2021년07월11일 일요일
117 |
11:00~12:30
118 |
119 | 전자정부표준프레임워크 금주의 행사안내입니다.
120 |
121 |
관리자
122 |
123 |
124 |
2021년07월11일 일요일
125 |
11:00~12:30
126 |
127 | 전자정부표준프레임워크 금주의 행사안내입니다.
128 |
129 |
관리자
130 |
131 |
132 |
2021년07월11일 일요일
133 |
11:00~12:30
134 |
135 | 전자정부표준프레임워크 금주의 행사안내입니다.
136 |
137 |
관리자
138 |
139 |
140 |
141 | {/* */}
142 |
143 |
144 | {/* */}
145 |
146 |
147 | 이전
148 |
149 |
150 |
151 |
152 | 1
153 |
154 |
155 |
156 | 2
157 |
158 |
159 | 3
160 |
161 |
162 | 4
163 |
164 |
165 | 5
166 |
167 |
168 |
169 | 다음
170 |
171 |
172 | {/* */}
173 |
174 |
175 | {/* */}
176 |
177 |
178 |
179 | );
180 | }
181 |
182 | export default EgovContainer;
183 |
--------------------------------------------------------------------------------
/src/components/EgovError.jsx:
--------------------------------------------------------------------------------
1 | import { useNavigate, useLocation } from "react-router-dom";
2 |
3 | function EgovError() {
4 | const navigate = useNavigate();
5 | const location = useLocation();
6 |
7 | let errormessage = location.state.msg || "알 수 없는 에러가 발생했습니다.";
8 |
9 | if (errormessage === "No message available") {
10 | errormessage = "알 수 없는 에러가 발생했습니다.";
11 | }
12 |
13 | const goBack = () => {
14 | navigate(-1, { replace: true }); // 이전 URL을 현재 페이지 인식하고 재 로딩하는 코드.
15 | };
16 |
17 | return (
18 |
19 |
Error
20 |
21 |
{errormessage}
22 |
23 |
24 | 이전페이지
25 |
26 |
27 |
28 |
29 | );
30 | }
31 |
32 | export default EgovError;
33 |
--------------------------------------------------------------------------------
/src/components/EgovFooter.jsx:
--------------------------------------------------------------------------------
1 | import { Link } from "react-router-dom";
2 |
3 | import logoFooterImg from "/assets/images/logo_footer_w.png";
4 | import logoFooterImgMobile from "/assets/images/logo_footer_m.png";
5 | import bannerImg_01 from "/assets/images/banner_w_01.png";
6 | import bannerImgMobile_01 from "/assets/images/banner_m_01.png";
7 | import bannerImg_02 from "/assets/images/banner_w_02.png";
8 | import bannerImgMobile_02 from "/assets/images/banner_m_02.png";
9 |
10 | function EgovFooter() {
11 | return (
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 | 대표문의메일 : egovframeexample@gmail.com{" "}
23 | |
24 | 대표전화 : 0000-0000 (000-0000-0000)
25 |
26 | 호환성확인 : 000-0000-0000 | 교육문의 : 0000-0000-0000
27 |
28 |
29 | Copyright © 2021 Ministry Of The Interior And Safety. All Rights
30 | Reserved.
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 | );
46 | }
47 |
48 | export default EgovFooter;
49 |
--------------------------------------------------------------------------------
/src/components/EgovImageGallery.jsx:
--------------------------------------------------------------------------------
1 | import React from "react";
2 | import { SERVER_URL } from "@/config";
3 |
4 | function EgovImageGallery({ boardFiles }) {
5 | let filesTag = [];
6 |
7 | if (boardFiles !== undefined) {
8 | boardFiles.forEach(function (item, index) {
9 | filesTag.push(
10 |
11 |
15 |
16 |
17 | );
18 | });
19 | }
20 | console.log("filesTag : ", filesTag);
21 | console.groupEnd("EgovAttachFile");
22 |
23 | return {filesTag}
;
24 | }
25 |
26 | export default EgovImageGallery;
27 |
--------------------------------------------------------------------------------
/src/components/EgovInfoPopup.jsx:
--------------------------------------------------------------------------------
1 | import templateIntroImg from "/assets/images/img_template_intro.png";
2 |
3 | function EgovInfoPopup() {
4 | return (
5 |
6 |
7 |
8 |
홈페이지 템플릿 소개
9 |
10 | 닫기
11 |
12 |
13 |
14 |
15 |
16 |
17 | 경량환경 템플릿은 개발자가 프레임워크 쉽게 이해하고 활용할 수
18 | 있도록 지원합니다.
19 |
20 |
21 | 홈페이지 템플릿은 공통컴포넌트를 기반으로 아래 그림과 같이 메뉴가
22 | 구성됩니다.
23 |
24 |
25 | 관리자로 로그인하면 관리자용 메뉴를 추가로 사용할 수 있습니다.
26 |
27 |
28 | 사이트소개, 정보마당, 고객지원 메뉴는 구성을 위한 샘플페이지가
29 | 제공되며 기능은 구현되지 않은 상태입니다.
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 | );
39 | }
40 |
41 | export default EgovInfoPopup;
42 |
--------------------------------------------------------------------------------
/src/components/EgovLeftNav.jsx:
--------------------------------------------------------------------------------
1 | import { NavLink } from "react-router-dom";
2 | import URL from "@/constants/url";
3 |
4 | function EgovLeftNav() {
5 | return (
6 |
7 |
8 |
알림마당
9 |
10 |
11 | (isActive ? "cur" : "")}
14 | >
15 | 오늘의 행사
16 |
17 |
18 |
19 | (isActive ? "cur" : "")}
22 | >
23 | 금주의 행사
24 |
25 |
26 |
27 | (isActive ? "cur" : "")}
30 | >
31 | 공지사항
32 |
33 |
34 |
35 | (isActive ? "cur" : "")}
38 | >
39 | 사이트갤러리
40 |
41 |
42 |
43 |
44 |
45 | );
46 | }
47 |
48 | export default EgovLeftNav;
49 |
--------------------------------------------------------------------------------
/src/components/EgovPaging.jsx:
--------------------------------------------------------------------------------
1 | function EgovPaging(props) {
2 | console.groupCollapsed("EgovPaging");
3 | console.log("EgovPaging [props] : ", props);
4 |
5 | let paginationTag = [];
6 |
7 | if (props.pagination === undefined) {
8 | paginationTag = "-";
9 | } else {
10 | const currentPageNo = props.pagination.currentPageNo;
11 | const pageSize = props.pagination.pageSize;
12 | const totalRecordCount = props.pagination.totalRecordCount;
13 | const recordCountPerPage = props.pagination.recordCountPerPage;
14 |
15 | const totalPageCount = Math.ceil(totalRecordCount / recordCountPerPage);
16 | const currentFirstPage =
17 | Math.floor((currentPageNo - 1) / pageSize) * pageSize + 1;
18 | let currentLastPage = currentFirstPage + pageSize - 1;
19 | currentLastPage =
20 | currentLastPage > totalPageCount ? totalPageCount : currentLastPage;
21 |
22 | if (totalPageCount > pageSize) {
23 | // 첫 페이지 이동
24 | const firstPageTag = (
25 |
26 | {
28 | props.moveToPage(1);
29 | }}
30 | className="first"
31 | >
32 | 처음
33 |
34 |
35 | );
36 | paginationTag.push(firstPageTag);
37 |
38 | // 이전 페이지 이동
39 | const prevPageIndex = currentPageNo - 1 > 0 ? currentPageNo - 1 : 1;
40 | const previousPageTag = (
41 |
42 | {
44 | props.moveToPage(prevPageIndex);
45 | }}
46 | className="prev"
47 | >
48 | 이전
49 |
50 |
51 | );
52 | paginationTag.push(previousPageTag);
53 | }
54 |
55 | for (let i = currentFirstPage; i <= currentLastPage; i++) {
56 | if (i === currentPageNo) {
57 | // 현재 페이지
58 | const currentPage = (
59 |
60 | {i}
61 |
62 | );
63 | paginationTag.push(currentPage);
64 | } else {
65 | // 다른 페이지
66 | const otherPage = (
67 |
68 | {
70 | props.moveToPage(i);
71 | }}
72 | >
73 | {i}
74 |
75 |
76 | );
77 | paginationTag.push(otherPage);
78 | }
79 | }
80 | if (totalPageCount > pageSize) {
81 | // 다음 페이지 이동
82 | const nextPageIndex =
83 | currentLastPage + 1 < totalPageCount
84 | ? currentLastPage + 1
85 | : totalPageCount;
86 | const nextPageTag = (
87 |
88 | {
90 | props.moveToPage(nextPageIndex);
91 | }}
92 | className="next"
93 | >
94 | 다음
95 |
96 |
97 | );
98 | paginationTag.push(nextPageTag);
99 |
100 | // 마지막 페이지 이동
101 | const lastPageTag = (
102 |
103 | {
105 | props.moveToPage(totalPageCount);
106 | }}
107 | className="last"
108 | >
109 |
110 | );
111 | paginationTag.push(lastPageTag);
112 | }
113 | }
114 | console.log("paginationTag", paginationTag);
115 | console.groupEnd("EgovPaging");
116 |
117 | return (
118 |
121 | );
122 | }
123 |
124 | export default EgovPaging;
125 |
--------------------------------------------------------------------------------
/src/components/EgovRadioButton.jsx:
--------------------------------------------------------------------------------
1 | function EgovRadioButton({ name, label, value, checkedValue, setter }) {
2 | const checked = value === checkedValue;
3 | const toggledClassName = checked ? "f_rdo on" : "f_rdo";
4 | return (
5 |
6 | setter(value)}
13 | />
14 | {label}
15 |
16 | );
17 | }
18 |
19 | export default EgovRadioButton;
20 |
--------------------------------------------------------------------------------
/src/components/EgovRadioButtonGroup.jsx:
--------------------------------------------------------------------------------
1 | import EgovRadioButton from "@/components/EgovRadioButton";
2 |
3 | function EgovRadioButtonGroup({ name, radioGroup, setValue, setter }) {
4 | return (
5 | <>
6 | {radioGroup.map((radioOption, i) => {
7 | return (
8 |
16 | );
17 | })}
18 | >
19 | );
20 | }
21 |
22 | export default EgovRadioButtonGroup;
23 |
--------------------------------------------------------------------------------
/src/components/EgovSelect.jsx:
--------------------------------------------------------------------------------
1 | function EgovSelect({ id, name, title, options, setValue, setter }) {
2 | console.log("egovSelect", id, name, title, options, setValue, setter);
3 | return (
4 | {
10 | console.log("select Change!! : ", setValue);
11 | setter(setValue);
12 | }}
13 | >
14 | {options.map((option, i) => {
15 | return (
16 |
17 | {option.label}
18 |
19 | );
20 | })}
21 |
22 | );
23 | }
24 |
25 | export default EgovSelect;
26 |
--------------------------------------------------------------------------------
/src/components/EgovViewTemplate.jsx:
--------------------------------------------------------------------------------
1 | import { useEffect } from "react";
2 |
3 | function EgovViewTemplate(props) {
4 | console.group("EgovViewTemplate");
5 | console.log("[Start] EgovViewTemplate ------------------------------");
6 | console.log("EgovViewTemplate [props] : ", props);
7 |
8 | useEffect(() => {
9 | return () => {};
10 | }, []);
11 |
12 | console.log("------------------------------EgovViewTemplate [End]");
13 | console.groupEnd("EgovViewTemplate");
14 | return (
15 |
18 | );
19 | }
20 |
21 | export default EgovViewTemplate;
22 |
--------------------------------------------------------------------------------
/src/components/leftmenu/EgovLeftNavAbout.jsx:
--------------------------------------------------------------------------------
1 | import { NavLink } from "react-router-dom";
2 | import URL from "@/constants/url";
3 |
4 | function EgovLeftNavAbout() {
5 | return (
6 |
7 |
8 |
사이트 소개
9 |
10 |
11 | (isActive ? "cur" : "")}
14 | >
15 | 소개
16 |
17 |
18 |
19 | (isActive ? "cur" : "")}
22 | >
23 | 연혁
24 |
25 |
26 |
27 | (isActive ? "cur" : "")}
30 | >
31 | 조직소개
32 |
33 |
34 |
35 | (isActive ? "cur" : "")}
38 | >
39 | 찾아오시는 길
40 |
41 |
42 |
43 |
44 |
45 | );
46 | }
47 |
48 | export default EgovLeftNavAbout;
49 |
--------------------------------------------------------------------------------
/src/components/leftmenu/EgovLeftNavAdmin.jsx:
--------------------------------------------------------------------------------
1 | import { NavLink } from "react-router-dom";
2 | import URL from "@/constants/url";
3 |
4 | function EgovLeftNavAdmin() {
5 | return (
6 |
7 |
8 |
사이트관리
9 |
10 |
11 | (isActive ? "cur" : "")}
14 | >
15 | 일정관리
16 |
17 |
18 |
19 | (isActive ? "cur" : "")}
22 | >
23 | 게시판생성관리
24 |
25 |
26 |
27 | (isActive ? "cur" : "")}
30 | >
31 | 게시판사용관리
32 |
33 |
34 |
35 | (isActive ? "cur" : "")}
38 | >
39 | 공지사항관리
40 |
41 |
42 |
43 | (isActive ? "cur" : "")}
46 | >
47 | 사이트갤러리관리
48 |
49 |
50 |
51 | (isActive ? "cur" : "")}
54 | >
55 | 사이트관리자 암호변경
56 |
57 |
58 |
59 | (isActive ? "cur" : "")}
62 | >
63 | 회원관리
64 |
65 |
66 |
67 |
68 |
69 | );
70 | }
71 |
72 | export default EgovLeftNavAdmin;
73 |
--------------------------------------------------------------------------------
/src/components/leftmenu/EgovLeftNavInform.jsx:
--------------------------------------------------------------------------------
1 | import { NavLink } from "react-router-dom";
2 | import URL from "@/constants/url";
3 |
4 | function EgovLeftNavInform() {
5 | console.groupCollapsed("EgovLeftNavInform");
6 | console.log("[Start] EgovLeftNavInform ------------------------------");
7 | console.log("------------------------------EgovLeftNavInform [End]");
8 | console.groupEnd("EgovLeftNavInform");
9 | return (
10 |
11 |
12 |
알림마당
13 |
14 |
15 | (isActive ? "cur" : "")}
18 | >
19 | 오늘의행사
20 |
21 |
22 |
23 | (isActive ? "cur" : "")}
26 | >
27 | 금주의행사
28 |
29 |
30 |
31 | (isActive ? "cur" : "")}
34 | >
35 | 공지사항
36 |
37 |
38 |
39 | (isActive ? "cur" : "")}
42 | >
43 | 사이트갤러리
44 |
45 |
46 |
47 |
48 |
49 | );
50 | }
51 |
52 | export default EgovLeftNavInform;
53 |
--------------------------------------------------------------------------------
/src/components/leftmenu/EgovLeftNavIntro.jsx:
--------------------------------------------------------------------------------
1 | import { NavLink } from "react-router-dom";
2 | import URL from "@/constants/url";
3 |
4 | function EgovLeftNavIntro() {
5 | return (
6 |
7 |
8 |
정보마당
9 |
10 |
11 | (isActive ? "cur" : "")}
14 | >
15 | 주요사업 소개
16 |
17 |
18 |
19 | (isActive ? "cur" : "")}
22 | >
23 | 대표서비스 소개
24 |
25 |
26 |
27 |
28 |
29 | );
30 | }
31 |
32 | export default EgovLeftNavIntro;
33 |
--------------------------------------------------------------------------------
/src/components/leftmenu/EgovLeftNavSupport.jsx:
--------------------------------------------------------------------------------
1 | import { NavLink } from "react-router-dom";
2 | import URL from "@/constants/url";
3 |
4 | function EgovLeftNavSupport() {
5 | return (
6 |
7 |
8 |
고객지원
9 |
10 |
11 | (isActive ? "cur" : "")}
14 | >
15 | 자료실
16 |
17 |
18 |
19 | (isActive ? "cur" : "")}
22 | >
23 | 묻고답하기
24 |
25 |
26 |
27 | (isActive ? "cur" : "")}
30 | >
31 | 서비스신청
32 |
33 |
34 |
35 |
36 |
37 | );
38 | }
39 |
40 | export default EgovLeftNavSupport;
41 |
--------------------------------------------------------------------------------
/src/components/sns/SnsKakaoBt.jsx:
--------------------------------------------------------------------------------
1 | const SnsKakaoBt = () => {
2 | const KAKAO_CLIENT_ID = import.meta.env.VITE_APP_KAKAO_CLIENTID; // 발급받은 클라이언트 아이디
3 | const REDIRECT_URI = import.meta.env.VITE_APP_KAKAO_CALLBACKURL; // Callback URL
4 | const KAKAO_AUTH_URL = `https://kauth.kakao.com/oauth/authorize?response_type=code&client_id=${KAKAO_CLIENT_ID}&redirect_uri=${REDIRECT_URI}`;
5 |
6 | const KakaoLogin = () => {
7 | window.location.href = KAKAO_AUTH_URL;
8 | };
9 |
10 | return (
11 |
12 | 카카오 로그인
13 |
14 | );
15 | };
16 |
17 | export default SnsKakaoBt;
18 |
--------------------------------------------------------------------------------
/src/components/sns/SnsKakaoCallback.jsx:
--------------------------------------------------------------------------------
1 | import { useEffect } from "react";
2 | import * as EgovNet from "@/api/egovFetch";
3 | import CODE from "@/constants/code";
4 | import { setSessionItem } from "@/utils/storage";
5 |
6 | const SnsKakaoCallback = () => {
7 | //백엔드 호출
8 | const callBackEnd = () => {
9 | // 백엔드로 코드값을 넘겨주는 로직
10 | let code = new URL(window.location.href).searchParams.get("code");
11 | let state = new URL(window.location.href).searchParams.get("state");
12 | console.log("code, state=====>", code, state);
13 | // 요청이 성공하면
14 | if (code) {
15 | const kakaoLoginUrl = `/login/kakao/callback?code=${code}&state=${state}`;
16 | const requestOptions = {
17 | method: "GET",
18 | headers: {
19 | "Content-type": "application/json",
20 | },
21 | };
22 | EgovNet.requestFetch(kakaoLoginUrl, requestOptions, (resp) => {
23 | let resultVO = resp.resultVO;
24 | let jToken = resp?.jToken || null;
25 | if (Number(resp.resultCode) === Number(CODE.RCV_SUCCESS)) {
26 | setSessionItem("jToken", jToken);
27 | //setLoginVO(resultVO);
28 | setSessionItem("loginUser", resultVO);
29 | //props.onChangeLogin(resultVO);
30 | // PC와 Mobile 열린메뉴 닫기
31 | document.querySelector(".all_menu.WEB").classList.add("closed");
32 | document.querySelector(".btnAllMenu").classList.remove("active");
33 | document.querySelector(".btnAllMenu").title = "전체메뉴 닫힘";
34 | document.querySelector(".all_menu.Mobile").classList.add("closed");
35 | alert("Sns 간편 로그인 중..."); //공통 alert 사용대신해서
36 | } else {
37 | //React.StrictMode 에서 fetch가 자동으로 2번 실행할 때 아래 메인화면으로 이동된다.
38 | window.location.replace("/");
39 | }
40 | });
41 | }
42 | };
43 | useEffect(callBackEnd, []);
44 |
45 | return (
46 | <>
47 | {/* 로그인중이라는 것을 표시할 수 있는 로딩중 화면 */}
48 | 로그인 중...
49 | >
50 | );
51 | };
52 |
53 | export default SnsKakaoCallback;
54 |
--------------------------------------------------------------------------------
/src/components/sns/SnsNaverBt.jsx:
--------------------------------------------------------------------------------
1 | const SnsNaverBt = () => {
2 | const NAVER_CLIENT_ID = import.meta.env.VITE_APP_NAVER_CLIENTID; // 발급받은 클라이언트 아이디
3 | const REDIRECT_URI = import.meta.env.VITE_APP_NAVER_CALLBACKURL; // Callback URL
4 | const STATE = import.meta.env.VITE_APP_STATE; //다른 서버와 통신 시 암호화문자
5 | const NAVER_AUTH_URL = `https://nid.naver.com/oauth2.0/authorize?response_type=code&client_id=${NAVER_CLIENT_ID}&state=${STATE}&redirect_uri=${REDIRECT_URI}`;
6 |
7 | const NaverLogin = () => {
8 | window.location.href = NAVER_AUTH_URL;
9 | };
10 |
11 | return (
12 |
13 | 네이버 로그인
14 |
15 | );
16 | };
17 |
18 | export default SnsNaverBt;
19 |
--------------------------------------------------------------------------------
/src/components/sns/SnsNaverCallback.jsx:
--------------------------------------------------------------------------------
1 | import { useEffect } from "react";
2 | import * as EgovNet from "@/api/egovFetch";
3 | import CODE from "@/constants/code";
4 | import { setSessionItem } from "@/utils/storage";
5 |
6 | const SnsNaverCallback = () => {
7 | //백엔드 호출
8 | const callBackEnd = () => {
9 | // 백엔드로 코드값을 넘겨주는 로직
10 | let code = new URL(window.location.href).searchParams.get("code");
11 | let state = new URL(window.location.href).searchParams.get("state");
12 | console.log("code, state=====>", code, state);
13 | // 요청이 성공하면
14 | if (code) {
15 | const naverLoginUrl = `/login/naver/callback?code=${code}&state=${state}`;
16 | const requestOptions = {
17 | method: "GET",
18 | headers: {
19 | "Content-type": "application/json",
20 | },
21 | };
22 | EgovNet.requestFetch(naverLoginUrl, requestOptions, (resp) => {
23 | let resultVO = resp.resultVO;
24 | let jToken = resp?.jToken || null;
25 | if (Number(resp.resultCode) === Number(CODE.RCV_SUCCESS)) {
26 | setSessionItem("jToken", jToken);
27 | //setLoginVO(resultVO);
28 | setSessionItem("loginUser", resultVO);
29 | //props.onChangeLogin(resultVO);
30 | // PC와 Mobile 열린메뉴 닫기
31 | document.querySelector(".all_menu.WEB").classList.add("closed");
32 | document.querySelector(".btnAllMenu").classList.remove("active");
33 | document.querySelector(".btnAllMenu").title = "전체메뉴 닫힘";
34 | document.querySelector(".all_menu.Mobile").classList.add("closed");
35 | alert("Sns 간편 로그인 중..."); //공통 alert 사용대신해서
36 | } else {
37 | //React.StrictMode 에서 fetch가 자동으로 2번 실행할 때 아래 메인화면으로 이동된다.
38 | window.location.replace("/");
39 | }
40 | });
41 | }
42 | };
43 | useEffect(callBackEnd, []);
44 |
45 | return (
46 | <>
47 | {/* 로그인중이라는 것을 표시할 수 있는 로딩중 화면 */}
48 | 로그인 중...
49 | >
50 | );
51 | };
52 |
53 | export default SnsNaverCallback;
54 |
--------------------------------------------------------------------------------
/src/config.js:
--------------------------------------------------------------------------------
1 | // Configuration for different environments
2 | export const SERVER_URL = process.env.NODE_ENV === 'test' ? 'http://localhost:8080' : 'http://localhost:8080';
3 |
4 | export const DEFAULT_BBS_ID = "BBSMSTR_AAAAAAAAAAAA"; // default = 공지사항 게시판 아이디
5 | export const NOTICE_BBS_ID = "BBSMSTR_AAAAAAAAAAAA"; // 공지사항 게시판 아이디
6 | export const GALLERY_BBS_ID = "BBSMSTR_BBBBBBBBBBBB"; // 갤러리 게시판 아이디
7 |
--------------------------------------------------------------------------------
/src/config/index.js:
--------------------------------------------------------------------------------
1 | export const SERVER_URL = "http://" + import.meta.env.VITE_APP_EGOV_CONTEXT_URL; // REST API 서버 Domain URL
2 | export const DEFAULT_BBS_ID = "BBSMSTR_AAAAAAAAAAAA"; // default = 공지사항 게시판 아이디
3 | export const NOTICE_BBS_ID = "BBSMSTR_AAAAAAAAAAAA"; // 공지사항 게시판 아이디
4 | export const GALLERY_BBS_ID = "BBSMSTR_BBBBBBBBBBBB"; // 갤러리 게시판 아이디
5 |
--------------------------------------------------------------------------------
/src/config/index.jsx:
--------------------------------------------------------------------------------
1 | export const SERVER_URL = "http://"+import.meta.env.VITE_EGOV_CONTEXT_URL; // REST API 서버 Domain URL
2 | export const DEFAULT_BBS_ID = "BBSMSTR_AAAAAAAAAAAA"; // default = 공지사항 게시판 아이디
3 | export const NOTICE_BBS_ID = "BBSMSTR_AAAAAAAAAAAA"; // 공지사항 게시판 아이디
4 | export const GALLERY_BBS_ID = "BBSMSTR_BBBBBBBBBBBB"; // 갤러리 게시판 아이디
5 |
--------------------------------------------------------------------------------
/src/constants/code.js:
--------------------------------------------------------------------------------
1 | const CODE = {
2 | RCV_SUCCESS : "200", // 성공
3 |
4 | RCV_ERROR_AUTH : "403", // 인증 오류
5 | RCV_ERROR_DELETE : "700", // 삭제 오류
6 | RCV_ERROR_SAVE : "800", // 저장 오류
7 | RCV_ERROR_VALIDATION : "900", // 입력 오류
8 |
9 | MODE_CREATE : "create", // 등록 모드
10 | MODE_MODIFY : "modify", // 수정 모드
11 | MODE_READ : "read", // 읽기 모드
12 | MODE_REPLY : "reply", // 답글 모드
13 |
14 | DATE_YEAR : "year",
15 | DATE_MONTH : "month",
16 | DATE_DATE : "date",
17 | DATE_WEEK : "week",
18 | DATE_DAY : "day",
19 | }
20 |
21 | export default CODE;
--------------------------------------------------------------------------------
/src/constants/code.jsx:
--------------------------------------------------------------------------------
1 | const CODE = {
2 | RCV_SUCCESS : "200", // 성공
3 |
4 | RCV_ERROR_AUTH : "403", // 인증 오류
5 | RCV_ERROR_DELETE : "700", // 삭제 오류
6 | RCV_ERROR_SAVE : "800", // 저장 오류
7 | RCV_ERROR_VALIDATION : "900", // 입력 오류
8 |
9 | MODE_CREATE : "create", // 등록 모드
10 | MODE_MODIFY : "modify", // 수정 모드
11 | MODE_READ : "read", // 읽기 모드
12 | MODE_REPLY : "reply", // 답글 모드
13 |
14 | DATE_YEAR : "year",
15 | DATE_MONTH : "month",
16 | DATE_DATE : "date",
17 | DATE_WEEK : "week",
18 | DATE_DAY : "day",
19 | }
20 |
21 | // eslint-disable-next-line react-refresh/only-export-components
22 | export default CODE;
--------------------------------------------------------------------------------
/src/constants/url.js:
--------------------------------------------------------------------------------
1 | const URL = {
2 | //COMMON
3 | MAIN: "/", //메인페이지
4 |
5 | LOGIN: "/login", //로그인
6 | SNS_NAVER_CB: "/login/naver/callback", //Sns Naver Callback
7 | SNS_KAKAO_CB: "/login/kakao/callback", //Sns Kakao Callback
8 | ERROR: "/error", //로그인
9 |
10 | //ABOUT
11 | ABOUT: "/about", //사이트소개
12 | ABOUT_SITE: "/about/site", // 사이트소개/소개
13 | ABOUT_HISTORY: "/about/history", // 사이트소개/연혁
14 | ABOUT_ORGANIZATION: "/about/organization", // 사이트소개/조직소개
15 | ABOUT_LOCATION: "/about/location", // 사이트소개/찾아오시는길
16 |
17 | //INTRO
18 | INTRO: "/intro", //정보마당
19 | INTRO_WORKS: "/intro/works", // 정보마당/주요사업소개
20 | INTRO_SERVICE: "/intro/service", // 정보마당/주요서비스소개
21 |
22 | //SUPPORT
23 | SUPPORT: "/support", // 고객지원
24 | SUPPORT_DOWNLOAD: "/support/download", // 고객지원/자료실
25 | SUPPORT_DOWNLOAD_DETAIL: "/support/download/detail", // 고객지원/자료실/상세
26 | SUPPORT_DOWNLOAD_CREATE: "/support/download/create", // 고객지원/자료실/등록
27 | SUPPORT_QNA: "/support/qna", // 고객지원/묻고답하기
28 | SUPPORT_QNA_DETAIL: "/support/qna/detail", // 고객지원/묻고답하기/상세
29 | SUPPORT_APPLY: "/support/apply", // 고객지원/서비스신청
30 |
31 | //INFORM
32 | INFORM: "/inform", // 알림마당
33 | INFORM_DAILY: "/inform/daily", // 알림마당/오늘의행사
34 | INFORM_DAILY_DETAIL: "/inform/daily/detail", // 알림마당/오늘의행사상세
35 | INFORM_WEEKLY: "/inform/weekly", // 알림마당/금주의행사
36 | INFORM_WEEKLY_DETAIL: "/inform/weekly/detail", // 알림마당/금주의행사상세
37 | INFORM_NOTICE: "/inform/notice", // 알림마당/공지사항
38 | INFORM_NOTICE_DETAIL: "/inform/notice/detail", // 알림마당/공지사항상세
39 | INFORM_NOTICE_CREATE: "/inform/notice/create", // 알림마당/공지사항등록
40 | INFORM_NOTICE_MODIFY: "/inform/notice/modify", // 알림마당/공지사항수정
41 | INFORM_NOTICE_REPLY: "/inform/notice/reply", // 알림마당/공지사항답글
42 | INFORM_GALLERY: "/inform/gallery", // 알림마당/사이트갤러리
43 | INFORM_GALLERY_DETAIL: "/inform/gallery/detail", // 알림마당/사이트갤러리상세
44 | INFORM_GALLERY_CREATE: "/inform/gallery/create", // 알림마당/사이트갤러리등록
45 | INFORM_GALLERY_MODIFY: "/inform/gallery/modify", // 알림마당/사이트갤러리수정
46 | INFORM_GALLERY_REPLY: "/inform/gallery/reply", // 알림마당/사이트갤러리답글
47 |
48 | //ADMIN
49 | ADMIN: "/admin", // 사이트관리
50 | ADMIN_SCHEDULE: "/admin/schedule", // 사이트관리/일정관리
51 | ADMIN_SCHEDULE_DETAIL: "/admin/schedule/detail", // 사이트관리/일정관리상세
52 | ADMIN_SCHEDULE_CREATE: "/admin/schedule/create", // 사이트관리/일정관리생성
53 | ADMIN_SCHEDULE_MODIFY: "/admin/schedule/modify", // 사이트관리/일정관리수정
54 |
55 | ADMIN_BOARD: "/admin/board", // 사이트관리/게시판생성관리 목록
56 | ADMIN_BOARD_DETAIL: "/admin/board/detail", // 사이트관리/게시판생성관리 상세
57 | ADMIN_BOARD_CREATE: "/admin/board/create", // 사이트관리/게시판생성관리 등록
58 | ADMIN_BOARD_MODIFY: "/admin/board/modify", // 사이트관리/게시판생성관리 상세/수정
59 |
60 | ADMIN_USAGE: "/admin/usage", // 사이트관리/게시판사용관리 목록
61 | ADMIN_USAGE_DETAIL: "/admin/usage/detail", // 사이트관리/게시판사용관리 상세
62 | ADMIN_USAGE_CREATE: "/admin/usage/create", // 사이트관리/게시판사용관리 등록
63 | ADMIN_USAGE_MODIFY: "/admin/usage/modify", // 사이트관리/게시판사용관리 상세/수정
64 |
65 | ADMIN_NOTICE: "/admin/notice", // 사이트관리/공지사항관리 목록
66 | ADMIN_NOTICE_DETAIL: "/admin/notice/detail", // 사이트관리/공지사항관리 상세
67 | ADMIN_NOTICE_CREATE: "/admin/notice/create", // 사이트관리/공지사항관리 등록
68 | ADMIN_NOTICE_MODIFY: "/admin/notice/modify", // 사이트관리/공지사항관리 수정
69 | ADMIN_NOTICE_REPLY: "/admin/notice/reply", // 사이트관리/공지사항관리 답글 등록
70 |
71 | ADMIN_GALLERY: "/admin/gallery", // 사이트관리/사이트갤러리관리
72 | ADMIN_GALLERY_DETAIL: "/admin/gallery/detail", // 사이트관리/사이트갤러리관리 상세
73 | ADMIN_GALLERY_CREATE: "/admin/gallery/create", // 사이트관리/사이트갤러리관리 등록
74 | ADMIN_GALLERY_MODIFY: "/admin/gallery/modify", // 사이트관리/사이트갤러리관리 수정
75 | ADMIN_GALLERY_REPLY: "/admin/gallery/reply", // 사이트관리/사이트갤러리관리 답글 등록
76 |
77 | ADMIN_MANAGER: "/admin/manager", // 사이트관리/사이트관리자 암호변경 기능
78 | ADMIN_MEMBERS: "/admin/members", // 사이트관리/회원관리 목록기능
79 | ADMIN_MEMBERS_DETAIL: "/admin/members/detail", // 사이트관리/회원관리 상세
80 | ADMIN_MEMBERS_CREATE: "/admin/members/create", // 사이트관리/회원관리 등록
81 | ADMIN_MEMBERS_MODIFY: "/admin/members/modify", // 사이트관리/회원관리 상세/수정
82 |
83 | //MYPAGE
84 | MYPAGE_MODIFY: "/mypage/modify", // 고객지원/마이페이지/회원 수정
85 | MYPAGE_CREATE: "/mypage/create", // 고객지원/마이페이지/회원 등록
86 | };
87 |
88 | // eslint-disable-next-line react-refresh/only-export-components
89 | export default URL;
90 |
--------------------------------------------------------------------------------
/src/constants/url.jsx:
--------------------------------------------------------------------------------
1 | const URL = {
2 | //COMMON
3 | MAIN: "/egovframe-template-simple-react", //메인페이지
4 |
5 | LOGIN: "/egovframe-template-simple-react/login", //로그인
6 | ERROR: "/egovframe-template-simple-react/error", //로그인
7 |
8 | //ABOUT
9 | ABOUT: "/egovframe-template-simple-react/about", //사이트소개
10 | ABOUT_SITE: "/egovframe-template-simple-react/about/site", // 사이트소개/소개
11 | ABOUT_HISTORY: "/egovframe-template-simple-react/about/history", // 사이트소개/연혁
12 | ABOUT_ORGANIZATION: "/egovframe-template-simple-react/about/organization", // 사이트소개/조직소개
13 | ABOUT_LOCATION: "/egovframe-template-simple-react/about/location", // 사이트소개/찾아오시는길
14 |
15 | //INTRO
16 | INTRO: "/egovframe-template-simple-react/intro", //정보마당
17 | INTRO_WORKS: "/egovframe-template-simple-react/intro/works", // 정보마당/주요사업소개
18 | INTRO_SERVICE: "/egovframe-template-simple-react/intro/service", // 정보마당/주요서비스소개
19 |
20 | //SUPPORT
21 | SUPPORT: "/egovframe-template-simple-react/support", // 고객지원
22 | SUPPORT_DOWNLOAD: "/egovframe-template-simple-react/support/download", // 고객지원/자료실
23 | SUPPORT_DOWNLOAD_DETAIL:
24 | "/egovframe-template-simple-react/support/download/detail", // 고객지원/자료실/상세
25 | SUPPORT_DOWNLOAD_CREATE:
26 | "/egovframe-template-simple-react/support/download/create", // 고객지원/자료실/등록
27 | SUPPORT_QNA: "/egovframe-template-simple-react/support/qna", // 고객지원/묻고답하기
28 | SUPPORT_QNA_DETAIL: "/egovframe-template-simple-react/support/qna/detail", // 고객지원/묻고답하기/상세
29 | SUPPORT_APPLY: "/egovframe-template-simple-react/support/apply", // 고객지원/서비스신청
30 |
31 | //INFORM
32 | INFORM: "/egovframe-template-simple-react/inform", // 알림마당
33 | INFORM_DAILY: "/egovframe-template-simple-react/inform/daily", // 알림마당/오늘의행사
34 | INFORM_DAILY_DETAIL: "/egovframe-template-simple-react/inform/daily/detail", // 알림마당/오늘의행사상세
35 | INFORM_WEEKLY: "/egovframe-template-simple-react/inform/weekly", // 알림마당/금주의행사
36 | INFORM_WEEKLY_DETAIL: "/egovframe-template-simple-react/inform/weekly/detail", // 알림마당/금주의행사상세
37 | INFORM_NOTICE: "/egovframe-template-simple-react/inform/notice", // 알림마당/공지사항
38 | INFORM_NOTICE_DETAIL: "/egovframe-template-simple-react/inform/notice/detail", // 알림마당/공지사항상세
39 | INFORM_NOTICE_CREATE: "/egovframe-template-simple-react/inform/notice/create", // 알림마당/공지사항등록
40 | INFORM_NOTICE_MODIFY: "/egovframe-template-simple-react/inform/notice/modify", // 알림마당/공지사항수정
41 | INFORM_NOTICE_REPLY: "/egovframe-template-simple-react/inform/notice/reply", // 알림마당/공지사항답글
42 | INFORM_GALLERY: "/egovframe-template-simple-react/inform/gallery", // 알림마당/사이트갤러리
43 | INFORM_GALLERY_DETAIL:
44 | "/egovframe-template-simple-react/inform/gallery/detail", // 알림마당/사이트갤러리상세
45 | INFORM_GALLERY_CREATE:
46 | "/egovframe-template-simple-react/inform/gallery/create", // 알림마당/사이트갤러리등록
47 | INFORM_GALLERY_MODIFY:
48 | "/egovframe-template-simple-react/inform/gallery/modify", // 알림마당/사이트갤러리수정
49 | INFORM_GALLERY_REPLY: "/egovframe-template-simple-react/inform/gallery/reply", // 알림마당/사이트갤러리답글
50 |
51 | //ADMIN
52 | ADMIN: "/egovframe-template-simple-react/admin", // 사이트관리
53 | ADMIN_SCHEDULE: "/egovframe-template-simple-react/admin/schedule", // 사이트관리/일정관리
54 | ADMIN_SCHEDULE_DETAIL:
55 | "/egovframe-template-simple-react/admin/schedule/detail", // 사이트관리/일정관리상세
56 | ADMIN_SCHEDULE_CREATE:
57 | "/egovframe-template-simple-react/admin/schedule/create", // 사이트관리/일정관리생성
58 | ADMIN_SCHEDULE_MODIFY:
59 | "/egovframe-template-simple-react/admin/schedule/modify", // 사이트관리/일정관리수정
60 |
61 | ADMIN_BOARD: "/egovframe-template-simple-react/admin/board", // 사이트관리/게시판생성관리 목록
62 | ADMIN_BOARD_DETAIL: "/egovframe-template-simple-react/admin/board/detail", // 사이트관리/게시판생성관리 상세
63 | ADMIN_BOARD_CREATE: "/egovframe-template-simple-react/admin/board/create", // 사이트관리/게시판생성관리 등록
64 | ADMIN_BOARD_MODIFY: "/egovframe-template-simple-react/admin/board/modify", // 사이트관리/게시판생성관리 상세/수정
65 |
66 | ADMIN_USAGE: "/egovframe-template-simple-react/admin/usage", // 사이트관리/게시판사용관리 목록
67 | ADMIN_USAGE_DETAIL: "/egovframe-template-simple-react/admin/usage/detail", // 사이트관리/게시판사용관리 상세
68 | ADMIN_USAGE_CREATE: "/egovframe-template-simple-react/admin/usage/create", // 사이트관리/게시판사용관리 등록
69 | ADMIN_USAGE_MODIFY: "/egovframe-template-simple-react/admin/usage/modify", // 사이트관리/게시판사용관리 상세/수정
70 |
71 | ADMIN_NOTICE: "/egovframe-template-simple-react/admin/notice/", // 사이트관리/공지사항관리 목록
72 | ADMIN_NOTICE_DETAIL: "/egovframe-template-simple-react/admin/notice/detail", // 사이트관리/공지사항관리 상세
73 | ADMIN_NOTICE_CREATE: "/egovframe-template-simple-react/admin/notice/create", // 사이트관리/공지사항관리 등록
74 | ADMIN_NOTICE_MODIFY: "/egovframe-template-simple-react/admin/notice/modify", // 사이트관리/공지사항관리 수정
75 | ADMIN_NOTICE_REPLY: "/egovframe-template-simple-react/admin/notice/reply", // 사이트관리/공지사항관리 답글 등록
76 |
77 | ADMIN_GALLERY: "/egovframe-template-simple-react/admin/gallery", // 사이트관리/사이트갤러리관리
78 | ADMIN_GALLERY_DETAIL: "/egovframe-template-simple-react/admin/gallery/detail", // 사이트관리/사이트갤러리관리 상세
79 | ADMIN_GALLERY_CREATE: "/egovframe-template-simple-react/admin/gallery/create", // 사이트관리/사이트갤러리관리 등록
80 | ADMIN_GALLERY_MODIFY: "/egovframe-template-simple-react/admin/gallery/modify", // 사이트관리/사이트갤러리관리 수정
81 | ADMIN_GALLERY_REPLY: "/egovframe-template-simple-react/admin/gallery/reply", // 사이트관리/사이트갤러리관리 답글 등록
82 |
83 | ADMIN_MANAGER: "/egovframe-template-simple-react/admin/manager/", // 사이트관리/사이트관리자 암호변경 기능
84 |
85 | ADMIN_MEMBERS: "/admin/members/", // 사이트관리/회원관리 목록기능
86 | ADMIN_MEMBERS_DETAIL: "/admin/members/detail", // 사이트관리/회원관리 상세
87 | ADMIN_MEMBERS_CREATE: "/admin/members/create", // 사이트관리/회원관리 등록
88 | ADMIN_MEMBERS_MODIFY: "/admin/members/modify", // 사이트관리/회원관리 상세/수정
89 |
90 | //MYPAGE
91 | MYPAGE_MODIFY: "/mypage/modify", // 고객지원/마이페이지/회원 수정
92 | MYPAGE_CREATE: "/mypage/create", // 고객지원/마이페이지/회원 등록
93 | };
94 |
95 | // eslint-disable-next-line react-refresh/only-export-components
96 | export default URL;
97 |
--------------------------------------------------------------------------------
/src/css/base.css:
--------------------------------------------------------------------------------
1 | @charset "utf-8";
2 |
3 | /* Web Font */
4 | @font-face {font-family: 'Noto Sans KR';font-style: normal;font-weight: 300;
5 | src: url(https://fonts.gstatic.com/ea/notosanskr/v2/NotoSansKR-Light.woff2) format('woff2'),
6 | url(https://fonts.gstatic.com/ea/notosanskr/v2/NotoSansKR-Light.woff) format('woff'),
7 | url(https://fonts.gstatic.com/ea/notosanskr/v2/NotoSansKR-Light.otf) format('opentype');}
8 |
9 | @font-face {font-family: 'Noto Sans KR';font-style: normal;font-weight: 400;src:
10 | url(https://fonts.gstatic.com/ea/notosanskr/v2/NotoSansKR-Regular.woff2) format('woff2'),
11 | url(https://fonts.gstatic.com/ea/notosanskr/v2/NotoSansKR-Regular.woff) format('woff'),
12 | url(https://fonts.gstatic.com/ea/notosanskr/v2/NotoSansKR-Regular.otf) format('opentype');}
13 |
14 | @font-face {font-family: 'Noto Sans KR';font-style: normal;font-weight: 500;
15 | src: url(https://fonts.gstatic.com/ea/notosanskr/v2/NotoSansKR-Medium.woff2) format('woff2'),
16 | url(https://fonts.gstatic.com/ea/notosanskr/v2/NotoSansKR-Medium.woff) format('woff'),
17 | url(https://fonts.gstatic.com/ea/notosanskr/v2/NotoSansKR-Medium.otf) format('opentype');}
18 |
19 | @font-face {font-family: 'Noto Sans KR';font-style: normal;font-weight: 700;
20 | src: url(https://fonts.gstatic.com/ea/notosanskr/v2/NotoSansKR-Bold.woff2) format('woff2'),
21 | url(https://fonts.gstatic.com/ea/notosanskr/v2/NotoSansKR-Bold.woff) format('woff'),
22 | url(https://fonts.gstatic.com/ea/notosanskr/v2/NotoSansKR-Bold.otf) format('opentype');}
23 |
24 | /* Reset style */
25 | * {word-break: keep-all; word-wrap: break-word; box-sizing: border-box; -webkit-box-sizing: border-box;}
26 | html, body, div, span, applet, object, iframe, h1, h2, h3, h4, h5, h6, p,
27 | blockquote, pre, a, abbr, acronym, address, big, cite, code, del, em, font, img, ins, q, s, small, strike, strong, sub, sup,
28 | dl, dt, dd, ol, ul, li, fieldset, form, label, legend, table, caption, thead, tbody, tfoot, tr, th, td, input {
29 | margin: 0; padding: 0;
30 | }
31 |
32 | blockquote, button, fieldset, iframe {border: 0;}
33 | cite, em, u, address, i {font-style: normal;}
34 | img {border: 0; vertical-align: top;}
35 | hr, legend {position: absolute; left: -9999px; top: -9999px;}
36 | caption {text-indent: -9999px; font-size: 0;}
37 | li {list-style: none;}
38 | table {width: 100%; table-layout: fixed; border-collapse: collapse;}
39 | a:link, a:visited, a:hover, a:active {text-decoration: none;}
40 |
41 | /* Blind 숨김처리 */
42 | .blind {position: absolute; left: -9999px; top: -9999px;}
43 | .skip {position: absolute; left: -9999px; top: -9999px;}
44 |
45 | body {font-family: 'Noto Sans KR', sans-serif; font-size: 16px;}
46 | button, textarea {font-family: 'Noto Sans KR', sans-serif;}
47 | button {cursor: pointer;}
48 |
49 |
50 | /* 정렬 */
51 | .al_c {text-align: center;}
52 | .al_r {text-align: right;}
53 |
54 |
55 | /* 가로길이 */
56 | .w_full {width: 100%;}
57 | .w_half {width: 50%;}
58 | .w_quarter {width: 25%;}
59 | .w_50 {width: 50px;}
60 | .w_70 {width: 70px;}
61 | .w_80 {width: 80px;}
62 | .w_100 {width: 100px;}
63 | .w_120 {width: 120px;}
64 | .w_130 {width: 130px;}
65 | .w_150 {width: 150px;}
66 | .w_200 {width: 200px;}
67 | .w_250 {width: 250px;}
68 | .w_300 {width: 300px;}
69 | .w_350 {width: 350px;}
70 | .w_400 {width: 400px;}
71 | .w_500 {width: 500px;}
72 |
73 | .h_30 {height: 30px;}
74 | .h_100 {height: 100px;}
75 |
76 |
77 | /* 여백 */
78 | .mt0 {margin-top: 0 !important;}
79 | .mt10 {margin-top: 10px !important;}
80 | .mt40 {margin-top: 40px !important;}
81 | .ml10 {margin-left: 10px !important;}
82 | .pb10 {padding-bottom: 10px !important;}
--------------------------------------------------------------------------------
/src/css/images/bg_btn_calendar.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/eGovFramework/egovframe-template-simple-react/e6e9ef0391cea902b99141c20fafbc08d121425c/src/css/images/bg_btn_calendar.png
--------------------------------------------------------------------------------
/src/css/images/bg_ds_t2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/eGovFramework/egovframe-template-simple-react/e6e9ef0391cea902b99141c20fafbc08d121425c/src/css/images/bg_ds_t2.png
--------------------------------------------------------------------------------
/src/css/images/bg_form_chk.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/eGovFramework/egovframe-template-simple-react/e6e9ef0391cea902b99141c20fafbc08d121425c/src/css/images/bg_form_chk.png
--------------------------------------------------------------------------------
/src/css/images/bg_form_chk_on.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/eGovFramework/egovframe-template-simple-react/e6e9ef0391cea902b99141c20fafbc08d121425c/src/css/images/bg_form_chk_on.png
--------------------------------------------------------------------------------
/src/css/images/bg_form_rdo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/eGovFramework/egovframe-template-simple-react/e6e9ef0391cea902b99141c20fafbc08d121425c/src/css/images/bg_form_rdo.png
--------------------------------------------------------------------------------
/src/css/images/bg_form_rdo_on.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/eGovFramework/egovframe-template-simple-react/e6e9ef0391cea902b99141c20fafbc08d121425c/src/css/images/bg_form_rdo_on.png
--------------------------------------------------------------------------------
/src/css/images/ico_address.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/eGovFramework/egovframe-template-simple-react/e6e9ef0391cea902b99141c20fafbc08d121425c/src/css/images/ico_address.png
--------------------------------------------------------------------------------
/src/css/images/ico_allmenu.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/eGovFramework/egovframe-template-simple-react/e6e9ef0391cea902b99141c20fafbc08d121425c/src/css/images/ico_allmenu.png
--------------------------------------------------------------------------------
/src/css/images/ico_allmenu_close.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/eGovFramework/egovframe-template-simple-react/e6e9ef0391cea902b99141c20fafbc08d121425c/src/css/images/ico_allmenu_close.png
--------------------------------------------------------------------------------
/src/css/images/ico_arrow_black_36x20.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/eGovFramework/egovframe-template-simple-react/e6e9ef0391cea902b99141c20fafbc08d121425c/src/css/images/ico_arrow_black_36x20.png
--------------------------------------------------------------------------------
/src/css/images/ico_arrow_gray_15x9.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/eGovFramework/egovframe-template-simple-react/e6e9ef0391cea902b99141c20fafbc08d121425c/src/css/images/ico_arrow_gray_15x9.png
--------------------------------------------------------------------------------
/src/css/images/ico_arrow_r_gray_4x7.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/eGovFramework/egovframe-template-simple-react/e6e9ef0391cea902b99141c20fafbc08d121425c/src/css/images/ico_arrow_r_gray_4x7.png
--------------------------------------------------------------------------------
/src/css/images/ico_arrow_r_gray_9x15.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/eGovFramework/egovframe-template-simple-react/e6e9ef0391cea902b99141c20fafbc08d121425c/src/css/images/ico_arrow_r_gray_9x15.png
--------------------------------------------------------------------------------
/src/css/images/ico_arrow_up_gray_16x9.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/eGovFramework/egovframe-template-simple-react/e6e9ef0391cea902b99141c20fafbc08d121425c/src/css/images/ico_arrow_up_gray_16x9.png
--------------------------------------------------------------------------------
/src/css/images/ico_bn01.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/eGovFramework/egovframe-template-simple-react/e6e9ef0391cea902b99141c20fafbc08d121425c/src/css/images/ico_bn01.png
--------------------------------------------------------------------------------
/src/css/images/ico_bn02.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/eGovFramework/egovframe-template-simple-react/e6e9ef0391cea902b99141c20fafbc08d121425c/src/css/images/ico_bn02.png
--------------------------------------------------------------------------------
/src/css/images/ico_bn03.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/eGovFramework/egovframe-template-simple-react/e6e9ef0391cea902b99141c20fafbc08d121425c/src/css/images/ico_bn03.png
--------------------------------------------------------------------------------
/src/css/images/ico_bn04.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/eGovFramework/egovframe-template-simple-react/e6e9ef0391cea902b99141c20fafbc08d121425c/src/css/images/ico_bn04.png
--------------------------------------------------------------------------------
/src/css/images/ico_call.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/eGovFramework/egovframe-template-simple-react/e6e9ef0391cea902b99141c20fafbc08d121425c/src/css/images/ico_call.png
--------------------------------------------------------------------------------
/src/css/images/ico_close_black44.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/eGovFramework/egovframe-template-simple-react/e6e9ef0391cea902b99141c20fafbc08d121425c/src/css/images/ico_close_black44.png
--------------------------------------------------------------------------------
/src/css/images/ico_delete.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/eGovFramework/egovframe-template-simple-react/e6e9ef0391cea902b99141c20fafbc08d121425c/src/css/images/ico_delete.png
--------------------------------------------------------------------------------
/src/css/images/ico_down.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/eGovFramework/egovframe-template-simple-react/e6e9ef0391cea902b99141c20fafbc08d121425c/src/css/images/ico_down.png
--------------------------------------------------------------------------------
/src/css/images/ico_error.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/eGovFramework/egovframe-template-simple-react/e6e9ef0391cea902b99141c20fafbc08d121425c/src/css/images/ico_error.png
--------------------------------------------------------------------------------
/src/css/images/ico_file.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/eGovFramework/egovframe-template-simple-react/e6e9ef0391cea902b99141c20fafbc08d121425c/src/css/images/ico_file.png
--------------------------------------------------------------------------------
/src/css/images/ico_home.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/eGovFramework/egovframe-template-simple-react/e6e9ef0391cea902b99141c20fafbc08d121425c/src/css/images/ico_home.png
--------------------------------------------------------------------------------
/src/css/images/ico_mail.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/eGovFramework/egovframe-template-simple-react/e6e9ef0391cea902b99141c20fafbc08d121425c/src/css/images/ico_mail.png
--------------------------------------------------------------------------------
/src/css/images/ico_more.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/eGovFramework/egovframe-template-simple-react/e6e9ef0391cea902b99141c20fafbc08d121425c/src/css/images/ico_more.png
--------------------------------------------------------------------------------
/src/css/images/ico_person.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/eGovFramework/egovframe-template-simple-react/e6e9ef0391cea902b99141c20fafbc08d121425c/src/css/images/ico_person.png
--------------------------------------------------------------------------------
/src/css/images/ico_plus.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/eGovFramework/egovframe-template-simple-react/e6e9ef0391cea902b99141c20fafbc08d121425c/src/css/images/ico_plus.png
--------------------------------------------------------------------------------
/src/css/images/ico_prev.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/eGovFramework/egovframe-template-simple-react/e6e9ef0391cea902b99141c20fafbc08d121425c/src/css/images/ico_prev.png
--------------------------------------------------------------------------------
/src/css/images/ico_question.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/eGovFramework/egovframe-template-simple-react/e6e9ef0391cea902b99141c20fafbc08d121425c/src/css/images/ico_question.png
--------------------------------------------------------------------------------
/src/css/images/ico_reply.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/eGovFramework/egovframe-template-simple-react/e6e9ef0391cea902b99141c20fafbc08d121425c/src/css/images/ico_reply.png
--------------------------------------------------------------------------------
/src/css/images/ico_req.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/eGovFramework/egovframe-template-simple-react/e6e9ef0391cea902b99141c20fafbc08d121425c/src/css/images/ico_req.png
--------------------------------------------------------------------------------
/src/css/images/ico_search_b.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/eGovFramework/egovframe-template-simple-react/e6e9ef0391cea902b99141c20fafbc08d121425c/src/css/images/ico_search_b.png
--------------------------------------------------------------------------------
/src/css/images/ico_service_intro1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/eGovFramework/egovframe-template-simple-react/e6e9ef0391cea902b99141c20fafbc08d121425c/src/css/images/ico_service_intro1.png
--------------------------------------------------------------------------------
/src/css/images/ico_service_intro2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/eGovFramework/egovframe-template-simple-react/e6e9ef0391cea902b99141c20fafbc08d121425c/src/css/images/ico_service_intro2.png
--------------------------------------------------------------------------------
/src/css/images/ico_subway.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/eGovFramework/egovframe-template-simple-react/e6e9ef0391cea902b99141c20fafbc08d121425c/src/css/images/ico_subway.png
--------------------------------------------------------------------------------
/src/css/images/ico_v.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/eGovFramework/egovframe-template-simple-react/e6e9ef0391cea902b99141c20fafbc08d121425c/src/css/images/ico_v.png
--------------------------------------------------------------------------------
/src/css/images/icon_google.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/eGovFramework/egovframe-template-simple-react/e6e9ef0391cea902b99141c20fafbc08d121425c/src/css/images/icon_google.png
--------------------------------------------------------------------------------
/src/css/images/icon_kakao.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/eGovFramework/egovframe-template-simple-react/e6e9ef0391cea902b99141c20fafbc08d121425c/src/css/images/icon_kakao.png
--------------------------------------------------------------------------------
/src/css/images/icon_naver.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/eGovFramework/egovframe-template-simple-react/e6e9ef0391cea902b99141c20fafbc08d121425c/src/css/images/icon_naver.png
--------------------------------------------------------------------------------
/src/css/images/logo.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/eGovFramework/egovframe-template-simple-react/e6e9ef0391cea902b99141c20fafbc08d121425c/src/css/images/logo.jpg
--------------------------------------------------------------------------------
/src/index.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import { BrowserRouter } from 'react-router-dom';
3 | import App from './App';
4 | import reportWebVitals from './reportWebVitals';
5 | import { createRoot } from 'react-dom/client';
6 |
7 | const root = createRoot(document.getElementById("root"));
8 | root.render(
9 |
10 |
11 |
12 | );
13 |
14 | // If you want to start measuring performance in your app, pass a function
15 | // to log results (for example: reportWebVitals(console.log))
16 | // or send to an analytics endpoint. Learn more: https://bit.ly/CRA-vitals
17 | reportWebVitals();
18 |
--------------------------------------------------------------------------------
/src/js/ui.js:
--------------------------------------------------------------------------------
1 | let init = false;
2 |
3 | export default function initPage() {
4 | const sessionUser = sessionStorage.getItem("loginUser");
5 | const sessionUserId = JSON.parse(sessionUser)?.id;
6 |
7 | if (sessionUserId === "admin") {
8 | // Mobile 서브메뉴 항목 클릭시 메뉴 닫기
9 | document.querySelectorAll(".all_menu.Mobile .submenu a").forEach((el) => {
10 | el.removeEventListener("click", handleSubmenuClick);
11 | el.addEventListener("click", handleSubmenuClick);
12 | });
13 |
14 | // 모바일 관리자 하위 메뉴 열고 닫기
15 | const nodes = document.querySelectorAll(".all_menu.Mobile h3 a");
16 | const last_submenu = nodes[nodes.length - 1];
17 | last_submenu.removeEventListener("click", handleLastSubmenuClick);
18 | last_submenu.addEventListener("click", handleLastSubmenuClick);
19 | }
20 |
21 | if (init) return;
22 | init = true;
23 |
24 | /* 전체메뉴 */
25 | // 웹
26 | const webMenuButton = document.querySelector(".btnAllMenu");
27 | if (webMenuButton) {
28 | webMenuButton.addEventListener("click", handleWebMenuToggle);
29 | }
30 |
31 | // 모바일 전체메뉴 열기
32 | const mobileMenuButton = document.querySelector(".btnAllMenuM");
33 | if (mobileMenuButton) {
34 | mobileMenuButton.addEventListener("click", handleMobileMenuOpen);
35 | }
36 |
37 | // 닫기
38 | const mobileUserInfoClose = document.querySelector(".user_info_m .close");
39 | if (mobileUserInfoClose) {
40 | mobileUserInfoClose.addEventListener("click", handleMobileMenuClose);
41 | }
42 |
43 | // PC 메뉴 항목 클릭시 메뉴 닫기
44 | const webAllMenu = document.querySelector(".all_menu.WEB");
45 | if (webAllMenu) {
46 | webAllMenu.addEventListener("click", handleWebMenuClose);
47 | }
48 |
49 | // 회원가입, 마이페이지 항목 클릭시 메뉴 닫기
50 | const webUserInfo = document.querySelector(".user_info");
51 | if (webUserInfo) {
52 | webUserInfo.addEventListener("click", handleWebMenuClose);
53 | }
54 |
55 | // 회원가입, 마이페이지 항목 클릭시 모바일 전체메뉴 열기
56 | const mobileUserInfo = document.querySelector(".user_info_m");
57 | if (mobileUserInfo) {
58 | mobileUserInfo.addEventListener("click", handleMobileMenuClose);
59 | }
60 |
61 | // Mobile 서브메뉴 항목 클릭시 메뉴 닫기
62 | document.querySelectorAll(".all_menu.Mobile .submenu a").forEach((el) => {
63 | el.removeEventListener("click", handleSubmenuClick);
64 | el.addEventListener("click", handleSubmenuClick);
65 | });
66 |
67 | // 모바일 하위 메뉴 열고 닫기
68 | document.querySelectorAll(".all_menu.Mobile h3 a").forEach((el) => {
69 | el.removeEventListener("click", handleMobileSubmenuToggle);
70 | el.addEventListener("click", handleMobileSubmenuToggle);
71 | });
72 |
73 | document.addEventListener("click", handleGlobalClick);
74 |
75 | // 홈페이지 템플릿 소개팝업
76 | const template = {
77 | init: function () {
78 | this.$tg = document.querySelector(".TEMPLATE_INTRO");
79 | this.$btn = document.querySelector(".lnk_go_template");
80 | this.$btnClose = this.$tg.querySelector(".pop_header .close");
81 | this.addEvent();
82 | },
83 | addEvent: function () {
84 | this.$btn.addEventListener("click", this.handleOpenPopup.bind(this));
85 | this.$btnClose.addEventListener(
86 | "click",
87 | this.handleClosePopup.bind(this)
88 | );
89 | },
90 | handleOpenPopup: function (e) {
91 | e.preventDefault();
92 | this.$tg.style.display = "block";
93 | },
94 | handleClosePopup: function (e) {
95 | e.preventDefault();
96 | this.$tg.style.display = "none";
97 | },
98 | };
99 | document.querySelector(".lnk_go_template") && template.init();
100 | }
101 |
102 | // Event Handlers
103 | function handleSubmenuClick() {
104 | document.querySelector(".all_menu.Mobile").classList.add("closed");
105 | }
106 |
107 | function handleLastSubmenuClick(e) {
108 | e.preventDefault();
109 | const el = e.currentTarget;
110 | el.classList.toggle("active");
111 |
112 | const submenu = el.parentElement.nextElementSibling;
113 | if (submenu && submenu.matches(".submenu")) {
114 | if (submenu.classList.contains("closed")) {
115 | submenu.style.height = submenu.scrollHeight + "px";
116 | submenu.classList.remove("closed");
117 | } else {
118 | submenu.classList.add("closed");
119 | submenu.style.height = "";
120 | }
121 | }
122 | }
123 |
124 | function handleWebMenuToggle(e) {
125 | const el = e.target;
126 |
127 | el.classList.toggle("active");
128 |
129 | const menu = document.querySelector(".all_menu.WEB");
130 | if (menu.matches(".closed")) {
131 | menu.classList.remove("closed");
132 | el.title = "전체메뉴 닫힘";
133 | } else {
134 | menu.classList.add("closed");
135 | el.title = "전체메뉴 열림";
136 | }
137 | }
138 |
139 | function handleMobileMenuOpen(e) {
140 | document.querySelector(".all_menu.Mobile").classList.remove("closed");
141 | e.target.title = "전체메뉴 열림";
142 | }
143 |
144 | function handleMobileMenuClose() {
145 | document.querySelector(".all_menu.Mobile").classList.add("closed");
146 | document.querySelector(".btnAllMenuM").title = "전체메뉴 닫힘";
147 | }
148 |
149 | function handleWebMenuClose(e) {
150 | if (e.target.matches("a")) {
151 | document.querySelector(".all_menu.WEB").classList.add("closed");
152 | document.querySelector(".btnAllMenu").classList.remove("active");
153 | document.querySelector(".btnAllMenu").title = "전체메뉴 닫힘";
154 | }
155 | }
156 |
157 | function handleMobileSubmenuToggle(e) {
158 | e.preventDefault();
159 | const el = e.target;
160 | el.classList.toggle("active");
161 |
162 | const submenu = el.parentElement.nextElementSibling;
163 | if (submenu.matches(".closed")) {
164 | submenu.style.height = submenu.scrollHeight + "px";
165 | submenu.classList.remove("closed");
166 | } else {
167 | submenu.classList.add("closed");
168 | submenu.style.height = "";
169 | }
170 | }
171 |
172 | function handleGlobalClick(e) {
173 | const el = e.target;
174 |
175 | if (el.matches(".mini_board .tab li a")) {
176 | e.preventDefault();
177 | const tabs = el.closest(".tab");
178 |
179 | tabs.querySelectorAll("a").forEach((a) => a.classList.remove("on"));
180 | el.classList.add("on");
181 |
182 | const divs = document.querySelectorAll(".mini_board .list > div");
183 | divs.forEach((div) => (div.style.display = "none"));
184 |
185 | const idx = Array.prototype.indexOf.call(tabs.querySelectorAll("a"), el);
186 | divs[idx].style.display = "block";
187 | } else if (el.matches(".f_chk input")) {
188 | el.parentElement.classList[el.checked ? "add" : "remove"]("on");
189 | }
190 | }
191 |
--------------------------------------------------------------------------------
/src/main.jsx:
--------------------------------------------------------------------------------
1 | import React from "react";
2 | import ReactDOM from "react-dom/client";
3 | import App from "./App.jsx";
4 |
5 | ReactDOM.createRoot(document.getElementById("root")).render(
6 |
7 |
8 |
9 | );
10 |
--------------------------------------------------------------------------------
/src/pages/about/EgovAboutHistory.jsx:
--------------------------------------------------------------------------------
1 | import { Link } from "react-router-dom";
2 |
3 | import URL from "@/constants/url";
4 | import { default as EgovLeftNav } from "@/components/leftmenu/EgovLeftNavAbout";
5 |
6 | function EgovAboutHistory() {
7 | return (
8 |
9 |
10 | {/* */}
11 |
12 |
13 |
14 |
15 | Home
16 |
17 |
18 |
19 | 사이트 소개
20 |
21 | 연혁
22 |
23 |
24 | {/* */}
25 |
26 |
27 | {/* */}
28 |
29 | {/* */}
30 |
31 |
32 | {/* */}
33 |
34 |
사이트 소개
35 |
36 |
37 | 표준프레임워크 경량환경 포털사이트를 소개합니다.
38 |
39 |
40 |
전자정부표준프레임워크 연혁
41 |
42 |
연혁
43 |
44 |
45 | 표준프레임워크 활성화 전담조직으로 한국정보화진흥원(NIA)에 2010년
46 | 11월 4일 「표준프레임워크센터」가
47 | 설립되었으며 정책지원, 글로벌 확산 등을 담당할 NIA 인력과 R&D,
48 | 기술지원 등을 담당할 외부 민간 전문가로
49 | 구성되었습니다.
50 |
51 |
52 | {/* */}
53 |
54 |
55 |
56 |
57 | );
58 | }
59 |
60 | export default EgovAboutHistory;
61 |
--------------------------------------------------------------------------------
/src/pages/about/EgovAboutLocation.jsx:
--------------------------------------------------------------------------------
1 | import { Link } from "react-router-dom";
2 |
3 | import URL from "@/constants/url";
4 | import { default as EgovLeftNav } from "@/components/leftmenu/EgovLeftNavAbout";
5 |
6 | import mapImg from "/assets/images/map.png";
7 | import qrImg from "/assets/images/qrcode.png";
8 |
9 | function EgovAboutLocation() {
10 | return (
11 |
12 |
13 | {/* */}
14 |
15 |
16 |
17 |
18 | Home
19 |
20 |
21 |
22 | 사이트 소개
23 |
24 | 찾아오시는길
25 |
26 |
27 | {/* */}
28 |
29 |
30 | {/* */}
31 |
32 | {/* */}
33 |
34 |
35 | {/* */}
36 |
37 |
사이트 소개
38 |
39 |
40 | 표준프레임워크 경량환경 포털사이트를 소개합니다.
41 |
42 |
43 |
찾아오시는길
44 |
45 |
54 |
55 |
56 |
57 |
표준프레임워크센터 주소
58 |
59 | 도로명주소
60 |
61 | 04513 서울특별시 중구 세종대로 39 대한서울상공회의소 7층
62 |
63 |
64 |
65 | 지번주소
66 |
67 | 04513 서울특별시 중구 남대문로4가 45 대한서울상공회의소 7층
68 |
69 |
70 |
71 |
72 |
QR코드로 위치알아보기
73 |
74 | 스마트폰에서 QR코드
75 |
76 | 리더를 이용해 사진·
77 |
78 | 지도 등 다양한 정보를
79 |
80 | 확인하세요.
81 |
82 |
83 |
84 |
85 |
86 |
87 |
88 |
찾아오시는 길
89 |
90 | 지하철 2호선
91 | 시청역 9번 출구 5분거리
92 |
93 |
94 | 지하철 1호선
95 | 서울역 3번 출구 5분거리
96 |
97 |
98 |
99 |
연락처
100 |
101 | 전화
102 | 0000-0000
103 |
104 |
105 | 이메일
106 | egovframeexample@gmail.com
107 |
108 |
109 |
110 |
111 | {/* */}
112 |
113 |
114 |
115 |
116 | );
117 | }
118 |
119 | export default EgovAboutLocation;
120 |
--------------------------------------------------------------------------------
/src/pages/about/EgovAboutOrganization.jsx:
--------------------------------------------------------------------------------
1 | import { Link } from "react-router-dom";
2 |
3 | import URL from "@/constants/url";
4 | import { default as EgovLeftNav } from "@/components/leftmenu/EgovLeftNavAbout";
5 |
6 | function EgovAboutOrganization() {
7 | return (
8 |
9 |
10 | {/* */}
11 |
12 |
13 |
14 |
15 | Home
16 |
17 |
18 |
19 | 사이트 소개
20 |
21 | 조직소개
22 |
23 |
24 | {/* */}
25 |
26 |
27 | {/* */}
28 |
29 | {/* */}
30 |
31 |
32 | {/* */}
33 |
34 |
사이트 소개
35 |
36 |
37 | 표준프레임워크 경량환경 포털사이트를 소개합니다.
38 |
39 |
40 |
조직소개
41 |
42 |
조직
43 |
44 |
45 | 오픈커뮤니티의 초기 정착을 위해 표준프레임워크 개발 참여자와 국내
46 | 주요 오픈커뮤니티의 운영자·전문가를 리딩
47 |
48 | 그룹(PMC, 커미터)으로 구성 오픈커뮤니티의 지속적인 확대·발전을
49 | 위해 프로젝트 활동에 적극적으로 참여하는
50 | 커뮤니티 회원이 리딩그룹의 역할을 획득할 수 있도록 투명하고 공정한
51 | 의사결정 체계를 수립
52 |
53 |
54 | {/* */}
55 |
56 |
57 |
58 |
59 | );
60 | }
61 |
62 | export default EgovAboutOrganization;
63 |
--------------------------------------------------------------------------------
/src/pages/about/EgovAboutSite.jsx:
--------------------------------------------------------------------------------
1 | import { Link } from "react-router-dom";
2 |
3 | import { default as EgovLeftNav } from "@/components/leftmenu/EgovLeftNavAbout";
4 |
5 | function EgovAboutSite() {
6 | return (
7 |
8 |
9 | {/* */}
10 |
11 |
12 |
13 |
14 | Home
15 |
16 |
17 |
18 | 사이트 소개
19 |
20 | 소개
21 |
22 |
23 | {/* */}
24 |
25 |
26 | {/* */}
27 |
28 | {/* */}
29 |
30 |
31 | {/* */}
32 |
33 |
사이트 소개
34 |
35 |
36 | 표준프레임워크 경량환경의 개요와 연혁, 조직소개,
37 |
38 | 표준프레임워크센터의 약도 등의 정보를 제공하고 있습니다.
39 |
40 |
41 |
전자정부표준프레임워크 소개
42 |
43 |
개요
44 |
45 |
46 | 전자정부 표준 프레임워크는 응용SW의 구성기반이 되며 응용SW실행 시
47 | 필요한 기본 기능을 제공하는 환경이다.
48 |
49 | 전자정부 표준 프레임워크는 ‘전자정부 서비스의 품질향상 및 정보화
50 | 투자 효율성 향상’을 위해 개발 프레임워크
51 |
52 | 표준을 정립하고, 개발 프레임워크 표준 적용을 통한 응용 SW의 표준화
53 | 및 품질과 재사용성 향상을 목표로 한다.
54 |
55 |
56 |
57 |
58 | 전자정부 서비스 품질향상 및 정보화투자 효율성 향상
59 |
60 |
61 |
62 |
63 | 국가 정보화
64 |
65 | 투자효율성 제고
66 |
67 |
68 | 중소SI업체
69 |
70 | 경쟁력 확보
71 |
72 |
73 | 선진 국가정보화
74 |
75 | 기반환경 제공
76 |
77 |
78 |
79 |
80 | 전자정부표준프레임워크
81 |
82 | 활용
83 |
84 |
85 |
86 |
87 | 전자정부표준프레임워크 구축 및 적용 요구
88 |
89 |
90 |
91 |
92 | 특정업체 종속성 발생으로
93 |
94 | 인한 공정경쟁 저하 및 사업자
95 |
96 | 변경 시 예산낭비
97 |
98 |
99 |
100 |
101 | 기관별/사업별 개별적인
102 |
103 | 정보화 사업추진으로 중복개발
104 |
105 |
106 |
107 |
108 | 표준화된 공통 개발기반 부재로
109 |
110 | 시스템간 상호 운용성 및
111 | 재사용성 저하
112 |
113 |
114 |
115 |
116 | 전자정부표준프레임워크는 응용SW의 구성기반이 되며 응용SW실행
117 | 시 필요한 기본 기능을 제공하는 환경으로 정보시스템 구축 시
118 | 특정 대기업의 프레임워크로 구축·운영되어, 사업자 종속-비용증가
119 | 및 중소기업의 입찰제한 등의 폐단이 발생하는 것을 방지하기 위한
120 | 목적과 ‘전자정부 서비스의 품질향상 및 정보화 투자 효율성
121 | 향상’을 위해 개발 프레임워크 표준을 정립하고, 개발 프레임워크
122 | 표준 적용을 통한 응용 SW의 표준화 및 품질과 재사용성 향상을
123 | 목표로 한다.
124 |
125 |
126 |
127 |
배경
128 |
129 | 현재 전자정부는 유사한 기능을 가지는 다양한 종류 및 버전의
130 | 프레임워크를 개별 시스템 단위로 적용/관리하고 있으며, 이에 따라
131 | 다양한 문제점들이 발생하고 있다. 전자정부에 적용된
132 | 개발프레임워크는 Black Box 형태로 제공되어 사업자의 기술지원
133 | 없이는 응용 SW를 유지보수하기 어렵기 때문에 사업자에 대한
134 | 의존성이 발생한다. 복수개의 개발프레임워크가 적용된 사업의 경우,
135 | 프레임워크에 따라 개발표준 정의, 개발자수급, 교육시행 등 별도의
136 | 유지보수 체계를 갖추는 중복 투자가 발생하며, 개발프레임워크의
137 | 체계적인 관리절차의 미비로 동일 개발프레임워크라 하더라도 버전
138 | 관리에 어려움이 있다.전자정부의 프레임워크의 표준화는 사업자
139 | 고유 개발 프레임워크에 대한 기술 종속성을 배제하고 표준화를 통해
140 | 응용 SW의 표준화와 품질, 재사용성을 향상시키며, 개발
141 | 프레임워크의 유지 보수 단일화를 통한 투자 효율성을 높인다.
142 |
143 |
144 |
특징
145 |
146 | 현재 전자정부는 유사한 기능을 가지는 다양한 종류 및 버전의
147 | 프레임워크를 개별 시스템 단위로 적용/관리하고 있으며, 이에 따라
148 | 다양한 문제점들이 발생하고 있다. 전자정부에 적용된
149 | 개발프레임워크는 Black Box 형태로 제공되어 사업자의 기술지원
150 | 없이는 응용 SW를 유지보수하기 어렵기 때문에 사업자에 대한
151 | 의존성이 발생한다. 복수개의 개발프레임워크가 적용된 사업의 경우,
152 | 프레임워크에 따라 개발표준 정의, 개발자수급, 교육시행 등 별도의
153 | 유지보수 체계를 갖추는 중복 투자가 발생하며, 개발프레임워크의
154 | 체계적인 관리절차의 미비로 동일 개발프레임워크라 하더라도 버전
155 | 관리에 어려움이 있다.전자정부의 프레임워크의 표준화는 사업자
156 | 고유 개발 프레임워크에 대한 기술 종속성을 배제하고 표준화를 통해
157 | 응용 SW의 표준화와 품질, 재사용성을 향상시키며, 개발
158 | 프레임워크의 유지 보수 단일화를 통한 투자 효율성을 높인다.
159 |
160 |
161 |
162 | {/* */}
163 |
164 |
165 |
166 |
167 | );
168 | }
169 |
170 | export default EgovAboutSite;
171 |
--------------------------------------------------------------------------------
/src/pages/admin/gallery/EgovAdminGalleryDetail.jsx:
--------------------------------------------------------------------------------
1 | import { useState, useEffect } from "react";
2 |
3 | import { Link, useLocation, useNavigate } from "react-router-dom";
4 |
5 | import * as EgovNet from "@/api/egovFetch";
6 | import URL from "@/constants/url";
7 | import CODE from "@/constants/code";
8 | import { GALLERY_BBS_ID } from "@/config";
9 |
10 | import { default as EgovLeftNav } from "@/components/leftmenu/EgovLeftNavAdmin";
11 | import EgovAttachFile from "@/components/EgovAttachFile";
12 | import EgovImageGallery from "@/components/EgovImageGallery";
13 |
14 | function EgovAdminGalleryDetail(props) {
15 | console.group("EgovAdminGalleryDetail");
16 | console.log("------------------------------");
17 | console.log("EgovAdminGalleryDetail [props] : ", props);
18 |
19 | const navigate = useNavigate();
20 | const location = useLocation();
21 | console.log("EgovAdminGalleryDetail [location] : ", location);
22 |
23 | const bbsId = location.state.bbsId || GALLERY_BBS_ID;
24 | const nttId = location.state.nttId;
25 | const searchCondition = location.state.searchCondition;
26 |
27 | const [masterBoard, setMasterBoard] = useState({});
28 | const [boardDetail, setBoardDetail] = useState({});
29 | const [boardAttachFiles, setBoardAttachFiles] = useState();
30 |
31 | const retrieveDetail = () => {
32 | const retrieveDetailURL = `/board/${bbsId}/${nttId}`;
33 | const requestOptions = {
34 | method: "GET",
35 | headers: {
36 | "Content-type": "application/json",
37 | },
38 | };
39 | EgovNet.requestFetch(retrieveDetailURL, requestOptions, function (resp) {
40 | setMasterBoard(resp.result.brdMstrVO);
41 | setBoardDetail(resp.result.boardVO);
42 | setBoardAttachFiles(resp.result.resultFiles);
43 | });
44 | };
45 |
46 | const onClickDeleteBoardArticle = (bbsId, nttId) => {
47 | const deleteBoardURL = `/board/${bbsId}/${nttId}`;
48 |
49 | const requestOptions = {
50 | method: "PATCH",
51 | headers: {
52 | "Content-type": "application/json",
53 | },
54 | };
55 |
56 | EgovNet.requestFetch(deleteBoardURL, requestOptions, (resp) => {
57 | console.log("====>>> board delete= ", resp);
58 | if (Number(resp.resultCode) === Number(CODE.RCV_SUCCESS)) {
59 | alert("게시글이 삭제되었습니다.");
60 | navigate(URL.ADMIN_GALLERY, { replace: true });
61 | } else {
62 | // alert("ERR : " + resp.message);
63 | navigate(
64 | { pathname: URL.ERROR },
65 | { state: { msg: resp.resultMessage } }
66 | );
67 | }
68 | });
69 | };
70 |
71 | useEffect(function () {
72 | retrieveDetail();
73 | // eslint-disable-next-line react-hooks/exhaustive-deps
74 | }, []);
75 |
76 | console.groupEnd("EgovAdminGalleryDetail");
77 |
78 | return (
79 |
80 |
81 | {/* */}
82 |
83 |
84 |
85 |
86 | Home
87 |
88 |
89 |
90 | 사이트관리
91 |
92 | {masterBoard && masterBoard.bbsNm}
93 |
94 |
95 | {/* */}
96 |
97 |
98 | {/* */}
99 |
100 | {/* */}
101 |
102 |
103 | {/* */}
104 |
105 |
106 |
사이트관리
107 |
108 |
109 |
{masterBoard && masterBoard.bbsNm}
110 |
111 | {/* */}
112 |
113 |
114 |
{boardDetail && boardDetail.nttSj}
115 |
116 |
117 | 작성자
118 | {boardDetail && boardDetail.frstRegisterNm}
119 |
120 |
121 | 작성일
122 | {boardDetail && boardDetail.frstRegisterPnttm}
123 |
124 |
125 | 조회수
126 | {boardDetail && boardDetail.inqireCo}
127 |
128 |
129 |
130 |
131 |
132 |
139 |
140 |
141 |
142 |
143 |
144 | {/* 답글이 아니고 게시판 파일 첨부 가능 상태에서만 첨부파일 컴포넌트 노출 */}
145 | {boardDetail.parnts === "0" &&
146 | masterBoard.fileAtchPosblAt === "Y" && (
147 |
148 | )}
149 |
150 |
151 |
152 | {masterBoard.bbsUseFlag === "Y" && (
153 |
190 | )}
191 |
192 |
201 | 목록
202 |
203 |
204 |
205 |
206 | {/* */}
207 |
208 | {/* */}
209 |
210 |
211 |
212 |
213 | );
214 | }
215 |
216 | export default EgovAdminGalleryDetail;
217 |
--------------------------------------------------------------------------------
/src/pages/admin/manager/EgovAdminPasswordUpdate.jsx:
--------------------------------------------------------------------------------
1 | import { useState, useEffect } from "react";
2 | import { Link, useNavigate } from "react-router-dom";
3 | import * as EgovNet from "@/api/egovFetch";
4 | import URL from "@/constants/url";
5 | import CODE from "@/constants/code";
6 | import { default as EgovLeftNav } from "@/components/leftmenu/EgovLeftNavAdmin";
7 |
8 | function EgovAdminPasswordUpdate(props) {
9 | console.group("EgovAdminPasswordUpdate");
10 | console.log("[Start] EgovAdminPasswordUpdate ------------------------------");
11 | console.log("EgovAdminPasswordUpdate [props] : ", props);
12 |
13 | const navigate = useNavigate();
14 | const [oldPassword, setOldPassword] = useState("");
15 | const [newPassword, setNewPassword] = useState("");
16 | const [confirmPassword, setConfirmPassword] = useState("");
17 | const formValidator = (formData) => {
18 | if (
19 | formData.get("old_password") === null ||
20 | formData.get("old_password") === ""
21 | ) {
22 | alert("기존 암호는 필수 값입니다.");
23 | return false;
24 | }
25 | if (
26 | formData.get("new_password") === null ||
27 | formData.get("new_password") === ""
28 | ) {
29 | alert("신규 암호는 필수 값입니다.");
30 | return false;
31 | }
32 | if (formData.get("new_password") === formData.get("old_password")) {
33 | alert("신규 암호는 기존 암호와 동일하게 사용할 수 없습니다.");
34 | return false;
35 | }
36 | return true;
37 | };
38 |
39 | const updateAdminPassword = () => {
40 | if (newPassword !== confirmPassword) {
41 | return alert("신규 암호와 입력 확인값이 일치하지 않습니다");
42 | }
43 |
44 | const editURL = "/admin/password";
45 |
46 | let requestOptions = {};
47 | const formData = new FormData();
48 | formData.append("old_password", oldPassword);
49 | formData.append("new_password", newPassword);
50 | if (formValidator(formData)) {
51 | requestOptions = {
52 | method: "PATCH",
53 | headers: {
54 | "Content-type": "application/json",
55 | },
56 | body: JSON.stringify({
57 | old_password: oldPassword,
58 | new_password: newPassword,
59 | }),
60 | };
61 | EgovNet.requestFetch(editURL, requestOptions, (resp) => {
62 | if (Number(resp.resultCode) === Number(CODE.RCV_SUCCESS)) {
63 | alert("OK 다음 로그인 시 신규 암호를 사용하세요.");
64 | navigate({ pathname: URL.MAIN }, { replace: true });
65 | } else {
66 | alert("Fail 변경되지 않았습니다. 다시 시도해 주세요.");
67 | navigate(
68 | { pathname: URL.ERROR },
69 | { state: { msg: resp.resultMessage } }
70 | ); //에러메세지 변수명 변경
71 | }
72 | });
73 | }
74 | };
75 |
76 | useEffect(() => {
77 | // eslint-disable-next-line react-hooks/exhaustive-deps
78 | }, []);
79 |
80 | console.log("------------------------------EgovAdminPasswordUpdate [End]");
81 | console.groupEnd("EgovAdminPasswordUpdate");
82 |
83 | return (
84 |
85 |
86 | {/* */}
87 |
88 |
89 |
90 |
91 | Home
92 |
93 |
94 |
95 | 사이트관리
96 |
97 | 사이트관리자 암호변경
98 |
99 |
100 | {/* */}
101 |
102 |
103 | {/* */}
104 |
105 | {/* */}
106 |
107 |
108 | {/* */}
109 |
110 |
111 |
사이트관리
112 |
113 |
사이트관리자 암호변경
114 |
182 | {/* */}
183 |
184 |
185 |
186 |
187 | );
188 | }
189 |
190 | export default EgovAdminPasswordUpdate;
191 |
--------------------------------------------------------------------------------
/src/pages/admin/notice/EgovAdminNoticeDetail.jsx:
--------------------------------------------------------------------------------
1 | import { useState, useEffect } from "react";
2 |
3 | import { Link, useLocation, useNavigate } from "react-router-dom";
4 |
5 | import * as EgovNet from "@/api/egovFetch";
6 | import URL from "@/constants/url";
7 | import CODE from "@/constants/code";
8 | import { NOTICE_BBS_ID } from "@/config";
9 |
10 | import { default as EgovLeftNav } from "@/components/leftmenu/EgovLeftNavAdmin";
11 | import EgovAttachFile from "@/components/EgovAttachFile";
12 |
13 | function EgovAdminNoticeDetail(props) {
14 | console.group("EgovAdminNoticeDetail");
15 | console.log("------------------------------");
16 | console.log("EgovAdminNoticeDetail [props] : ", props);
17 |
18 | const navigate = useNavigate();
19 | const location = useLocation();
20 | console.log("EgovAdminNoticeDetail [location] : ", location);
21 |
22 | const bbsId = location.state.bbsId || NOTICE_BBS_ID;
23 | const nttId = location.state.nttId;
24 | const searchCondition = location.state.searchCondition;
25 |
26 | const [masterBoard, setMasterBoard] = useState({});
27 | const [boardDetail, setBoardDetail] = useState({});
28 | const [boardAttachFiles, setBoardAttachFiles] = useState();
29 |
30 | const retrieveDetail = () => {
31 | const retrieveDetailURL = `/board/${bbsId}/${nttId}`;
32 | const requestOptions = {
33 | method: "GET",
34 | headers: {
35 | "Content-type": "application/json",
36 | },
37 | };
38 | EgovNet.requestFetch(retrieveDetailURL, requestOptions, function (resp) {
39 | setMasterBoard(resp.result.brdMstrVO);
40 | setBoardDetail(resp.result.boardVO);
41 | setBoardAttachFiles(resp.result.resultFiles);
42 | });
43 | };
44 |
45 | const onClickDeleteBoardArticle = (bbsId, nttId) => {
46 | const deleteBoardURL = `/board/${bbsId}/${nttId}`;
47 |
48 | const requestOptions = {
49 | method: "PATCH",
50 | headers: {
51 | "Content-type": "application/json",
52 | },
53 | };
54 |
55 | EgovNet.requestFetch(deleteBoardURL, requestOptions, (resp) => {
56 | console.log("====>>> board delete= ", resp);
57 | if (Number(resp.resultCode) === Number(CODE.RCV_SUCCESS)) {
58 | alert("게시글이 삭제되었습니다.");
59 | navigate(URL.ADMIN_NOTICE, { replace: true });
60 | } else {
61 | navigate(
62 | { pathname: URL.ERROR },
63 | { state: { msg: resp.resultMessage } }
64 | );
65 | }
66 | });
67 | };
68 |
69 | useEffect(function () {
70 | retrieveDetail();
71 | // eslint-disable-next-line react-hooks/exhaustive-deps
72 | }, []);
73 |
74 | console.groupEnd("EgovAdminNoticeDetail");
75 |
76 | return (
77 |
78 |
79 | {/* */}
80 |
81 |
82 |
83 |
84 | Home
85 |
86 |
87 |
88 | 사이트관리
89 |
90 | {masterBoard && masterBoard.bbsNm}
91 |
92 |
93 | {/* */}
94 |
95 |
96 | {/* */}
97 |
98 | {/* */}
99 |
100 |
101 | {/* */}
102 |
103 |
104 |
사이트관리
105 |
106 |
107 |
{masterBoard && masterBoard.bbsNm}
108 |
109 | {/* */}
110 |
111 |
112 |
{boardDetail && boardDetail.nttSj}
113 |
114 |
115 | 작성자
116 | {boardDetail && boardDetail.frstRegisterNm}
117 |
118 |
119 | 작성일
120 | {boardDetail && boardDetail.frstRegisterPnttm}
121 |
122 |
123 | 조회수
124 | {boardDetail && boardDetail.inqireCo}
125 |
126 |
127 |
128 |
129 |
130 |
137 |
138 |
139 | {/* 답글이 아니고 게시판 파일 첨부 가능 상태에서만 첨부파일 컴포넌트 노출 */}
140 | {boardDetail.parnts === "0" &&
141 | masterBoard.fileAtchPosblAt === "Y" && (
142 |
143 | )}
144 |
145 |
146 |
147 | {masterBoard.bbsUseFlag === "Y" && (
148 |
185 | )}
186 |
187 |
196 | 목록
197 |
198 |
199 |
200 |
201 | {/* */}
202 |
203 | {/* */}
204 |
205 |
206 |
207 |
208 | );
209 | }
210 |
211 | export default EgovAdminNoticeDetail;
212 |
--------------------------------------------------------------------------------
/src/pages/admin/schedule/EgovAdminScheduleDetail.jsx:
--------------------------------------------------------------------------------
1 | import { useState, useEffect } from "react";
2 | import { Link, useLocation, useNavigate } from "react-router-dom";
3 |
4 | import * as EgovNet from "@/api/egovFetch";
5 | import URL from "@/constants/url";
6 | import CODE from "@/constants/code";
7 |
8 | import { default as EgovLeftNav } from "@/components/leftmenu/EgovLeftNavAdmin";
9 | import EgovAttachFile from "@/components/EgovAttachFile";
10 |
11 | function EgovAdminScheduleDetail(props) {
12 | console.group("EgovAdminScheduleDetail");
13 | console.log("[Start] EgovAdminScheduleDetail ------------------------------");
14 | console.log("EgovAdminScheduleDetail [props] : ", props);
15 |
16 | const navigate = useNavigate();
17 | const location = useLocation();
18 | console.log("EgovAdminScheduleDetail [location] : ", location);
19 |
20 | const [scheduleDetail, setScheduleDetail] = useState({});
21 | const [boardAttachFiles, setBoardAttachFiles] = useState();
22 | const [user, setUser] = useState({});
23 |
24 | const retrieveDetail = () => {
25 | const retrieveDetailURL = `/schedule/${location.state?.schdulId}`;
26 |
27 | const requestOptions = {
28 | method: "GET",
29 | headers: {
30 | "Content-type": "application/json",
31 | },
32 | };
33 | EgovNet.requestFetch(retrieveDetailURL, requestOptions, function (resp) {
34 | let rawScheduleDetail = resp.result.scheduleDetail;
35 | rawScheduleDetail.startDateTime = convertDate(
36 | rawScheduleDetail.schdulBgnde
37 | );
38 | rawScheduleDetail.endDateTime = convertDate(
39 | rawScheduleDetail.schdulEndde
40 | );
41 | rawScheduleDetail.reptitSeCodeNm = getCodeName(
42 | resp.result.reptitSeCode,
43 | resp.result.scheduleDetail.reptitSeCode
44 | );
45 | rawScheduleDetail.schdulIpcrCodeNm = getCodeName(
46 | resp.result.schdulIpcrCode,
47 | resp.result.scheduleDetail.schdulIpcrCode
48 | );
49 | rawScheduleDetail.schdulSeNm = getCodeName(
50 | resp.result.schdulSe,
51 | resp.result.scheduleDetail.schdulSe
52 | );
53 | setScheduleDetail(rawScheduleDetail);
54 | setUser(resp.result.user);
55 | setBoardAttachFiles(resp.result.resultFiles);
56 | });
57 | };
58 | const convertDate = (str) => {
59 | let year = str.substring(0, 4);
60 | let month = str.substring(4, 6);
61 | let date = str.substring(6, 8);
62 | let hour = str.substring(8, 10);
63 | let minute = str.substring(10, 12);
64 | return {
65 | year: year,
66 | month: month,
67 | date: date,
68 | hour: hour,
69 | minute: minute,
70 | dateForm:
71 | year +
72 | "년 " +
73 | month +
74 | "월 " +
75 | date +
76 | "일 " +
77 | hour +
78 | "시 " +
79 | minute +
80 | "분 ",
81 | };
82 | };
83 |
84 | const getCodeName = (codeArr, code) => {
85 | return codeArr.map((codeObj) => {
86 | if (codeObj.code === code?.trim()) return codeObj.codeNm;
87 | else return "";
88 | });
89 | };
90 |
91 | const onClickDeleteSchedule = (schdulId) => {
92 | const deleteBoardURL = `/schedule/${schdulId}`;
93 |
94 | const requestOptions = {
95 | method: "DELETE",
96 | headers: {
97 | "Content-type": "application/json",
98 | },
99 | };
100 |
101 | EgovNet.requestFetch(deleteBoardURL, requestOptions, (resp) => {
102 | console.log("====>>> Schdule delete= ", resp);
103 | if (Number(resp.resultCode) === Number(CODE.RCV_SUCCESS)) {
104 | alert("게시글이 삭제되었습니다.");
105 | navigate(URL.ADMIN_SCHEDULE, { replace: true });
106 | } else {
107 | // alert("ERR : " + resp.message);
108 | navigate(
109 | { pathname: URL.ERROR },
110 | { state: { msg: resp.resultMessage } }
111 | );
112 | }
113 | });
114 | };
115 |
116 | useEffect(function () {
117 | retrieveDetail();
118 | // eslint-disable-next-line react-hooks/exhaustive-deps
119 | }, []);
120 |
121 | console.log("------------------------------EgovAdminScheduleDetail [End]");
122 | console.groupEnd("EgovAdminScheduleDetail");
123 | return (
124 |
125 |
126 | {/* */}
127 |
128 |
129 |
130 |
131 | Home
132 |
133 |
134 |
135 | 사이트관리
136 |
137 | 일정관리
138 |
139 |
140 | {/* */}
141 |
142 |
143 | {/* */}
144 |
145 | {/* */}
146 |
147 |
148 | {/* */}
149 |
150 |
151 |
사이트관리
152 |
153 |
154 |
일정관리 상세보기
155 |
156 | {/* */}
157 |
158 |
159 | 일정구분
160 | {scheduleDetail.schdulSeNm}
161 |
162 |
163 | 중요도
164 | {scheduleDetail.schdulIpcrCodeNm}
165 |
166 |
167 | 부서
168 | {scheduleDetail.schdulDeptName}
169 |
170 |
171 | 일정명
172 | {scheduleDetail.schdulNm}
173 |
174 |
175 | 일정내용
176 | {scheduleDetail.schdulCn}
177 |
178 |
179 | 반복구분
180 | {scheduleDetail.reptitSeCodeNm}
181 |
182 |
183 | 날짜/시간
184 |
185 | {" "}
186 | {scheduleDetail.startDateTime?.dateForm} ~{" "}
187 | {scheduleDetail.endDateTime?.dateForm}
188 |
189 |
190 |
191 | 담당자
192 | {scheduleDetail.schdulChargerName}
193 |
194 |
195 |
196 |
197 | {/* */}
198 |
199 | {user.id && (
200 |
201 |
208 | 수정
209 |
210 | {
213 | onClickDeleteSchedule(location.state?.schdulId);
214 | }}
215 | >
216 | 삭제
217 |
218 |
219 | )}
220 |
221 |
225 | 목록
226 |
227 |
228 |
229 | {/* */}
230 |
231 | {/* */}
232 |
233 | {/* */}
234 |
235 |
236 |
237 |
238 | );
239 | }
240 |
241 | export default EgovAdminScheduleDetail;
242 |
--------------------------------------------------------------------------------
/src/pages/inform/daily/EgovDailyDetail.jsx:
--------------------------------------------------------------------------------
1 | import { useState, useEffect } from "react";
2 | import { Link, useLocation } from "react-router-dom";
3 |
4 | import * as EgovNet from "@/api/egovFetch";
5 | import URL from "@/constants/url";
6 |
7 | import { default as EgovLeftNav } from "@/components/leftmenu/EgovLeftNavInform";
8 | import EgovAttachFile from "@/components/EgovAttachFile";
9 |
10 | function EgovDailyDetail(props) {
11 | console.group("EgovDailyDetail");
12 | console.log("[Start] EgovDailyDetail ------------------------------");
13 | console.log("EgovDailyDetail [props] : ", props);
14 |
15 | const location = useLocation();
16 | console.log("EgovDailyDetail [location] : ", location);
17 |
18 | const [scheduleDetail, setScheduleDetail] = useState({});
19 | const [boardAttachFiles, setBoardAttachFiles] = useState();
20 |
21 | const retrieveDetail = () => {
22 | const retrieveDetailURL = `/schedule/${location.state?.schdulId}`;
23 | const requestOptions = {
24 | method: "GET",
25 | headers: {
26 | "Content-type": "application/json",
27 | },
28 | };
29 | EgovNet.requestFetch(retrieveDetailURL, requestOptions, function (resp) {
30 | let rawScheduleDetail = resp.result.scheduleDetail;
31 | rawScheduleDetail.startDateTime = convertDate(
32 | rawScheduleDetail.schdulBgnde
33 | );
34 | rawScheduleDetail.endDateTime = convertDate(
35 | rawScheduleDetail.schdulEndde
36 | );
37 | rawScheduleDetail.reptitSeCodeNm = getCodeName(
38 | resp.result.reptitSeCode,
39 | resp.result.scheduleDetail.reptitSeCode
40 | );
41 | rawScheduleDetail.schdulIpcrCodeNm = getCodeName(
42 | resp.result.schdulIpcrCode,
43 | resp.result.scheduleDetail.schdulIpcrCode
44 | );
45 | rawScheduleDetail.schdulSeNm = getCodeName(
46 | resp.result.schdulSe,
47 | resp.result.scheduleDetail.schdulSe
48 | );
49 | setScheduleDetail(rawScheduleDetail);
50 | setBoardAttachFiles(resp.result.resultFiles);
51 | });
52 | };
53 | const convertDate = (str) => {
54 | let year = str.substring(0, 4);
55 | let month = str.substring(4, 6);
56 | let date = str.substring(6, 8);
57 | let hour = str.substring(8, 10);
58 | let minute = str.substring(10, 12);
59 | return {
60 | year: year,
61 | month: month,
62 | date: date,
63 | hour: hour,
64 | minute: minute,
65 | dateForm:
66 | year +
67 | "년 " +
68 | month +
69 | "월 " +
70 | date +
71 | "일 " +
72 | hour +
73 | "시 " +
74 | minute +
75 | "분 ",
76 | };
77 | };
78 |
79 | const getCodeName = (codeArr, code) => {
80 | return codeArr.map((codeObj) => {
81 | if (codeObj.code === code?.trim()) return codeObj.codeNm;
82 | else return "";
83 | });
84 | };
85 |
86 | useEffect(function () {
87 | retrieveDetail();
88 | // eslint-disable-next-line react-hooks/exhaustive-deps
89 | }, []);
90 |
91 | console.log("------------------------------EgovDailyDetail [End]");
92 | console.groupEnd("EgovDailyDetail");
93 | return (
94 |
95 |
96 | {/* */}
97 |
98 |
99 |
100 |
101 | Home
102 |
103 |
104 |
105 | 알림마당
106 |
107 | 일정관리
108 |
109 |
110 | {/* */}
111 |
112 |
113 | {/* */}
114 |
115 | {/* */}
116 |
117 |
118 | {/* */}
119 |
120 |
121 |
알림마당
122 |
123 |
124 |
일정관리 상세보기
125 |
126 | {/* */}
127 |
128 |
129 | 일정구분
130 | {scheduleDetail.schdulSeNm}
131 |
132 |
133 | 중요도
134 | {scheduleDetail.schdulIpcrCodeNm}
135 |
136 |
137 | 부서
138 | {scheduleDetail.schdulDeptName}
139 |
140 |
141 | 일정명
142 | {scheduleDetail.schdulNm}
143 |
144 |
145 | 일정내용
146 | {scheduleDetail.schdulCn}
147 |
148 |
149 | 반복구분
150 | {scheduleDetail.reptitSeCodeNm}
151 |
152 |
153 | 날짜/시간
154 |
155 | {" "}
156 | {scheduleDetail.startDateTime?.dateForm} ~{" "}
157 | {scheduleDetail.endDateTime?.dateForm}
158 |
159 |
160 |
161 | 담당자
162 | {scheduleDetail.schdulChargerName}
163 |
164 |
165 |
166 | {/* */}
167 |
168 |
169 |
173 | 목록
174 |
175 |
176 |
177 | {/* */}
178 |
179 | {/* */}
180 |
181 | {/* */}
182 |
183 |
184 |
185 |
186 | );
187 | }
188 |
189 | export default EgovDailyDetail;
190 |
--------------------------------------------------------------------------------
/src/pages/inform/notice/EgovNoticeDetail.jsx:
--------------------------------------------------------------------------------
1 | import { useState, useEffect } from "react";
2 |
3 | import { Link, useLocation, useNavigate } from "react-router-dom";
4 |
5 | import * as EgovNet from "@/api/egovFetch";
6 | import URL from "@/constants/url";
7 | import CODE from "@/constants/code";
8 | import { NOTICE_BBS_ID } from "@/config";
9 |
10 | import { default as EgovLeftNav } from "@/components/leftmenu/EgovLeftNavInform";
11 | import EgovAttachFile from "@/components/EgovAttachFile";
12 | import { getSessionItem } from "@/utils/storage";
13 |
14 | function EgovNoticeDetail(props) {
15 | console.group("EgovNoticeDetail");
16 | console.log("------------------------------");
17 | console.log("EgovNoticeDetail [props] : ", props);
18 |
19 | const navigate = useNavigate();
20 | const location = useLocation();
21 | console.log("EgovNoticeDetail [location] : ", location);
22 | //관리자 권한 체크때문에 추가(아래)
23 | const sessionUser = getSessionItem("loginUser");
24 | const sessionUserSe = sessionUser?.userSe;
25 |
26 | const bbsId = location.state.bbsId || NOTICE_BBS_ID;
27 | const nttId = location.state.nttId;
28 | const searchCondition = location.state.searchCondition;
29 |
30 | const [masterBoard, setMasterBoard] = useState({});
31 | const [user, setUser] = useState({});
32 | const [boardDetail, setBoardDetail] = useState({});
33 | const [boardAttachFiles, setBoardAttachFiles] = useState();
34 |
35 | const retrieveDetail = () => {
36 | const retrieveDetailURL = `/board/${bbsId}/${nttId}`;
37 | const requestOptions = {
38 | method: "GET",
39 | headers: {
40 | "Content-type": "application/json",
41 | },
42 | };
43 | EgovNet.requestFetch(retrieveDetailURL, requestOptions, function (resp) {
44 | setMasterBoard(resp.result.brdMstrVO);
45 | setBoardDetail(resp.result.boardVO);
46 | setUser(resp.result.user);
47 | setBoardAttachFiles(resp.result.resultFiles);
48 | });
49 | };
50 |
51 | const onClickDeleteBoardArticle = (bbsId, nttId) => {
52 | const deleteBoardURL = `/board/${bbsId}/${nttId}`;
53 |
54 | const requestOptions = {
55 | method: "PATCH",
56 | headers: {
57 | "Content-type": "application/json",
58 | },
59 | };
60 |
61 | EgovNet.requestFetch(deleteBoardURL, requestOptions, (resp) => {
62 | console.log("====>>> board delete= ", resp);
63 | if (Number(resp.resultCode) === Number(CODE.RCV_SUCCESS)) {
64 | alert("게시글이 삭제되었습니다.");
65 | navigate(URL.INFORM_NOTICE, { replace: true });
66 | } else {
67 | navigate(
68 | { pathname: URL.ERROR },
69 | { state: { msg: resp.resultMessage } }
70 | );
71 | }
72 | });
73 | };
74 |
75 | useEffect(function () {
76 | retrieveDetail();
77 | // eslint-disable-next-line react-hooks/exhaustive-deps
78 | }, []);
79 |
80 | console.groupEnd("EgovNoticeDetail");
81 |
82 | return (
83 |
84 |
85 | {/* */}
86 |
87 |
88 |
89 |
90 | Home
91 |
92 |
93 |
94 | 알림마당
95 |
96 | {masterBoard && masterBoard.bbsNm}
97 |
98 |
99 | {/* */}
100 |
101 |
102 | {/* */}
103 |
104 | {/* */}
105 |
106 |
107 | {/* */}
108 |
109 |
110 |
알림마당
111 |
112 |
113 |
{masterBoard && masterBoard.bbsNm}
114 |
115 | {/* */}
116 |
117 |
118 |
{boardDetail && boardDetail.nttSj}
119 |
120 |
121 | 작성자
122 | {boardDetail && boardDetail.frstRegisterNm}
123 |
124 |
125 | 작성일
126 | {boardDetail && boardDetail.frstRegisterPnttm}
127 |
128 |
129 | 조회수
130 | {boardDetail && boardDetail.inqireCo}
131 |
132 |
133 |
134 |
135 |
136 |
143 |
144 |
145 | {/* 답글이 아니고 게시판 파일 첨부 가능 상태에서만 첨부파일 컴포넌트 노출 */}
146 | {boardDetail.parnts === "0" &&
147 | masterBoard.fileAtchPosblAt === "Y" && (
148 |
149 | )}
150 |
151 |
152 |
153 | {user &&
154 | sessionUserSe === "ADM" &&
155 | masterBoard.bbsUseFlag === "Y" && (
156 |
157 |
165 | 수정
166 |
167 | {
170 | e.preventDefault();
171 | onClickDeleteBoardArticle(
172 | boardDetail.bbsId,
173 | boardDetail.nttId
174 | );
175 | }}
176 | >
177 | 삭제
178 |
179 | {masterBoard.replyPosblAt === "Y" && (
180 |
188 | 답글작성
189 |
190 | )}
191 |
192 | )}
193 |
194 |
195 |
204 | 목록
205 |
206 |
207 |
208 |
209 | {/* */}
210 |
211 | {/* */}
212 |
213 |
214 |
215 |
216 | );
217 | }
218 |
219 | export default EgovNoticeDetail;
220 |
--------------------------------------------------------------------------------
/src/pages/intro/EgovIntroService.jsx:
--------------------------------------------------------------------------------
1 | import { default as EgovLeftNav } from "@/components/leftmenu/EgovLeftNavIntro";
2 |
3 | function EgovIntroService() {
4 | return (
5 |
6 |
7 | {/* */}
8 |
21 | {/* */}
22 |
23 |
24 | {/* */}
25 |
26 | {/* */}
27 |
28 |
29 | {/* */}
30 |
31 |
정보마당
32 |
33 |
34 | 대표제품의 소개와 대표서비스의 소개를 보실 수 있는 페이지입니다.
35 |
36 |
37 |
대표서비스 소개
38 |
39 |
40 | 전자정부 표준 프레임워크 실행환경은 5개 서비스 그룹으로 구성되며
41 | 34개 서비스를 제공한다.
42 |
43 | 실행환경 서비스 구조는 아래 그림과 같다.
44 |
45 |
46 |
화면처리
47 |
48 |
49 |
50 | 화면처리 서비스그룹은 업무처리 서비스와 사용자간의 인터페이스를
51 | 담당하는 서비스로 사용자 화면 구성 및
52 | 사용자 입력 정보 검증 등의 기능을 지원한다.
53 |
54 |
55 |
56 | Ajax Support: Ajax는 대화식 웹 애플리케이션의 제작을 위해
57 | HTML과 CSS, DOM, 자바 스크립트, XML, XSLT 등과 같은 조합을
58 | 이용하는 웹 개발 기법으로 Ajax 기능 지원을 위한 Custom Tag
59 | Library를 제공한다.
60 |
61 |
62 | Internationalization: Internationalization은 다양한 지역과
63 | 언어 환경을 지원할 수 있는 서비스로, 서버 설정 및 클라이언트
64 | 브라우저 환경에 따라 자동화된 다국어 기능을 제공한다.
65 |
66 |
67 | MVC : MVC 디자인 패턴을 적용하여 사용자 화면을 개발할 수
68 | 있도록 MVC 기반 구조를 제공한다.
69 |
70 |
71 | Security : 웹 응용프로그램 작성 시 발생될 수 있는 웹 보안상의
72 | 취약점(XSS, SQL Injection 등)에 대응하기 위한 기능을 제공한다.
73 |
74 |
75 | UI Adaptor : 화면 레이어의 구현 방식에 따라 업무로직 레이어가
76 | 변경되는 것을 막기 위해서, 업무처리 Layer에서 사용할 데이터
77 | 타입을 정의하고, 화면 레이어에서 사용하는 in/out parameter를
78 | 해당 구현 방식에 맞게 변환해주는 기능 제공한다.
79 |
80 |
81 |
82 |
83 |
업무처리
84 |
85 |
86 |
87 | 업무처리 서비스는 업무 프로그램의 업무 로직을 담당하는 서비스로
88 | 업무 흐름제어, 트랜잭션 관리, 에러 처리 등의
89 |
90 | 기능을 제공한다.
91 |
92 |
93 |
94 | Process Control : 비지니스 로직과 업무 흐름의 분리를 지원하며,
95 | XML 등의 외부 설정으로 업무흐름 구성을 제공하고, 미리 정의된
96 | 프로세스를 실행하는 기능을 제공한다.
97 |
98 |
99 | Exception Handling : 응용 프로그래밍의 수행 과정에서 발생하는
100 | 예외사항(Exception)을 처리하기 위해 표준화된 방법을 제공한다.
101 |
102 |
103 |
104 |
105 | {/* */}
106 |
107 |
108 |
109 |
110 | );
111 | }
112 |
113 | export default EgovIntroService;
114 |
--------------------------------------------------------------------------------
/src/pages/intro/EgovIntroWork.jsx:
--------------------------------------------------------------------------------
1 | import { default as EgovLeftNav } from "@/components/leftmenu/EgovLeftNavIntro";
2 |
3 | import businessIntroImg from "/assets/images/img_business_intro.png";
4 | import businessIntroImgMobile from "/assets/images/img_business_intro_m.png";
5 |
6 | function EgovIntroWork() {
7 | return (
8 |
9 |
10 | {/* */}
11 |
24 | {/* */}
25 |
26 |
27 | {/* */}
28 |
29 | {/* */}
30 |
31 |
32 | {/* */}
33 |
34 |
정보마당
35 |
36 |
37 | 대표제품의 소개와 대표서비스의 소개를 보실 수 있는 페이지입니다.
38 |
39 |
40 |
주요사업 소개
41 |
42 |
개요
43 |
44 |
45 | 전자정부 표준프레임워크는 실행환경, 개발환경, 관리환경, 운영환경
46 | 등 4개의 표준프레임워크 환경과 공통
47 |
48 | 컴포넌트로 구성된다. 전자정부 및 공공사업에서 웹 어플리케이션
49 | 시스템 구축 시 어플리케이션 아키텍처와 기본
50 | 기능 및 공통컴포넌트를 표준으로 제공하는 개발프레임워크로서 다음과
51 | 같이 실행, 개발, 운영, 관리환경과 공통
52 |
53 | 컴포넌트로 구성됨
54 |
55 |
56 |
실행 환경
57 |
58 |
59 | 전자정부 사업에서 개발하는 업무 프로그램의 실행에 필요한 공통모듈
60 | 등 업무 프로그램 개발 시 화면,서버 프로
61 |
62 | 그램, 데이터 개발을 표준화가 용이하도록 지원하는 응용프로그램 환경
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 | {/* */}
71 |
72 |
73 |
74 |
75 | );
76 | }
77 |
78 | export default EgovIntroWork;
79 |
--------------------------------------------------------------------------------
/src/pages/login/EgovLogin.jsx:
--------------------------------------------------------------------------------
1 | import { Link } from "react-router-dom";
2 |
3 | import EgovLoginContent from "@/pages/login/EgovLoginContent";
4 |
5 | import URL from "@/constants/url";
6 |
7 | function EgovLogin(props) {
8 | console.group("EgovLogin");
9 | console.log("[Start] EgovLogin ------------------------------");
10 | console.log("EgovLogin [props] : ", props);
11 |
12 | const onChangeLogin = (user) => {
13 | props.onChangeLogin(user);
14 | };
15 |
16 | console.log("------------------------------EgovLogin [End]");
17 | console.groupEnd("EgovLogin");
18 |
19 | return (
20 |
21 |
22 | {/* */}
23 |
24 |
25 |
26 |
27 | Home
28 |
29 |
30 | 로그인
31 |
32 |
33 | {/* */}
34 |
35 |
36 |
37 |
38 |
39 |
40 | );
41 | }
42 |
43 | export default EgovLogin;
44 |
--------------------------------------------------------------------------------
/src/pages/login/EgovLoginContent.jsx:
--------------------------------------------------------------------------------
1 | import { useState, useEffect, useRef } from "react";
2 | import { useLocation, useNavigate } from "react-router-dom";
3 | import * as EgovNet from "@/api/egovFetch";
4 |
5 | import URL from "@/constants/url";
6 | import CODE from "@/constants/code";
7 | import { getLocalItem, setLocalItem, setSessionItem } from "@/utils/storage";
8 | import SnsNaverBt from "@/components/sns/SnsNaverBt";
9 | import SnsKakaoBt from "@/components/sns/SnsKakaoBt";
10 |
11 | function EgovLoginContent(props) {
12 | console.group("EgovLoginContent");
13 | console.log("[Start] EgovLoginContent ------------------------------");
14 | console.log("EgovLoginContent [props] : ", props);
15 |
16 | const navigate = useNavigate();
17 | const location = useLocation();
18 | console.log("EgovLoginContent [location] : ", location);
19 |
20 | const [userInfo, setUserInfo] = useState({
21 | id: "",
22 | password: "default",
23 | userSe: "USR",
24 | });
25 | // eslint-disable-next-line no-unused-vars
26 | const [loginVO, setLoginVO] = useState({});
27 |
28 | const [saveIDFlag, setSaveIDFlag] = useState(false);
29 |
30 | const checkRef = useRef();
31 | const idRef = useRef(null); //id입력 부분에서 엔터키 이벤트 발생 확인
32 | const passwordRef = useRef(null); //비밀번호 입력 부분
33 |
34 | const KEY_ID = "KEY_ID";
35 | const KEY_SAVE_ID_FLAG = "KEY_SAVE_ID_FLAG";
36 |
37 | const handleSaveIDFlag = () => {
38 | setLocalItem(KEY_SAVE_ID_FLAG, !saveIDFlag);
39 | setSaveIDFlag(!saveIDFlag);
40 | };
41 |
42 | useEffect(() => {
43 | let idFlag = getLocalItem(KEY_SAVE_ID_FLAG);
44 | if (idFlag === null) {
45 | setSaveIDFlag(false);
46 | // eslint-disable-next-line react-hooks/exhaustive-deps
47 | idFlag = false;
48 | } else {
49 | setSaveIDFlag(idFlag);
50 | }
51 | if (idFlag === false) {
52 | setLocalItem(KEY_ID, "");
53 | checkRef.current.className = "f_chk";
54 | } else {
55 | checkRef.current.className = "f_chk on";
56 | }
57 | }, []);
58 |
59 | useEffect(() => {
60 | let data = getLocalItem(KEY_ID);
61 | if (data !== null) {
62 | setUserInfo({ id: data, password: "default", userSe: "USR" });
63 | }
64 | }, []);
65 |
66 | const activeEnter = (e) => {
67 | if (e.key === "Enter") {
68 | e.preventDefault();
69 | if (e.target === idRef.current && passwordRef.current.value === "") {
70 | //엔터 키 이벤트 발생한 입력 필드가 아이디인지 확인하기
71 | alert("비밀번호 입력 여부를 확인하여 주세요");
72 | passwordRef.current.focus();
73 | } else {
74 | submitFormHandler(e);
75 | }
76 | }
77 | };
78 | const submitFormHandler = () => {
79 | console.log("EgovLoginContent submitFormHandler()");
80 |
81 | const loginUrl = "/auth/login-jwt";
82 |
83 | const requestOptions = {
84 | method: "POST",
85 | headers: {
86 | "Content-type": "application/json",
87 | },
88 | body: JSON.stringify(userInfo),
89 | };
90 |
91 | EgovNet.requestFetch(loginUrl, requestOptions, (resp) => {
92 | let resultVO = resp.resultVO;
93 | let jToken = resp?.jToken || null;
94 |
95 | setSessionItem("jToken", jToken);
96 |
97 | if (Number(resp.resultCode) === Number(CODE.RCV_SUCCESS)) {
98 | //setLoginVO(resultVO);
99 | setSessionItem("loginUser", resultVO);
100 | props.onChangeLogin(resultVO);
101 | if (saveIDFlag) setLocalItem(KEY_ID, resultVO?.id);
102 | navigate(URL.MAIN);
103 | // PC와 Mobile 열린메뉴 닫기
104 | document.querySelector(".all_menu.WEB").classList.add("closed");
105 | document.querySelector(".btnAllMenu").classList.remove("active");
106 | document.querySelector(".btnAllMenu").title = "전체메뉴 닫힘";
107 | document.querySelector(".all_menu.Mobile").classList.add("closed");
108 | } else {
109 | alert(resp.resultMessage);
110 | }
111 | });
112 | };
113 |
114 | console.log("------------------------------EgovLoginContent [End]");
115 | console.groupEnd("EgovLoginContent");
116 |
117 | return (
118 |
119 | {/* */}
120 |
121 |
로그인
122 |
123 | 전자정부표준프레임워크 경량환경 홈페이지 로그인 페이지입니다.
124 |
125 | 로그인을 하시면 모든 서비스를 제한없이 이용하실 수 있습니다.
126 |
127 |
128 |
175 |
176 |
177 |
178 | 비밀번호는 6~12자의 영문 대/소문자, 숫자, 특수문자를 혼합해서
179 | 사용하실 수 있습니다.
180 |
181 |
182 | 쉬운 비밀번호나 자주 쓰는 사이트의 비밀번호가 같을 경우, 도용되기
183 | 쉬우므로 주기적으로 변경하셔서 사용하는 것이 좋습니다.
184 |
185 |
186 |
187 |
188 |
189 |
190 |
191 | {/* */}
192 |
193 | );
194 | }
195 |
196 | export default EgovLoginContent;
197 |
--------------------------------------------------------------------------------
/src/pages/main/EgovMain.jsx:
--------------------------------------------------------------------------------
1 | import { useState, useEffect, useCallback } from "react";
2 | import { Link, useLocation } from "react-router-dom";
3 |
4 | import * as EgovNet from "@/api/egovFetch";
5 | import URL from "@/constants/url";
6 |
7 | import simpleMainIng from "/assets/images/img_simple_main.png";
8 | import initPage from "@/js/ui";
9 |
10 | function EgovMain(props) {
11 | console.group("EgovMain");
12 | console.log("[Start] EgovMain ------------------------------");
13 | console.log("EgovMain [props] : ", props);
14 |
15 | const location = useLocation();
16 | console.log("EgovMain [location] : ", location);
17 |
18 | // eslint-disable-next-line no-unused-vars
19 | const [noticeBoard, setNoticeBoard] = useState();
20 | // eslint-disable-next-line no-unused-vars
21 | const [gallaryBoard, setGallaryBoard] = useState();
22 | const [noticeListTag, setNoticeListTag] = useState();
23 | const [gallaryListTag, setGallaryListTag] = useState();
24 |
25 | useEffect(() => {
26 | initPage();
27 | });
28 |
29 | const retrieveList = useCallback(() => {
30 | console.groupCollapsed("EgovMain.retrieveList()");
31 |
32 | const retrieveListURL = "/mainPage";
33 | const requestOptions = {
34 | method: "GET",
35 | headers: {
36 | "Content-type": "application/json",
37 | },
38 | };
39 |
40 | EgovNet.requestFetch(
41 | retrieveListURL,
42 | requestOptions,
43 | (resp) => {
44 | setNoticeBoard(resp.result.notiList);
45 | setGallaryBoard(resp.result.galList);
46 |
47 | let mutNotiListTag = [];
48 | mutNotiListTag.push(검색된 결과가 없습니다. ); // 게시판 목록 초기값
49 |
50 | // 리스트 항목 구성
51 | resp.result.notiList.forEach(function (item, index) {
52 | if (index === 0) mutNotiListTag = []; // 목록 초기화
53 | mutNotiListTag.push(
54 |
55 |
62 | {item.nttSj}
63 | {item.frstRegisterPnttm}
64 |
65 |
66 | );
67 | });
68 | setNoticeListTag(mutNotiListTag);
69 |
70 | let mutGallaryListTag = [];
71 | mutGallaryListTag.push(검색된 결과가 없습니다. ); // 게시판 목록 초기값
72 |
73 | // 리스트 항목 구성
74 | resp.result.galList.forEach(function (item, index) {
75 | if (index === 0) mutGallaryListTag = []; // 목록 초기화
76 | mutGallaryListTag.push(
77 |
78 |
85 | {item.nttSj}
86 | {item.frstRegisterPnttm}
87 |
88 |
89 | );
90 | });
91 | setGallaryListTag(mutGallaryListTag);
92 | },
93 | function (resp) {
94 | console.log("err response : ", resp);
95 | }
96 | );
97 | console.groupEnd("EgovMain.retrieveList()");
98 | }, []);
99 |
100 | useEffect(() => {
101 | retrieveList();
102 | }, [retrieveList]);
103 |
104 | console.log("------------------------------EgovMain [End]");
105 | console.groupEnd("EgovMain");
106 |
107 | return (
108 |
109 |
110 |
111 |
112 |
116 |
117 |
118 |
119 |
120 |
130 |
131 |
132 |
공지사항
133 |
134 |
135 | 더보기
136 |
137 |
138 |
139 |
140 |
갤러리
141 |
142 |
143 | 더보기
144 |
145 |
146 |
147 |
148 |
149 |
150 |
151 | 자료실
152 |
153 | 다양한 자료를
154 |
155 | 다운로드 받으실 수 있습니다.
156 |
157 |
158 |
159 | 표준프레임워크센터
160 |
161 | 표준프레임워크센터의
162 |
163 | 약도 등의 정보를 제공합니다.
164 |
165 |
166 |
167 |
168 |
169 |
170 |
171 |
172 |
173 |
주요사업 소개
174 |
175 | 표준프레임워크가 제공하는
176 |
177 | 주요 사업을 소개합니다.
178 |
179 |
180 |
자세히 보기
181 |
182 |
183 |
184 |
대표서비스 소개
185 |
186 | 표준프레임워크 실행환경의
187 |
188 | 서비스 그룹에서 제공하는
189 |
190 | 대표서비스입니다.
191 |
192 |
193 |
자세히 보기
194 |
195 |
196 |
197 |
서비스 신청
198 |
199 | 표준프레임워크 경량환경
200 |
201 | 홈페이지의 다양한 서비스를
202 |
203 | 신청 하실 수 있습니다.
204 |
205 |
206 |
자세히 보기
207 |
208 |
209 |
210 |
일정 현황
211 |
212 | 표준프레임워크 경량환경
213 |
214 | 홈페이지의 전체적인 일정
215 |
216 | 현황을 조회하실 수 있습니다.
217 |
218 |
219 |
자세히 보기
220 |
221 |
222 |
223 |
224 | );
225 | }
226 |
227 | export default EgovMain;
228 |
--------------------------------------------------------------------------------
/src/pages/support/apply/EgovSupportApply.jsx:
--------------------------------------------------------------------------------
1 | import { default as EgovLeftNav } from "@/components/leftmenu/EgovLeftNavSupport";
2 |
3 | function EgovSupportApply() {
4 | return (
5 |
6 |
7 | {/* */}
8 |
21 | {/* */}
22 |
23 |
24 | {/* */}
25 |
26 | {/* */}
27 |
28 |
29 | {/* */}
30 |
31 |
고객지원
32 |
33 |
34 | 프레임워크 경량환경의 원하시는 서비스를 신청하실 수 있습니다.
35 |
36 |
37 |
서비스 신청
38 |
39 |
주요 서비스 안내
40 |
41 |
42 | 서비스필요시 다음과 같은 절차로 신청하시면 됩니다.
43 |
44 |
45 | 1. 필요한 서비스 확인
46 |
47 |
48 | 2. 자료실에서 필요한 서비스 존재여부 확인
49 |
50 |
51 | 3. 서비스요청을 통해 필요한 서비스 신청
52 |
53 |
54 | 대표 서비스 자세히 보기
55 |
56 |
57 | {/* */}
58 |
59 |
60 |
61 |
62 | );
63 | }
64 |
65 | export default EgovSupportApply;
66 |
--------------------------------------------------------------------------------
/src/pages/support/download/EgovDownloadCreate.jsx:
--------------------------------------------------------------------------------
1 | import { Link } from "react-router-dom";
2 |
3 | import { default as EgovLeftNav } from "@/components/leftmenu/EgovLeftNavSupport";
4 | import URL from "@/constants/url";
5 |
6 | import samplePdsListImg from "/assets/images/sample_pds_list.png";
7 |
8 | function EgovDownloadCreate() {
9 | return (
10 |
11 |
12 | {/* */}
13 |
14 |
15 |
16 |
17 | Home
18 |
19 |
20 |
21 | 고객지원
22 |
23 | 소개
24 |
25 |
26 | {/* */}
27 |
28 |
29 | {/* */}
30 |
31 | {/* */}
32 |
33 |
34 | {/* */}
35 |
36 |
37 |
고객지원
38 |
39 |
40 |
자료실
41 |
본 화면은 디자인 예시임
42 |
43 | {/* */}
44 |
45 |
60 |
61 |
62 |
63 | 작성자
64 | innovate
65 |
66 |
67 | 작성일
68 | 2011-08-01 23:22:11
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 | 썸네일 이미지는
77 |
78 | width : 160px, height : 109px
79 |
80 | 크기의 이미지를 올려주세요
81 |
82 |
83 |
145 |
146 |
147 | {/* */}
148 |
149 |
150 | 자료설명 입력
151 |
152 |
153 |
154 |
161 |
162 |
163 | {/* */}
164 |
165 |
166 |
167 |
168 |
172 | 등록
173 |
174 |
175 |
176 | {/* */}
177 |
178 | {/* */}
179 |
180 |
181 |
182 |
183 | );
184 | }
185 |
186 | export default EgovDownloadCreate;
187 |
--------------------------------------------------------------------------------
/src/pages/support/download/EgovDownloadDetail.jsx:
--------------------------------------------------------------------------------
1 | import { Link } from "react-router-dom";
2 |
3 | import { default as EgovLeftNav } from "@/components/leftmenu/EgovLeftNavSupport";
4 | import URL from "@/constants/url";
5 |
6 | import samplePdsList from "/assets/images/sample_pds_list.png";
7 |
8 | function EgovDownloadDetail() {
9 | return (
10 |
11 |
12 | {/* */}
13 |
14 |
15 |
16 |
17 | Home
18 |
19 |
20 |
21 | 고객지원
22 |
23 | 소개
24 |
25 |
26 | {/* */}
27 |
28 |
29 | {/* */}
30 |
31 | {/* */}
32 |
33 |
34 | {/* */}
35 |
36 |
37 |
고객지원
38 |
39 |
40 |
자료실
41 |
본 화면은 디자인 예시임
42 |
43 | {/* */}
44 |
45 |
egovframe installer v1.03
46 |
47 |
48 |
49 | 작성자
50 | innovate
51 |
52 |
53 | 작성일
54 | 2011-08-01 23:22:11
55 |
56 |
57 |
58 |
59 |
65 |
66 |
67 | 운영체제
68 |
69 | Win95/Win98/WinME/WinNT/Win2000/WinXP/WinVISTA/Win7/
70 |
71 |
72 |
73 | 권장사양
74 | 펜티엄3
75 |
76 |
77 | 파일정보
78 |
79 | 7MB (총 1 개)/ egovframework-common-all.zip [15,083,713
80 | byte]
81 |
82 |
83 |
84 | 등록일자
85 | 2011-08-08 11:11:11
86 |
87 |
88 | 언어
89 | 영어
90 |
91 |
92 |
93 |
94 | {/* */}
95 |
96 |
자료 상세설명
97 |
98 |
99 | 안녕하세요.. 공통컴포넌트 전체 소스입니다. 관련된 내용은 다음
100 | 가이드를 참조하십시오.
101 | http://www.egovframe.go.kr/wiki/doku.php?id=
102 | egovframework:com:v3:init_guide 감사합니다.
103 |
104 |
105 | {/* */}
106 |
107 |
108 |
109 |
110 |
114 | 목록
115 |
116 |
117 |
118 | {/* */}
119 |
120 |
121 |
122 | 이전글
123 |
124 | egovframe installer v1.03
125 |
126 |
127 |
128 | 다음글
129 |
130 | egovframe installer v1.03
131 |
132 |
133 |
134 |
135 | {/* */}
136 |
137 |
138 |
139 |
140 | );
141 | }
142 |
143 | export default EgovDownloadDetail;
144 |
--------------------------------------------------------------------------------
/src/pages/support/qna/EgovQnaDetail.jsx:
--------------------------------------------------------------------------------
1 | import { Link } from "react-router-dom";
2 |
3 | import { default as EgovLeftNav } from "@/components/leftmenu/EgovLeftNavSupport";
4 |
5 | function EgovQnaDetail() {
6 | return (
7 |
8 |
9 | {/* */}
10 |
11 |
12 |
13 |
14 | Home
15 |
16 |
17 |
18 | 고객지원
19 |
20 | 소개
21 |
22 |
23 | {/* */}
24 |
25 |
26 | {/* */}
27 |
28 | {/* */}
29 |
30 |
31 | {/* */}
32 |
33 |
34 |
고객지원
35 |
36 |
37 |
Q&A 상세조회
38 |
본 화면은 디자인 예시임
39 |
40 |
41 |
42 | 제목
43 | jsp파일을 못찼습니다.
44 |
45 |
46 | 이메일
47 | abc@nate.com
48 |
49 |
50 | 이메일답변여부
51 | 답변요청
52 |
53 |
54 | 등록일자
55 | 2011-08-08 11:11:11
56 |
57 |
58 | 작성자
59 | 박성환
60 |
61 |
62 | 전화
63 | 000-000-0000
64 |
65 |
66 | 작성일
67 | 2011-08-08
68 |
69 |
70 | 조회
71 | 100
72 |
73 |
74 | 처리상태
75 | 접수대기
76 |
77 |
78 | 첨부파일
79 |
80 |
81 | file_name.hwp [3626] byte
82 |
83 |
84 |
85 |
86 |
87 | Q
88 | 안녕하세요 웹호스팅에 올렸더니 jsp파일에서 이런에러로그가
89 | 남았는데요 jsp파일을 못찾는것같습니다? xml을 수정해야하나요?
90 |
91 | 심각: Servlet.service() for servlet action threw exception
92 |
93 | javax.servlet.ServletException: Could not get RequestDispatcher
94 | for [/WEB-INF/jsp/egovframework//main/main.jsp]: check that this
95 | file exists within your WAR
96 |
97 | at
98 | org.springframework.web.servlet.view.InternalResourceView.renderMergedOutputModel(InternalResourceView.java:217)
99 |
100 |
101 |
A
102 |
103 |
104 | chanjin님의 답변 2011-08-08 12:33:33
105 | 심각: Servlet.service() for servlet action threw exception은
106 | jsp파일을 열어서 보셔야합니다. javax.servlet.ServletException:
107 | Could not get RequestDispatcher for
108 | [/WEB-INF/jsp/egovframework//main/main.jsp]: check that this
109 | file exists within your WAR
110 |
111 | Delete
112 |
113 |
114 |
115 | sunrise님의 답변 2011-08-07 11:11:11
116 | tomcat서버를 재시동해보세요. 전 그렇게 하니깐 되던데요.
117 |
118 | Delete
119 |
120 |
121 |
122 | auto님의 답변 2011-08-07 11:11:11
123 | 제가 살펴볼께요 메일로 주세요. test@naver.com
124 |
125 | Delete
126 |
127 |
128 |
129 |
130 |
131 | {/* */}
132 |
133 |
134 |
답변달기
135 |
136 |
143 |
144 |
145 |
150 |
151 | {/* */}
152 |
153 | {/* */}
154 |
155 |
156 |
157 |
158 | );
159 | }
160 |
161 | export default EgovQnaDetail;
162 |
--------------------------------------------------------------------------------
/src/pages/support/qna/EgovQnaList.jsx:
--------------------------------------------------------------------------------
1 | import { Link } from "react-router-dom";
2 |
3 | import { default as EgovLeftNav } from "@/components/leftmenu/EgovLeftNavSupport";
4 | import URL from "@/constants/url";
5 |
6 | function EgovQnaList() {
7 | return (
8 |
9 |
10 | {/* */}
11 |
12 |
13 |
14 |
15 | Home
16 |
17 |
18 |
19 | 고객지원
20 |
21 | 소개
22 |
23 |
24 | {/* */}
25 |
26 |
27 | {/* */}
28 |
29 | {/* */}
30 |
31 |
32 | {/* */}
33 |
34 |
35 |
고객지원
36 |
37 |
38 |
묻고답하기(Q&A)
39 |
본 화면은 디자인 예시임
40 |
41 | {/* */}
42 |
67 | {/* */}
68 |
69 | {/* */}
70 |
71 |
72 | 번호
73 | 제목
74 | 작성자
75 | 조회수
76 | 등록일
77 |
78 |
79 | {/* */}
80 | {/*
검색된 결과가 없습니다.
*/}
81 |
82 | {/* */}
83 |
84 |
3
85 |
86 | 공통컴포넌트 중 모니터링 관련 서비스 실행시 오류가
87 | 발생합니다(15)
88 |
89 |
홍길동
90 |
3
91 |
2021-7-24
92 |
93 |
94 |
2
95 |
96 | validation 처리 시.패스워드에 대한 메소드를 찾지 못합니다.
97 |
98 |
홍길동
99 |
3
100 |
2021-7-24
101 |
102 |
103 |
1
104 |
105 | 공통컴포넌트 중 모니터링 관련 서비스 실행시 오류가
106 | 발생합니다.
107 |
108 |
홍길동
109 |
3
110 |
2021-7-24
111 |
112 |
113 |
114 | {/* */}
115 |
116 |
117 | {/* */}
118 |
119 |
120 |
121 |
122 | 처음
123 |
124 |
125 |
126 |
127 | 이전
128 |
129 |
130 |
131 |
132 | 1
133 |
134 |
135 |
136 | 2
137 |
138 |
139 | 3
140 |
141 |
142 | 4
143 |
144 |
145 | 5
146 |
147 |
148 |
149 | 다음
150 |
151 |
152 |
153 |
154 | 마지막
155 |
156 |
157 |
158 |
159 | {/* */}
160 |
161 |
162 | {/* */}
163 |
164 |
165 |
166 |
167 | );
168 | }
169 |
170 | export default EgovQnaList;
171 |
--------------------------------------------------------------------------------
/src/reportWebVitals.js:
--------------------------------------------------------------------------------
1 | const reportWebVitals = onPerfEntry => {
2 | if (onPerfEntry && onPerfEntry instanceof Function) {
3 | import('web-vitals').then(({ getCLS, getFID, getFCP, getLCP, getTTFB }) => {
4 | getCLS(onPerfEntry);
5 | getFID(onPerfEntry);
6 | getFCP(onPerfEntry);
7 | getLCP(onPerfEntry);
8 | getTTFB(onPerfEntry);
9 | });
10 | }
11 | };
12 |
13 | export default reportWebVitals;
14 |
--------------------------------------------------------------------------------
/src/utils/bbsFormVaildator.js:
--------------------------------------------------------------------------------
1 | const bbsFormVaildator = (formData) => {
2 | if (formData.get('nttSj') === null || formData.get('nttSj') === "") {
3 | alert("제목은 필수 값입니다.");
4 | return false;
5 | }
6 | if (formData.get('nttCn') === null || formData.get('nttCn') === "") {
7 | alert("내용은 필수 값입니다.");
8 | return false;
9 | }
10 | return true;
11 | };
12 |
13 | export default bbsFormVaildator;
--------------------------------------------------------------------------------
/src/utils/bbsFormVaildator.jsx:
--------------------------------------------------------------------------------
1 | const bbsFormVaildator = (formData) => {
2 | if (formData.get("nttSj") === null || formData.get("nttSj") === "") {
3 | alert("제목은 필수 값입니다.");
4 | return false;
5 | }
6 | if (formData.get("nttCn") === null || formData.get("nttCn") === "") {
7 | alert("내용은 필수 값입니다.");
8 | return false;
9 | }
10 | return true;
11 | };
12 |
13 | export default bbsFormVaildator;
14 |
--------------------------------------------------------------------------------
/src/utils/calc.js:
--------------------------------------------------------------------------------
1 | export const itemIdxByPage = (resultCnt, currentPageNo, pageSize, index) => resultCnt + 1 - ((currentPageNo - 1) * pageSize + index + 1);
--------------------------------------------------------------------------------
/src/utils/calc.jsx:
--------------------------------------------------------------------------------
1 | export const itemIdxByPage = (resultCnt, currentPageNo, pageSize, index) => resultCnt + 1 - ((currentPageNo - 1) * pageSize + index + 1);
--------------------------------------------------------------------------------
/src/utils/storage.js:
--------------------------------------------------------------------------------
1 | function getItem(storage, key) {
2 | const jsonStr = storage.getItem(key);
3 | if (!jsonStr) return null;
4 | return JSON.parse(jsonStr);
5 | }
6 |
7 | function setItem(storage, key, value) {
8 | const str = (value === undefined) ? null : value;
9 | storage.setItem(key, JSON.stringify(str));
10 | }
11 |
12 | function removeItem(storage, key) {
13 | storage.removeItem(key);
14 | }
15 |
16 | export function getLocalItem(key) {
17 | return getItem(localStorage, key);
18 | }
19 |
20 | export function setLocalItem(key, value) {
21 | setItem(localStorage, key, value);
22 | }
23 |
24 | export function removeLocalItem(key) {
25 | removeItem(localStorage, key);
26 | }
27 |
28 | export function getSessionItem(key) {
29 | return getItem(sessionStorage, key);
30 | }
31 |
32 | export function setSessionItem(key, value) {
33 | setItem(sessionStorage, key, value);
34 | }
35 |
36 | export function removeSessionItem(key) {
37 | removeItem(sessionStorage, key);
38 | }
--------------------------------------------------------------------------------
/vite.config.js:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/eGovFramework/egovframe-template-simple-react/e6e9ef0391cea902b99141c20fafbc08d121425c/vite.config.js
--------------------------------------------------------------------------------
/vitest.setup.js:
--------------------------------------------------------------------------------
1 | import "@testing-library/jest-dom"; // 테스트에서 커스텀 매처 사용
2 | import { vi } from 'vitest';
3 |
4 | // Mock fetch API for tests
5 | global.fetch = vi.fn(() =>
6 | Promise.resolve({
7 | json: () =>
8 | Promise.resolve({
9 | resultCode: 0,
10 | result: {
11 | notiList: [],
12 | galList: []
13 | }
14 | })
15 | })
16 | );
17 |
--------------------------------------------------------------------------------