From d5f5d008035c0e11129ad66e500d6bd65515736f Mon Sep 17 00:00:00 2001 From: luckyboy07 Date: Sun, 18 Aug 2024 05:53:44 +0800 Subject: [PATCH 1/3] first commit --- .env | 1 + .eslintrc.cjs | 15 +++ .gitignore | 66 +++++-------- .prettierrc.json | 8 ++ env.d.ts | 1 + index.html | 13 +++ package.json | 37 +++++++ postcss.config.cjs | 7 ++ public/favicon.ico | Bin 0 -> 4286 bytes src/App.vue | 11 +++ src/assets/base.css | 86 ++++++++++++++++ src/assets/logo.svg | 1 + src/assets/main.css | 27 ++++++ src/assets/tailwind.css | 81 ++++++++++++++++ src/components/Accordion/AccordionItem.vue | 79 +++++++++++++++ src/components/Accordion/ArrowIcon.vue | 34 +++++++ src/components/Card/Card.vue | 28 ++++++ src/components/Card/CardItem.vue | 78 +++++++++++++++ src/components/ExerciseOne/BannerImage.css | 31 ++++++ src/components/ExerciseOne/BannerImage.vue | 19 ++++ src/components/ExerciseOne/ListSection.vue | 12 +++ src/components/ExerciseTwo/MobileView.vue | 31 ++++++ src/components/ExerciseTwo/TabDisplay.css | 46 +++++++++ src/components/ExerciseTwo/TabDisplay.vue | 31 ++++++ src/components/NavLink/FloatingLink.vue | 38 ++++++++ src/components/Tab/TabContent.vue | 24 +++++ src/components/Tab/TabNavigation.vue | 108 +++++++++++++++++++++ src/components/icons/IconCommunity.vue | 7 ++ src/components/icons/IconDocumentation.vue | 7 ++ src/components/icons/IconEcosystem.vue | 7 ++ src/components/icons/IconSupport.vue | 7 ++ src/components/icons/IconTooling.vue | 19 ++++ src/composable/useBreakpoint.ts | 30 ++++++ src/constants/data.json | 18 ++++ src/constants/listSection.json | 19 ++++ src/main.ts | 11 +++ src/router/index.ts | 24 +++++ src/types/dataTypes.ts | 11 +++ src/views/ExerciseOne.vue | 17 ++++ src/views/ExerciseTwo.vue | 25 +++++ tailwind.config.js | 9 ++ tsconfig.app.json | 14 +++ tsconfig.json | 11 +++ tsconfig.node.json | 19 ++++ vite.config.ts | 16 +++ 45 files changed, 1144 insertions(+), 40 deletions(-) create mode 100644 .env create mode 100644 .eslintrc.cjs create mode 100644 .prettierrc.json create mode 100644 env.d.ts create mode 100644 index.html create mode 100644 package.json create mode 100644 postcss.config.cjs create mode 100644 public/favicon.ico create mode 100644 src/App.vue create mode 100644 src/assets/base.css create mode 100644 src/assets/logo.svg create mode 100644 src/assets/main.css create mode 100644 src/assets/tailwind.css create mode 100644 src/components/Accordion/AccordionItem.vue create mode 100644 src/components/Accordion/ArrowIcon.vue create mode 100644 src/components/Card/Card.vue create mode 100644 src/components/Card/CardItem.vue create mode 100644 src/components/ExerciseOne/BannerImage.css create mode 100644 src/components/ExerciseOne/BannerImage.vue create mode 100644 src/components/ExerciseOne/ListSection.vue create mode 100644 src/components/ExerciseTwo/MobileView.vue create mode 100644 src/components/ExerciseTwo/TabDisplay.css create mode 100644 src/components/ExerciseTwo/TabDisplay.vue create mode 100644 src/components/NavLink/FloatingLink.vue create mode 100644 src/components/Tab/TabContent.vue create mode 100644 src/components/Tab/TabNavigation.vue create mode 100644 src/components/icons/IconCommunity.vue create mode 100644 src/components/icons/IconDocumentation.vue create mode 100644 src/components/icons/IconEcosystem.vue create mode 100644 src/components/icons/IconSupport.vue create mode 100644 src/components/icons/IconTooling.vue create mode 100644 src/composable/useBreakpoint.ts create mode 100644 src/constants/data.json create mode 100644 src/constants/listSection.json create mode 100644 src/main.ts create mode 100644 src/router/index.ts create mode 100644 src/types/dataTypes.ts create mode 100644 src/views/ExerciseOne.vue create mode 100644 src/views/ExerciseTwo.vue create mode 100644 tailwind.config.js create mode 100644 tsconfig.app.json create mode 100644 tsconfig.json create mode 100644 tsconfig.node.json create mode 100644 vite.config.ts diff --git a/.env b/.env new file mode 100644 index 000000000..8926f94f6 --- /dev/null +++ b/.env @@ -0,0 +1 @@ +BASE_URL=http://localhost:8080 \ No newline at end of file diff --git a/.eslintrc.cjs b/.eslintrc.cjs new file mode 100644 index 000000000..6f40582dd --- /dev/null +++ b/.eslintrc.cjs @@ -0,0 +1,15 @@ +/* eslint-env node */ +require('@rushstack/eslint-patch/modern-module-resolution') + +module.exports = { + root: true, + 'extends': [ + 'plugin:vue/vue3-essential', + 'eslint:recommended', + '@vue/eslint-config-typescript', + '@vue/eslint-config-prettier/skip-formatting' + ], + parserOptions: { + ecmaVersion: 'latest' + } +} diff --git a/.gitignore b/.gitignore index 2f17e952b..ee107188d 100644 --- a/.gitignore +++ b/.gitignore @@ -1,44 +1,30 @@ -# Compiled source # -################### -*.com -*.class -*.dll -*.exe -*.o -*.so - -# Packages # -############ -# it's better to unpack these files and commit the raw source -# git has its own built in compression methods -*.7z -*.dmg -*.gz -*.iso -*.jar -*.rar -*.tar -*.zip - -# Logs and databases # -###################### +# Logs +logs *.log -*.sql -*.sqlite +npm-debug.log* +yarn-debug.log* +yarn-error.log* +pnpm-debug.log* +lerna-debug.log* -# OS generated files # -###################### +node_modules .DS_Store -.DS_Store? -._* -.Spotlight-V100 -.Trashes -Icon? -ehthumbs.db -Thumbs.db +dist +dist-ssr +coverage +*.local +package-lock.json +/cypress/videos/ +/cypress/screenshots/ -# Custom # -###################### -*.sass-cache* -node_modules -/.idea \ No newline at end of file +# Editor directories and files +.vscode/* +!.vscode/extensions.json +.idea +*.suo +*.ntvs* +*.njsproj +*.sln +*.sw? + +*.tsbuildinfo \ No newline at end of file diff --git a/.prettierrc.json b/.prettierrc.json new file mode 100644 index 000000000..66e23359c --- /dev/null +++ b/.prettierrc.json @@ -0,0 +1,8 @@ +{ + "$schema": "https://json.schemastore.org/prettierrc", + "semi": false, + "tabWidth": 2, + "singleQuote": true, + "printWidth": 100, + "trailingComma": "none" +} \ No newline at end of file diff --git a/env.d.ts b/env.d.ts new file mode 100644 index 000000000..11f02fe2a --- /dev/null +++ b/env.d.ts @@ -0,0 +1 @@ +/// diff --git a/index.html b/index.html new file mode 100644 index 000000000..a88854489 --- /dev/null +++ b/index.html @@ -0,0 +1,13 @@ + + + + + + + Vite App + + +
+ + + diff --git a/package.json b/package.json new file mode 100644 index 000000000..30ea21e5b --- /dev/null +++ b/package.json @@ -0,0 +1,37 @@ +{ + "name": "frontend-assessment", + "version": "0.0.0", + "private": true, + "type": "module", + "scripts": { + "dev": "vite", + "build": "run-p type-check \"build-only {@}\" --", + "preview": "vite preview", + "build-only": "vite build", + "type-check": "vue-tsc --build --force", + "lint": "eslint . --ext .vue,.js,.jsx,.cjs,.mjs,.ts,.tsx,.cts,.mts --fix --ignore-path .gitignore", + "format": "prettier --write src/" + }, + "dependencies": { + "autoprefixer": "^10.4.20", + "vue": "^3.4.29", + "vue-router": "^4.3.3" + }, + "devDependencies": { + "@rushstack/eslint-patch": "^1.8.0", + "@tsconfig/node20": "^20.1.4", + "@types/node": "^20.14.5", + "@vitejs/plugin-vue": "^5.0.5", + "@vue/eslint-config-prettier": "^9.0.0", + "@vue/eslint-config-typescript": "^13.0.0", + "@vue/tsconfig": "^0.5.1", + "eslint": "^8.57.0", + "eslint-plugin-vue": "^9.23.0", + "npm-run-all2": "^6.2.0", + "prettier": "^3.2.5", + "tailwindcss": "^3.4.10", + "typescript": "~5.4.0", + "vite": "^5.3.1", + "vue-tsc": "^2.0.21" + } +} diff --git a/postcss.config.cjs b/postcss.config.cjs new file mode 100644 index 000000000..01e85bd0d --- /dev/null +++ b/postcss.config.cjs @@ -0,0 +1,7 @@ +// TODO check why ES6 syntax is not working +const autoprefixer = require('autoprefixer') +const tailwindcss = require('tailwindcss') + +module.exports = { + plugins: [tailwindcss, autoprefixer] +} diff --git a/public/favicon.ico b/public/favicon.ico new file mode 100644 index 0000000000000000000000000000000000000000..df36fcfb72584e00488330b560ebcf34a41c64c2 GIT binary patch literal 4286 zcmds*O-Phc6o&64GDVCEQHxsW(p4>LW*W<827=Unuo8sGpRux(DN@jWP-e29Wl%wj zY84_aq9}^Am9-cWTD5GGEo#+5Fi2wX_P*bo+xO!)p*7B;iKlbFd(U~_d(U?#hLj56 zPhFkj-|A6~Qk#@g^#D^U0XT1cu=c-vu1+SElX9NR;kzAUV(q0|dl0|%h|dI$%VICy zJnu2^L*Te9JrJMGh%-P79CL0}dq92RGU6gI{v2~|)p}sG5x0U*z<8U;Ij*hB9z?ei z@g6Xq-pDoPl=MANPiR7%172VA%r)kevtV-_5H*QJKFmd;8yA$98zCxBZYXTNZ#QFk2(TX0;Y2dt&WitL#$96|gJY=3xX zpCoi|YNzgO3R`f@IiEeSmKrPSf#h#Qd<$%Ej^RIeeYfsxhPMOG`S`Pz8q``=511zm zAm)MX5AV^5xIWPyEu7u>qYs?pn$I4nL9J!=K=SGlKLXpE<5x+2cDTXq?brj?n6sp= zphe9;_JHf40^9~}9i08r{XM$7HB!`{Ys~TK0kx<}ZQng`UPvH*11|q7&l9?@FQz;8 zx!=3<4seY*%=OlbCbcae?5^V_}*K>Uo6ZWV8mTyE^B=DKy7-sdLYkR5Z?paTgK-zyIkKjIcpyO z{+uIt&YSa_$QnN_@t~L014dyK(fOOo+W*MIxbA6Ndgr=Y!f#Tokqv}n<7-9qfHkc3 z=>a|HWqcX8fzQCT=dqVbogRq!-S>H%yA{1w#2Pn;=e>JiEj7Hl;zdt-2f+j2%DeVD zsW0Ab)ZK@0cIW%W7z}H{&~yGhn~D;aiP4=;m-HCo`BEI+Kd6 z={Xwx{TKxD#iCLfl2vQGDitKtN>z|-AdCN|$jTFDg0m3O`WLD4_s#$S literal 0 HcmV?d00001 diff --git a/src/App.vue b/src/App.vue new file mode 100644 index 000000000..41dc47f93 --- /dev/null +++ b/src/App.vue @@ -0,0 +1,11 @@ + + + diff --git a/src/assets/base.css b/src/assets/base.css new file mode 100644 index 000000000..8816868a4 --- /dev/null +++ b/src/assets/base.css @@ -0,0 +1,86 @@ +/* color palette from */ +:root { + --vt-c-white: #ffffff; + --vt-c-white-soft: #f8f8f8; + --vt-c-white-mute: #f2f2f2; + + --vt-c-black: #181818; + --vt-c-black-soft: #222222; + --vt-c-black-mute: #282828; + + --vt-c-indigo: #2c3e50; + + --vt-c-divider-light-1: rgba(60, 60, 60, 0.29); + --vt-c-divider-light-2: rgba(60, 60, 60, 0.12); + --vt-c-divider-dark-1: rgba(84, 84, 84, 0.65); + --vt-c-divider-dark-2: rgba(84, 84, 84, 0.48); + + --vt-c-text-light-1: var(--vt-c-indigo); + --vt-c-text-light-2: rgba(60, 60, 60, 0.66); + --vt-c-text-dark-1: var(--vt-c-white); + --vt-c-text-dark-2: rgba(235, 235, 235, 0.64); +} + +/* semantic color variables for this project */ +:root { + --color-background: var(--vt-c-white); + --color-background-soft: var(--vt-c-white-soft); + --color-background-mute: var(--vt-c-white-mute); + + --color-border: var(--vt-c-divider-light-2); + --color-border-hover: var(--vt-c-divider-light-1); + + --color-heading: var(--vt-c-text-light-1); + --color-text: var(--vt-c-text-light-1); + + --section-gap: 160px; +} + +@media (prefers-color-scheme: dark) { + :root { + --color-background: var(--vt-c-black); + --color-background-soft: var(--vt-c-black-soft); + --color-background-mute: var(--vt-c-black-mute); + + --color-border: var(--vt-c-divider-dark-2); + --color-border-hover: var(--vt-c-divider-dark-1); + + --color-heading: var(--vt-c-text-dark-1); + --color-text: var(--vt-c-text-dark-2); + } +} + +*, +*::before, +*::after { + box-sizing: border-box; + margin: 0; + font-weight: normal; +} + +body { + min-height: 100vh; + color: var(--color-text); + background: var(--color-background); + transition: + color 0.5s, + background-color 0.5s; + line-height: 1.6; + font-family: + Inter, + -apple-system, + BlinkMacSystemFont, + 'Segoe UI', + Roboto, + Oxygen, + Ubuntu, + Cantarell, + 'Fira Sans', + 'Droid Sans', + 'Helvetica Neue', + sans-serif; + font-size: 15px; + text-rendering: optimizeLegibility; + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; +} diff --git a/src/assets/logo.svg b/src/assets/logo.svg new file mode 100644 index 000000000..756566035 --- /dev/null +++ b/src/assets/logo.svg @@ -0,0 +1 @@ + diff --git a/src/assets/main.css b/src/assets/main.css new file mode 100644 index 000000000..cf5a0512f --- /dev/null +++ b/src/assets/main.css @@ -0,0 +1,27 @@ +@import './base.css'; + +#app { + /* max-width: 1280px; */ + margin: 0 auto; + /* padding: 2rem; */ + font-weight: normal; +} +body { + background-color: #fff; + height: auto; + font-family: sans-serif; +} + +@media (min-width: 1024px) { + /* body { + display: flex; + place-items: center; + } +*/ + #app { + width: 100%; + /* display: grid; + grid-template-columns: 1fr 1fr; */ + /* padding: 0 2rem; */ + } +} diff --git a/src/assets/tailwind.css b/src/assets/tailwind.css new file mode 100644 index 000000000..d04b1c64c --- /dev/null +++ b/src/assets/tailwind.css @@ -0,0 +1,81 @@ +@tailwind base; +@tailwind components; +@tailwind utilities; +/* Move style into different place */ + +html, body { + height: 100%; +} + +#app { + height: 100%; +} + +.five-pointed-star { + --star-color: #fff; + margin: 1em auto; + font-size: 1em; + position: relative; + display: block; + width: 0px; + height: 0px; + border-right: 1em solid transparent; + border-bottom: 0.7em solid var(--star-color); + border-left: 1em solid transparent; + transform: rotate(35deg); + } + .five-pointed-star:before { + border-bottom: 0.8em solid var(--star-color); + border-left: 0.3em solid transparent; + border-right: 0.3em solid transparent; + position: absolute; + height: 0; + width: 0; + top: -0.45em; + left: -0.65em; + display: block; + content:""; + transform: rotate(-35deg); + } + .five-pointed-star:after { + position: absolute; + display: block; + top: 0.03em; + left: -1.05em; + width: 0; + height: 0; + border-right: 1em solid transparent; + border-bottom: 0.7em solid var(--star-color); + border-left: 1em solid transparent; + transform: rotate(-70deg); + content:""; + } + +.article-thumbnail-star { + font-size: 0.7em !important; +} +h1 { + font-size: 1.9em; + font-weight: bold; +} +h2 { + font-size: 1.5em; + font-weight: bold; +} + +h3 { + font-size: 1.17em; + font-weight: bold; +} + +h4 { + font-weight: bold; +} +h5 { + font-size: 0.83em; + font-weight: bold; +} +h6 { + font-size: 0.67em; + font-weight: bold; +} \ No newline at end of file diff --git a/src/components/Accordion/AccordionItem.vue b/src/components/Accordion/AccordionItem.vue new file mode 100644 index 000000000..ba48a05ef --- /dev/null +++ b/src/components/Accordion/AccordionItem.vue @@ -0,0 +1,79 @@ + + + + + diff --git a/src/components/Accordion/ArrowIcon.vue b/src/components/Accordion/ArrowIcon.vue new file mode 100644 index 000000000..6d276ee67 --- /dev/null +++ b/src/components/Accordion/ArrowIcon.vue @@ -0,0 +1,34 @@ + + + diff --git a/src/components/Card/Card.vue b/src/components/Card/Card.vue new file mode 100644 index 000000000..fd7c22b02 --- /dev/null +++ b/src/components/Card/Card.vue @@ -0,0 +1,28 @@ + + + + diff --git a/src/components/Card/CardItem.vue b/src/components/Card/CardItem.vue new file mode 100644 index 000000000..6f38aee95 --- /dev/null +++ b/src/components/Card/CardItem.vue @@ -0,0 +1,78 @@ + + + diff --git a/src/components/ExerciseOne/BannerImage.css b/src/components/ExerciseOne/BannerImage.css new file mode 100644 index 000000000..04dd0e7fe --- /dev/null +++ b/src/components/ExerciseOne/BannerImage.css @@ -0,0 +1,31 @@ +.banner { + @apply bg-cover bg-center h-[320px]; + background-image: url(https://via.placeholder.com/600x600); + } + + h1 { + @apply text-5xl tracking-widest font-bold; + line-height: 1.8; + } + + h2 { + @apply text-[1.5rem] mb-0; + letter-spacing: 0.13rem; + } + + /* Medium devices (tablets, 768px and up) */ + @media (min-width: 768px) { + .banner { + @apply h-[570px]; + background-image: url(https://via.placeholder.com/1920x650); + } + + h1 { + @apply text-[4rem]; + } + + h2 { + @apply text-[2.3rem]; + letter-spacing: 0.17rem; + } + } \ No newline at end of file diff --git a/src/components/ExerciseOne/BannerImage.vue b/src/components/ExerciseOne/BannerImage.vue new file mode 100644 index 000000000..ecf6f623c --- /dev/null +++ b/src/components/ExerciseOne/BannerImage.vue @@ -0,0 +1,19 @@ + + + + diff --git a/src/components/Tab/TabNavigation.vue b/src/components/Tab/TabNavigation.vue new file mode 100644 index 000000000..0d7485066 --- /dev/null +++ b/src/components/Tab/TabNavigation.vue @@ -0,0 +1,108 @@ + + + + + diff --git a/src/components/icons/IconCommunity.vue b/src/components/icons/IconCommunity.vue new file mode 100644 index 000000000..2dc8b0552 --- /dev/null +++ b/src/components/icons/IconCommunity.vue @@ -0,0 +1,7 @@ + diff --git a/src/components/icons/IconDocumentation.vue b/src/components/icons/IconDocumentation.vue new file mode 100644 index 000000000..6d4791cfb --- /dev/null +++ b/src/components/icons/IconDocumentation.vue @@ -0,0 +1,7 @@ + diff --git a/src/components/icons/IconEcosystem.vue b/src/components/icons/IconEcosystem.vue new file mode 100644 index 000000000..c3a4f078c --- /dev/null +++ b/src/components/icons/IconEcosystem.vue @@ -0,0 +1,7 @@ + diff --git a/src/components/icons/IconSupport.vue b/src/components/icons/IconSupport.vue new file mode 100644 index 000000000..7452834d3 --- /dev/null +++ b/src/components/icons/IconSupport.vue @@ -0,0 +1,7 @@ + diff --git a/src/components/icons/IconTooling.vue b/src/components/icons/IconTooling.vue new file mode 100644 index 000000000..660598d7c --- /dev/null +++ b/src/components/icons/IconTooling.vue @@ -0,0 +1,19 @@ + + diff --git a/src/composable/useBreakpoint.ts b/src/composable/useBreakpoint.ts new file mode 100644 index 000000000..930cdc0e7 --- /dev/null +++ b/src/composable/useBreakpoint.ts @@ -0,0 +1,30 @@ +import { ref, computed, onMounted, onUnmounted } from 'vue' +import type { Ref } from 'vue' + +interface BreakpointData { + isMobile: Readonly> +} + +const mobileBreakpoint = 768 //(in pixel) + +export function useBreakpoint(): BreakpointData { + const width = ref(window.innerWidth) + + const updateWidth = (): void => { + width.value = window.innerWidth + } + + onMounted(() => { + window.addEventListener('resize', updateWidth) + }) + + onUnmounted(() => { + window.removeEventListener('resize', updateWidth) + }) + + const isMobile = computed(() => width.value < mobileBreakpoint) + + return { + isMobile + } +} diff --git a/src/constants/data.json b/src/constants/data.json new file mode 100644 index 000000000..b6e5442f8 --- /dev/null +++ b/src/constants/data.json @@ -0,0 +1,18 @@ +[ + { + "title": "Section 1", + "content": "

Maecenas nec semper ante, pellentesque posuere lorem. Nullam ipsum massa, consequat eget urna ut, pulvinar dignissim lorem. Nulla facilisi. Nam mattis eleifend metus. Fusce at commodo lorem. Orci varius natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. Phasellus pellentesque elit sem, vel blandit posuere.

" + }, + { + "title": "Section 2", + "content": "

Mauris a orci sodales, scelerisque velit vitae, gravida nisl. Ut non laoreet eros, vel laoreet nisi. Praesent sed dolor dui. Proin non fringilla quam. Aliquam erat volutpat. Vestibulum vel arcu semper, lobortis turpis ac, ultricies nisi. Praesent id.

" + }, + { + "title": "Section 3", + "content": "

Sed elementum sapien ut sapien imperdiet, eu venenatis enim rhoncus. Praesent euismod tincidunt rhoncus. Duis cras amet:

  • List item one
  • List item two
  • List item three
" + }, + { + "title": "Section 4", + "content": "

Cras dictum. Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae; Aenean lacinia mauris vel est.

Suspendisse eu nisl. Nullam ut libero. Integer dignissim consequat lectus. Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos himenaeos.

" + } +] diff --git a/src/constants/listSection.json b/src/constants/listSection.json new file mode 100644 index 000000000..cc4c72c4f --- /dev/null +++ b/src/constants/listSection.json @@ -0,0 +1,19 @@ +[ + { + "id": 1, + "description": "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim adminim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.", + "imageUrl": "https://via.placeholder.com/400x300" + }, + { + "id": 2, + "description": "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim adminim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.", + + "imageUrl": "https://via.placeholder.com/400x300" + }, + { + "id": 3, + "description": "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim adminim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.", + + "imageUrl": "https://via.placeholder.com/400x300" + } +] diff --git a/src/main.ts b/src/main.ts new file mode 100644 index 000000000..18a832b11 --- /dev/null +++ b/src/main.ts @@ -0,0 +1,11 @@ +import './assets/main.css' +import './assets/tailwind.css' +import { createApp } from 'vue' +import App from './App.vue' +import router from './router' + +const app = createApp(App) + +app.use(router) + +app.mount('#app') diff --git a/src/router/index.ts b/src/router/index.ts new file mode 100644 index 000000000..ad41ca32c --- /dev/null +++ b/src/router/index.ts @@ -0,0 +1,24 @@ +import { createRouter, createWebHistory } from 'vue-router' +import ExerciseOne from '../views/ExerciseOne.vue' +import ExerciseTwo from '../views/ExerciseTwo.vue' + +const router = createRouter({ + history: createWebHistory(import.meta.env.BASE_URL), + routes: [ + { + path: '/', + name: 'ExerciseOne', + component: ExerciseOne + }, + { + path: '/exercise-two', + name: 'ExerciseTwo', + // route level code-splitting + // this generates a separate chunk (About.[hash].js) for this route + // which is lazy-loaded when the route is visited. + component: ExerciseTwo + } + ] +}) + +export default router diff --git a/src/types/dataTypes.ts b/src/types/dataTypes.ts new file mode 100644 index 000000000..8326acf9c --- /dev/null +++ b/src/types/dataTypes.ts @@ -0,0 +1,11 @@ +export interface DataItem { + title: string + content: string +} +export interface CardItem { + description: string + imageUrl: string + id: number +} + +export type CardType = CardItem[] diff --git a/src/views/ExerciseOne.vue b/src/views/ExerciseOne.vue new file mode 100644 index 000000000..ce7c74072 --- /dev/null +++ b/src/views/ExerciseOne.vue @@ -0,0 +1,17 @@ + + + + + diff --git a/src/views/ExerciseTwo.vue b/src/views/ExerciseTwo.vue new file mode 100644 index 000000000..0c17de574 --- /dev/null +++ b/src/views/ExerciseTwo.vue @@ -0,0 +1,25 @@ + + diff --git a/tailwind.config.js b/tailwind.config.js new file mode 100644 index 000000000..fff34edbb --- /dev/null +++ b/tailwind.config.js @@ -0,0 +1,9 @@ +/** @type {import('tailwindcss').Config} */ +export default { + content: [], + purge: ['./index.html', './src/**/*.{vue,js,ts,jsx,tsx}'], + theme: { + extend: {} + }, + plugins: [] +} diff --git a/tsconfig.app.json b/tsconfig.app.json new file mode 100644 index 000000000..e14c754d3 --- /dev/null +++ b/tsconfig.app.json @@ -0,0 +1,14 @@ +{ + "extends": "@vue/tsconfig/tsconfig.dom.json", + "include": ["env.d.ts", "src/**/*", "src/**/*.vue"], + "exclude": ["src/**/__tests__/*"], + "compilerOptions": { + "composite": true, + "tsBuildInfoFile": "./node_modules/.tmp/tsconfig.app.tsbuildinfo", + + "baseUrl": ".", + "paths": { + "@/*": ["./src/*"] + } + } +} diff --git a/tsconfig.json b/tsconfig.json new file mode 100644 index 000000000..66b5e5703 --- /dev/null +++ b/tsconfig.json @@ -0,0 +1,11 @@ +{ + "files": [], + "references": [ + { + "path": "./tsconfig.node.json" + }, + { + "path": "./tsconfig.app.json" + } + ] +} diff --git a/tsconfig.node.json b/tsconfig.node.json new file mode 100644 index 000000000..f09406303 --- /dev/null +++ b/tsconfig.node.json @@ -0,0 +1,19 @@ +{ + "extends": "@tsconfig/node20/tsconfig.json", + "include": [ + "vite.config.*", + "vitest.config.*", + "cypress.config.*", + "nightwatch.conf.*", + "playwright.config.*" + ], + "compilerOptions": { + "composite": true, + "noEmit": true, + "tsBuildInfoFile": "./node_modules/.tmp/tsconfig.node.tsbuildinfo", + + "module": "ESNext", + "moduleResolution": "Bundler", + "types": ["node"] + } +} diff --git a/vite.config.ts b/vite.config.ts new file mode 100644 index 000000000..5c45e1d9b --- /dev/null +++ b/vite.config.ts @@ -0,0 +1,16 @@ +import { fileURLToPath, URL } from 'node:url' + +import { defineConfig } from 'vite' +import vue from '@vitejs/plugin-vue' + +// https://vitejs.dev/config/ +export default defineConfig({ + plugins: [ + vue(), + ], + resolve: { + alias: { + '@': fileURLToPath(new URL('./src', import.meta.url)) + } + } +}) From 6cf8d5b7006a619ddd1bf876008e63d47c87218e Mon Sep 17 00:00:00 2001 From: luckyboy07 Date: Sun, 18 Aug 2024 06:02:05 +0800 Subject: [PATCH 2/3] added read me --- readme.md | 67 +++++++++++++++++++++++++------------------------------ 1 file changed, 30 insertions(+), 37 deletions(-) diff --git a/readme.md b/readme.md index 72b342846..7f3c2fb3f 100644 --- a/readme.md +++ b/readme.md @@ -1,40 +1,33 @@ -Introduction ---- -Thanks for taking the time to complete this frontend technical assessment. We will be focusing on software quality (scalability, readability, maintainability, etc.) and your eye for detail. You may include any libraries, but Vue.js is preferred and jQuery is not recommended. Along with following best practices, bonus points for following our [coding guidelines](https://github.com/mindarc/frontend-assessment/wiki/Coding-guidelines). - -Exercise 1 ---- -Build a responsive page based on the designs. - -##### Requirements -1. Match the designs exactly. -2. Needs to be responsive. - -##### Designs -* exercise1-desktop.png -* exercise1-mobile.png - -##### Assets -* Desktop banner - https://via.placeholder.com/1920x650 -* Mobile banner - https://via.placeholder.com/600x600 -* Content images - https://via.placeholder.com/400x300 - -Exercise 2 ---- -Read the `data.json` file and display the data as tabs on desktop and an accordion on mobile. - -##### Requirements -1. Display data in tabs on desktop. -2. Display data in an accordion on mobile. -3. Only 1 accordion/tab should be open at a time. -4. Open the first accordion/tab on load. -5. If the open accordion is selected, close it. +## Frontend Assesment + +- Exercise 1 +- Exercise 2 + +``` + - Access Exercise 1 by the default route `/` + - Access Exercise 2 by the route `/exercise-two` or the floating button at bottom right +``` + +### Usage + +``` + ### Install dependencies +``` + +```bash +npm install +``` + +### Run + +```bash +npm run start +``` ###### Bonus points -* Improve the user experience with meaningful animations/transitions. -* Design and styling. -* Explain why the result of `('b' + 'a' + + 'a' + 'a').toLowerCase()` is `banana`. -Submission ---- -We recommend submitting your completed assessment as a forked repository. Please replace README content with instructions and relevant documentation. +- Explain why the result of `('b' + 'a' + + 'a' + 'a').toLowerCase()` is `banana`. + +``` +- After the concatenation of 'b' + 'a' = "ba", The following + 'a' attempts to convert into a number since 'a' is not a number, this results into 'NaN' which is a "Not a Number". Now the "ba" + "NaN" becomes "baNaN" as it is converted to a string value. adding another 'a' results in "baNaNa". Since we converted it into "toLowerCase()" the resut now is "banana". +``` From 48f8c2b62242672452af65d5661763ee18f03070 Mon Sep 17 00:00:00 2001 From: Cairudin Jr Ramos Date: Sun, 18 Aug 2024 06:03:12 +0800 Subject: [PATCH 3/3] Update readme.md --- readme.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/readme.md b/readme.md index 7f3c2fb3f..e8343b602 100644 --- a/readme.md +++ b/readme.md @@ -29,5 +29,7 @@ npm run start - Explain why the result of `('b' + 'a' + + 'a' + 'a').toLowerCase()` is `banana`. ``` -- After the concatenation of 'b' + 'a' = "ba", The following + 'a' attempts to convert into a number since 'a' is not a number, this results into 'NaN' which is a "Not a Number". Now the "ba" + "NaN" becomes "baNaN" as it is converted to a string value. adding another 'a' results in "baNaNa". Since we converted it into "toLowerCase()" the resut now is "banana". +- After the concatenation of 'b' + 'a' = "ba", The following + 'a' attempts to convert into a number since 'a' is not a number. +This results into 'NaN' which is a "Not a Number". Now the "ba" + "NaN" becomes "baNaN" as it is converted to a string value. +Adding another 'a' results in "baNaNa". Since we converted it into "toLowerCase()" the resut now is "banana". ```