Browse Source

client: restructures and implements new components

master
creton32 1 month ago
parent
commit
202b60ae14
  1. 1
      client/.dockerignore
  2. 37
      client/.eslintrc.json
  3. 9
      client/.prettierrc.js
  4. 7
      client/Dockerfile
  5. 0
      client/assets/fonts/nunito/Nunito-Black.ttf
  6. 0
      client/assets/fonts/nunito/Nunito-BlackItalic.ttf
  7. 0
      client/assets/fonts/nunito/Nunito-Bold.ttf
  8. 0
      client/assets/fonts/nunito/Nunito-BoldItalic.ttf
  9. 0
      client/assets/fonts/nunito/Nunito-ExtraBold.ttf
  10. 0
      client/assets/fonts/nunito/Nunito-ExtraBoldItalic.ttf
  11. 0
      client/assets/fonts/nunito/Nunito-ExtraLight.ttf
  12. 0
      client/assets/fonts/nunito/Nunito-ExtraLightItalic.ttf
  13. 0
      client/assets/fonts/nunito/Nunito-Italic.ttf
  14. 0
      client/assets/fonts/nunito/Nunito-Light.ttf
  15. 0
      client/assets/fonts/nunito/Nunito-LightItalic.ttf
  16. 0
      client/assets/fonts/nunito/Nunito-Regular.ttf
  17. 0
      client/assets/fonts/nunito/Nunito-SemiBold.ttf
  18. 0
      client/assets/fonts/nunito/Nunito-SemiBoldItalic.ttf
  19. 0
      client/assets/fonts/nunito/OFL.txt
  20. 0
      client/assets/fonts/roboto/LICENSE.txt
  21. 0
      client/assets/fonts/roboto/Roboto-Black.ttf
  22. 0
      client/assets/fonts/roboto/Roboto-BlackItalic.ttf
  23. 0
      client/assets/fonts/roboto/Roboto-Bold.ttf
  24. 0
      client/assets/fonts/roboto/Roboto-BoldItalic.ttf
  25. 0
      client/assets/fonts/roboto/Roboto-Italic.ttf
  26. 0
      client/assets/fonts/roboto/Roboto-Light.ttf
  27. 0
      client/assets/fonts/roboto/Roboto-LightItalic.ttf
  28. 0
      client/assets/fonts/roboto/Roboto-Medium.ttf
  29. 0
      client/assets/fonts/roboto/Roboto-MediumItalic.ttf
  30. 0
      client/assets/fonts/roboto/Roboto-Regular.ttf
  31. 0
      client/assets/fonts/roboto/Roboto-Thin.ttf
  32. 0
      client/assets/fonts/roboto/Roboto-ThinItalic.ttf
  33. 0
      client/assets/icons/caret-right.svg
  34. 0
      client/assets/icons/close.svg
  35. 0
      client/assets/icons/close_mobile.jpg
  36. 0
      client/assets/icons/facebook.svg
  37. 0
      client/assets/icons/health.svg
  38. 0
      client/assets/icons/ic_email.svg
  39. 0
      client/assets/icons/linkedin.svg
  40. 0
      client/assets/icons/logo-doulton-desc.svg
  41. 0
      client/assets/icons/logo-doulton.svg
  42. 0
      client/assets/icons/logo-siameses.svg
  43. 11
      client/assets/icons/loop.svg
  44. 0
      client/assets/icons/menu.svg
  45. 0
      client/assets/icons/my_location.svg
  46. 7
      client/assets/icons/pause.svg
  47. 0
      client/assets/icons/phone.svg
  48. 4
      client/assets/icons/play.svg
  49. 0
      client/assets/icons/quality.svg
  50. 0
      client/assets/icons/technology.svg
  51. 0
      client/assets/img/carlos.png
  52. 0
      client/assets/img/doulton-banner.png
  53. 0
      client/assets/img/doulton-logo.png
  54. 0
      client/assets/img/main-showcase.png
  55. 0
      client/assets/img/miguel.png
  56. 0
      client/assets/img/objective-showcase.png
  57. 16
      client/assets/styles/base/_globals.scss
  58. 21
      client/assets/styles/base/_mixins.scss
  59. 0
      client/assets/styles/base/_typography.scss
  60. 0
      client/assets/styles/base/_variables.scss
  61. 38
      client/assets/styles/components/_button.scss
  62. 22
      client/assets/styles/components/_card.scss
  63. 102
      client/assets/styles/components/_form.scss
  64. 71
      client/assets/styles/components/_modals.scss
  65. 131
      client/assets/styles/components/_navbar.scss
  66. 111
      client/assets/styles/components/_showcase.scss
  67. 44
      client/assets/styles/components/_video.scss
  68. 5
      client/assets/styles/layout/_container.scss
  69. 6
      client/assets/styles/layout/_footer.scss
  70. 0
      client/assets/styles/layout/_header.scss
  71. 2
      client/assets/styles/main.scss
  72. 0
      client/assets/videos/doulton_peru.mp4
  73. 23
      client/components/layout/button/Button.js
  74. 12
      client/components/layout/button/ButtonWrapper.js
  75. 48
      client/components/layout/cards/CardItem.js
  76. 5
      client/components/layout/cards/Cards.js
  77. 0
      client/components/layout/footer/Footer.js
  78. 2
      client/components/layout/form/Form.js
  79. 14
      client/components/layout/form/FormInput.js
  80. 37
      client/components/layout/modals/Modal.js
  81. 46
      client/components/layout/navbar/MobileNavbar.js
  82. 46
      client/components/layout/navbar/Navbar.js
  83. 6
      client/components/layout/navbar/NavbarItem.js
  84. 58
      client/components/layout/showcase/Showcase.js
  85. 58
      client/components/layout/video/Video.js
  86. 88
      client/components/pages/About.js
  87. 0
      client/components/pages/Contact.js
  88. 64
      client/components/pages/Doulton.js
  89. 12
      client/components/pages/Index.js
  90. 0
      client/hooks/useFetch.js
  91. 10
      client/hooks/useFormInput.js
  92. 2
      client/index.html
  93. 7
      client/index.js
  94. 11284
      client/package-lock.json
  95. 46
      client/package.json
  96. 17
      client/reducers/GlobalReducer.js
  97. 10
      client/src/assets/styles/base/_globals.scss
  98. 90
      client/src/assets/styles/components/_form.scss
  99. 44
      client/src/assets/styles/components/_navbar.scss
  100. 39
      client/src/components/layout/cards/CardItem.js

1
client/.dockerignore

@ -1 +0,0 @@
node_modules

37
client/.eslintrc.json

@ -1,37 +0,0 @@
{
"env": {
"browser": true,
"es2020": true
},
"extends": [
"eslint:recommended",
"plugin:react/recommended",
"plugin:@typescript-eslint/eslint-recommended",
"plugin:@typescript-eslint/recommended"
],
"parserOptions": {
"ecmaFeatures": {
"jsx": true
},
"ecmaVersion": 11,
"sourceType": "module"
},
"plugins": [
"react",
"@typescript-eslint"
],
"rules": {
"indent":"off",
"react/destructuring-assignment": [ 1, "always" ],
"react/self-closing-comp": [ 1, {
"component": true,
"html": true
} ],
"react/jsx-indent": [ 1, 2, {
"checkAttributes": true,
"indentLogicalExpressions": true
} ],
"react/jsx-indent-props": [ 1, 2 ],
"react/jsx-no-useless-fragment": [ 1, true ]
}
}

9
client/.prettierrc.js

@ -1,9 +0,0 @@
module.exports = {
trailingComma: 'none',
tabWidth: 2,
semi: false,
singleQuote: true,
jsxBracketSameLine: true,
arrowParens: 'always',
bracketSpacing: true
}

7
client/Dockerfile

@ -1,7 +0,0 @@
FROM node:lts-alpine
WORKDIR /usr/src/client
COPY package*.json ./
RUN npm i -qy
COPY . .
EXPOSE 8080
CMD [ "npm", "dev" ]

client/src/assets/fonts/nunito/Nunito-Black.ttf → client/assets/fonts/nunito/Nunito-Black.ttf

client/src/assets/fonts/nunito/Nunito-BlackItalic.ttf → client/assets/fonts/nunito/Nunito-BlackItalic.ttf

client/src/assets/fonts/nunito/Nunito-Bold.ttf → client/assets/fonts/nunito/Nunito-Bold.ttf

client/src/assets/fonts/nunito/Nunito-BoldItalic.ttf → client/assets/fonts/nunito/Nunito-BoldItalic.ttf

client/src/assets/fonts/nunito/Nunito-ExtraBold.ttf → client/assets/fonts/nunito/Nunito-ExtraBold.ttf

client/src/assets/fonts/nunito/Nunito-ExtraBoldItalic.ttf → client/assets/fonts/nunito/Nunito-ExtraBoldItalic.ttf

client/src/assets/fonts/nunito/Nunito-ExtraLight.ttf → client/assets/fonts/nunito/Nunito-ExtraLight.ttf

client/src/assets/fonts/nunito/Nunito-ExtraLightItalic.ttf → client/assets/fonts/nunito/Nunito-ExtraLightItalic.ttf

client/src/assets/fonts/nunito/Nunito-Italic.ttf → client/assets/fonts/nunito/Nunito-Italic.ttf

client/src/assets/fonts/nunito/Nunito-Light.ttf → client/assets/fonts/nunito/Nunito-Light.ttf

client/src/assets/fonts/nunito/Nunito-LightItalic.ttf → client/assets/fonts/nunito/Nunito-LightItalic.ttf

client/src/assets/fonts/nunito/Nunito-Regular.ttf → client/assets/fonts/nunito/Nunito-Regular.ttf

client/src/assets/fonts/nunito/Nunito-SemiBold.ttf → client/assets/fonts/nunito/Nunito-SemiBold.ttf

client/src/assets/fonts/nunito/Nunito-SemiBoldItalic.ttf → client/assets/fonts/nunito/Nunito-SemiBoldItalic.ttf

client/src/assets/fonts/nunito/OFL.txt → client/assets/fonts/nunito/OFL.txt

client/src/assets/fonts/roboto/LICENSE.txt → client/assets/fonts/roboto/LICENSE.txt

client/src/assets/fonts/roboto/Roboto-Black.ttf → client/assets/fonts/roboto/Roboto-Black.ttf

client/src/assets/fonts/roboto/Roboto-BlackItalic.ttf → client/assets/fonts/roboto/Roboto-BlackItalic.ttf

client/src/assets/fonts/roboto/Roboto-Bold.ttf → client/assets/fonts/roboto/Roboto-Bold.ttf

client/src/assets/fonts/roboto/Roboto-BoldItalic.ttf → client/assets/fonts/roboto/Roboto-BoldItalic.ttf

client/src/assets/fonts/roboto/Roboto-Italic.ttf → client/assets/fonts/roboto/Roboto-Italic.ttf

client/src/assets/fonts/roboto/Roboto-Light.ttf → client/assets/fonts/roboto/Roboto-Light.ttf

client/src/assets/fonts/roboto/Roboto-LightItalic.ttf → client/assets/fonts/roboto/Roboto-LightItalic.ttf

client/src/assets/fonts/roboto/Roboto-Medium.ttf → client/assets/fonts/roboto/Roboto-Medium.ttf

client/src/assets/fonts/roboto/Roboto-MediumItalic.ttf → client/assets/fonts/roboto/Roboto-MediumItalic.ttf

client/src/assets/fonts/roboto/Roboto-Regular.ttf → client/assets/fonts/roboto/Roboto-Regular.ttf

client/src/assets/fonts/roboto/Roboto-Thin.ttf → client/assets/fonts/roboto/Roboto-Thin.ttf

client/src/assets/fonts/roboto/Roboto-ThinItalic.ttf → client/assets/fonts/roboto/Roboto-ThinItalic.ttf

client/src/assets/icons/caret-right.svg → client/assets/icons/caret-right.svg

client/src/assets/icons/close.svg → client/assets/icons/close.svg

client/src/assets/icons/close_mobile.jpg → client/assets/icons/close_mobile.jpg

client/src/assets/icons/facebook.svg → client/assets/icons/facebook.svg

client/src/assets/icons/health.svg → client/assets/icons/health.svg

client/src/assets/icons/ic_email.svg → client/assets/icons/ic_email.svg

client/src/assets/icons/linkedin.svg → client/assets/icons/linkedin.svg

client/src/assets/icons/logo-doulton-desc.svg → client/assets/icons/logo-doulton-desc.svg

client/src/assets/icons/logo-doulton.svg → client/assets/icons/logo-doulton.svg

client/src/assets/icons/logo-siameses.svg → client/assets/icons/logo-siameses.svg

11
client/assets/icons/loop.svg

@ -0,0 +1,11 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Generator: Adobe Illustrator 21.1.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
width="52px" height="52px" viewBox="0 0 52 52" enable-background="new 0 0 52 52" xml:space="preserve">
<path fill="#FFFFFF" d="M47.2,32.6c0,0.1,0,0.1-0.1,0.2c-0.3,0.9-0.5,1.8-0.9,2.6c-0.4,0.9-0.8,1.9-1.3,2.7c-1,1.8-2.2,3.4-3.6,4.8
c-1.4,1.4-3,2.7-4.7,3.7c-1.7,1-3.6,1.9-5.6,2.4c-2,0.6-4.1,0.8-6.2,0.8C12.3,50,2,39.7,2,27.1S12.3,4.2,24.9,4.2
c4.3,0,8.3,1.2,11.7,3.2c0,0,0,0,0,0c1.7,1,3.2,2.2,4.5,3.5c0.4,0.3,0.7,0.6,1,1c0.8,0.6,1.3,0.2,1.3-0.8V3.6C43.4,2.8,44.2,2,45,2
h3.2c0.9,0,1.6,0.8,1.7,1.6v19.6c0,0.8-0.6,1.4-1.4,1.4H28.9c-0.9,0-1.5-0.6-1.5-1.5v-3.3c0-0.9,0.8-1.6,1.6-1.6h7.5
c0.6,0,1.2-0.2,1.4-0.5c-2.9-4-7.6-6.6-13-6.6c-8.9,0-16,7.2-16,16s7.2,16,16,16c7,0,12.9-4.4,15.1-10.6c0,0,0.3-1.4,1.4-1.4
c1.1,0,3.8,0,4.6,0c0.7,0,1.3,0.5,1.3,1.2C47.2,32.4,47.2,32.5,47.2,32.6z"/>
</svg>

client/src/assets/icons/Menu.svg → client/assets/icons/menu.svg

client/src/assets/icons/my_location.svg → client/assets/icons/my_location.svg

7
client/assets/icons/pause.svg

@ -0,0 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Generator: Adobe Illustrator 21.0.2, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
width="52px" height="52px" viewBox="0 0 52 52" enable-background="new 0 0 52 52" xml:space="preserve">
<path fill="#FFFFFF" d="M30,43c0,1,0.9,2,2,2h4c1.1,0,2-1.1,2-2V9c0-1-0.9-2-2-2h-4c-1.1,0-2,1.1-2,2V43z"/>
<path fill="#FFFFFF" d="M14,43c0,1,0.9,2,2,2h4c1.1,0,2-1.1,2-2V9c0-1-0.9-2-2-2h-4c-1.1,0-2,1.1-2,2V43z"/>
</svg>

client/src/assets/icons/phone.svg → client/assets/icons/phone.svg

4
client/assets/icons/play.svg

@ -0,0 +1,4 @@
<svg width="104" height="104" viewBox="0 0 104 104" fill="none" xmlns="http://www.w3.org/2000/svg">
<circle cx="52" cy="52" r="50" stroke="white" stroke-width="4"/>
<path d="M72 52L42 69.3205L42 34.6795L72 52Z" fill="white"/>
</svg>

client/src/assets/icons/quality.svg → client/assets/icons/quality.svg

client/src/assets/icons/technology.svg → client/assets/icons/technology.svg

client/src/assets/img/carlos.png → client/assets/img/carlos.png

client/src/assets/img/doulton-banner.png → client/assets/img/doulton-banner.png

client/src/assets/img/doulton-logo.png → client/assets/img/doulton-logo.png

client/src/assets/img/main-showcase.png → client/assets/img/main-showcase.png

client/src/assets/img/miguel.png → client/assets/img/miguel.png

client/src/assets/img/objective-showcase.png → client/assets/img/objective-showcase.png

16
client/assets/styles/base/_globals.scss

@ -0,0 +1,16 @@
*, :root {
padding: 0;
margin: 0;
border: none;
}
body {
background: white;
color: #747B8E;
font-family: $nunito-light;
@include scrollbar;
z-index: 1;
}
::selection {
background: $navy_blue;
color: $cool_gray;
}

client/src/assets/styles/base/_mixins.scss → client/assets/styles/base/_mixins.scss

client/src/assets/styles/base/_typography.scss → client/assets/styles/base/_typography.scss

client/src/assets/styles/base/_variables.scss → client/assets/styles/base/_variables.scss

client/src/assets/styles/components/_button.scss → client/assets/styles/components/_button.scss

client/src/assets/styles/components/_card.scss → client/assets/styles/components/_card.scss

102
client/assets/styles/components/_form.scss

@ -0,0 +1,102 @@
.form-wrapper {
padding: 3rem 0;
@include respond($tablet) {
width: 100%;
padding: 2rem;
box-sizing: border-box;
}
form {
@include flexbox-center;
@include flex-direction(column);
width: 100%;
.number-input {
@include flexbox;
@include align-items(flex-end);
}
div {
width: inherit;
.input-wrapper {
@include flexbox;
@include align-items(flex-end);
position: relative;
height: 5.5rem;
@include respond($tablet) {
width: 100%;
}
.label {
position: absolute;
bottom: 1.2rem;
left: 1rem;
-moz-user-select: -moz-none;
-khtml-user-select: none;
-webkit-user-select: none;
transition: transform 0.2s ease-in-out, font-size 0.2s ease-in-out,
color 0.1s ease-in;
}
.selected {
transform: translateY(-40px);
font-size: 0.8rem;
color: $navy_blue;
}
input {
width: 400px;
border: none;
background: transparent;
border: 1px solid $gray;
border-radius: 0.5rem;
font-size: 1.1rem;
color: $dark_gray;
transition: border-bottom 0.2s ease-in-out;
font-family: $nunito-light;
padding: 1rem;
z-index: 2;
&:focus {
outline: 0;
}
@include respond($tablet){
width: inherit;
}
}
}
.input-wrapper.large {
@extend .input-wrapper;
height: 200px;
margin: 3rem 0 0 0;
box-sizing: border-box;
textarea {
resize: none;
width: 420px;
padding: 0.5rem;
height: 200px;
font-size: 14px;
font-family: inherit;
font-size: inherit;
color: $dark_gray;
bottom: 0;
border: none;
background: transparent;
border: 1px solid $gray;
z-index: 2;
box-sizing: border-box;
border-radius: 0.5rem;
transition: border 0.2s ease-in-out;
&:focus {
outline: 0;
}
@include respond($tablet) {
width: inherit;
}
}
.label {
top: 1rem;
}
.selected {
transform: translateY(-40px);
font-size: 0.8rem;
color: $navy_blue;
}
}
}
}
}

71
client/assets/styles/components/_modals.scss

@ -0,0 +1,71 @@
.content-modal-wrapper {
@include flexbox-center;
@include flex-direction(column);
&.visible {
height: 100vh;
z-index: 3;
padding: 2rem 5rem;
@include respond($tablet) {
padding: 0 1rem;
}
opacity: 1;
visibility: visible;
}
&.video {
z-index: 3;
padding: 0;
.close-btn {
&:hover > svg path {
fill: white;
}
}
}
visibility: hidden;
opacity: 0;
top: 0;
left: 0;
height: 0;
background: white;
position: fixed;
width: 100vw;
box-sizing: border-box;
padding: 0;
transition-property: visibility, opacity;
transition-duration: .3s;
transition-timing-function: linear;
.close-btn {
position: absolute;
top: 2rem;
right: 2rem;
z-index: 2;
cursor: pointer;
&:hover > svg path {
transition: fill .3s ease-in-out;
fill: $navy_blue;
}
}
.modal-title {
color: $navy_blue;
font-size: 1rem;
text-align: center;
padding: 4rem;
box-sizing: border-box;
@include respond($mobile-landscape) {
padding: 4rem 1rem 1rem;
}
b {
font-family: $nunito_semibold;
}
}
.modal-content {
@include scrollbar;
@include respond($tablet) {
height: 80%;
}
overflow-y: scroll;
p {
padding: 1rem 1rem;
text-align: justify;
}
}
}

131
client/assets/styles/components/_navbar.scss

@ -0,0 +1,131 @@
.nav-wrapper {
@include flexbox;
justify-content: space-between;
@include align-items(center);
font-family: 'nunito-light';
padding: 2rem .5rem 2rem 3rem;
.logo {
outline: none;
&:focus {
border: none;
}
img {
height: 30px;
width: auto;
outline: none;
&:focus {
border: none;
}
}
}
div.mobile-menu {
padding: 0 2rem;
cursor: pointer;
display: none;
@include respond($tablet) {
display: block;
}
}
ul.navbar {
display: flex;
justify-content: center;
align-items: center;
flex-direction: row;
list-style-type: none;
@include respond($tablet) {
display: none;
}
a {
text-decoration: none;
color: $dark_blue;
font-size: 1.1rem;
padding: .5rem 2rem;
cursor: pointer;
outline: none;
&.active {
font-weight: bold;
}
}
.social-links {
a {
padding: .5rem;
}
}
}
}
nav.mobile-nav-wrapper {
@include flexbox;
@include flex-direction(column);
@include justify-content(center);
@include align-items(flex-start);
&.visible {
height: 100vh;
z-index: 3;
visibility: visible;
opacity: 1;
}
visibility: hidden;
position: fixed;
width: 100vw;
left: 0;
top: 0;
height: 0;
opacity: 0;
background: white;
box-sizing: border-box;
transition-property: visibility, opacity;
transition-duration: .3s;
transition-timing-function: ease;
.close-btn {
cursor: pointer;
position: absolute;
padding: 2rem;
top: 0;
right: 0;
svg {
path {
fill: $navy_blue;
}
}
}
ul.mobile-navbar {
padding: 3rem;
list-style: none;
a {
color: $navy_blue;
text-decoration: none;
padding: 2rem;
font-size: 2rem;
@include respond($mobile-portrait) {
font-size: 1.5rem;
}
&.active {
font-family: $nunito-semibold;
}
}
}
.social-links {
@include flexbox;
@include flex-wrap(wrap);
font-size: 1.2rem;
position: absolute;
bottom: 0;
right: 0;
padding: 2rem;
.social-icons {
padding: 0 .5rem;
@include respond($mobile-portrait) {
padding: 0 .5rem;
svg {
transform: scale(1);
}
}
a {
padding: 0 1rem;
svg {
transform: scale(1.5);
}
}
}
}
}

client/src/assets/styles/components/_showcase.scss → client/assets/styles/components/_showcase.scss

44
client/assets/styles/components/_video.scss

@ -0,0 +1,44 @@
.video-wrapper {
height: 500px;
width: 100%;
position: relative;
background: black;
.content-modal-wrapper & {
height: 0;
}
.content-modal-wrapper.visible & {
height: 100%;
}
@include respond($monitor) {
height: 350px;
}
@include respond($mobile-landscape) {
height: 200px;
}
.video-overlay {
@include flexbox-center;
top: 0;
height: 100%;
width: 100%;
position: absolute;
background-color: rgba(0, 0, 0, .5);
visibility: visible;
opacity: 1;
cursor: pointer;
transition: opacity .5s ease-in-out;
&.hidden {
visibility: none;
opacity: 0;
}
svg {
@include respond($tablet) {
transform: scale(.5);
}
}
}
video {
display: block;
width: 100%;
height: inherit;
}
}

client/src/assets/styles/layout/_container.scss → client/assets/styles/layout/_container.scss

client/src/assets/styles/layout/_footer.scss → client/assets/styles/layout/_footer.scss

client/src/assets/styles/layout/_header.scss → client/assets/styles/layout/_header.scss

client/src/assets/styles/main.scss → client/assets/styles/main.scss

client/src/assets/videos/doulton_peru.mp4 → client/assets/videos/doulton_peru.mp4

client/src/components/layout/button/Button.js → client/components/layout/button/Button.js

client/src/components/layout/button/ButtonWrapper.js → client/components/layout/button/ButtonWrapper.js

48
client/components/layout/cards/CardItem.js

@ -0,0 +1,48 @@
import React from 'react'
import ButtonWrapper from '../button/ButtonWrapper'
import PropTypes from 'prop-types'
const CardItem = ({ avatar, name, position, description, socialLink }) => (
<div className="card-item">
<div className="card-preview">
<div className="avatar">
<img src={avatar} alt="" />
</div>
<div className="details">
<span className="name">{name}</span>
<span className="position">{position}</span>
</div>
<ButtonWrapper
buttons={[
{
type: 'full',
content: 'Linkedin',
path: {
uri: socialLink,
isExternal: true
}
},
{
type: 'bare',
content: 'Ver más',
path: {
uri: socialLink,
isExternal: true
}
}
]}
/>
</div>
<div className="card-description">{description}</div>
</div>
)
CardItem.propTypes = {
avatar: PropTypes.element.isRequired,
name: PropTypes.string.isRequired,
position: PropTypes.string.isRequired,
description: PropTypes.string.isRequired,
socialLink: PropTypes.string.isRequired
}
export default CardItem

client/src/components/layout/cards/Cards.js → client/components/layout/cards/Cards.js

client/src/components/layout/footer/Footer.js → client/components/layout/footer/Footer.js

client/src/components/layout/form/Form.js → client/components/layout/form/Form.js

client/src/components/layout/form/FormInput.js → client/components/layout/form/FormInput.js

37
client/components/layout/modals/Modal.js

@ -0,0 +1,37 @@
import React, { useState, useContext, useEffect } from 'react'
import CloseIcon from '../../../assets/icons/close.svg'
import PropTypes from 'prop-types'
import { Context } from '../../../stores/Store'
import Video from '../video/Video'
import DoultonVideo from '../../../assets/videos/doulton_peru.mp4'
const Modal = ({ title, content, type }) => {
const [state, dispatch] = useContext(Context)
const [isModalClosed, setIsModalClosed] = useState(false)
return (
<div className={`content-modal-wrapper${state.isModalVisible ? ' visible' : ''} ${type ? type : ''}`}>
<div className="close-btn" onClick={() => dispatch({ type: 'TOGGLE_MODAL' })}>
<CloseIcon />
</div>
{
type
? <Video src={DoultonVideo} isModalVisible={state.isModalVisible} isModal={true}/>
: <>
<div className="modal-title">
<h1>{title}</h1>
</div>
<div className="modal-content">{content}</div>
</>
}
</div>
)
}
Modal.propTypes = {
title: PropTypes.element,
content: PropTypes.element,
type: PropTypes.string
}
export default Modal

46
client/components/layout/navbar/MobileNavbar.js

@ -0,0 +1,46 @@
import React, { useContext } from 'react'
import NavbarItem from './NavbarItem'
import FbLogo from '../../../assets/icons/facebook.svg'
import LiLogo from '../../../assets/icons/linkedin.svg'
import CloseIcon from '../../../assets/icons/close.svg'
import { Context } from '../../../stores/Store'
const MobileNavbar = () => {
const [state, dispatch] = useContext(Context)
return (
<nav className={`mobile-nav-wrapper${state.isMobileNavVisible ? ' visible' : ''}`}>
<span className="close-btn" onClick={() => dispatch({type: 'TOGGLE_MOBILE_NAV'})}>
<CloseIcon />
</span>
<ul className="mobile-navbar" onClick={() => dispatch({type: 'TOGGLE_MOBILE_NAV'})}>
<NavbarItem title="Inicio" url="/" />
<NavbarItem title="Nosotros" url="/about" />
<NavbarItem title="Doulton Filters" url="/doulton" />
<NavbarItem title="Contacto" url="/contact" />
</ul>
<div className="social-links">
<span>Visitanos en</span>
<div className="social-icons">
<a
target="_blank"
rel="noreferrer"
href="https://facebook.com/siameses.com.pe"
>
<FbLogo />
</a>
<a
target="_blank"
rel="noreferrer"
href="https://linkedin.com/company/siameses/"
>
<LiLogo />
</a>
</div>
</div>
</nav>
)
}
export default MobileNavbar

46
client/components/layout/navbar/Navbar.js

@ -0,0 +1,46 @@
import React, { useContext, useEffect } from 'react'
import { NavLink } from 'react-router-dom'
import Logo from '../../../assets/icons/logo-siameses.svg'
import FbLogo from '../../../assets/icons/facebook.svg'
import LiLogo from '../../../assets/icons/linkedin.svg'
import MenuIcon from '../../../assets/icons/menu.svg'
import NavbarItem from './NavbarItem'
import MobileNavbar from './MobileNavbar'
import { Context } from '../../../stores/Store'
export const Navbar = () => {
const [state, dispatch] = useContext(Context)
useEffect(() => {
console.log(state.isMobileNavVisible)
if (state.isMobileNavVisible || state.isModalVisible) {
document.body.style.overflow = 'hidden'
} else {
document.body.style.overflow = 'auto'
}
})
return (
<>
<nav className="nav-wrapper">
<NavLink to="/" className="logo">
<Logo />
</NavLink>
<ul className="navbar">
<NavbarItem title="Inicio" url="/" />
<NavbarItem title="Nosotros" url="/about" />
<NavbarItem title="Doulton Filters" url="/doulton" />
<NavbarItem title="Contacto" url="/contact" />
<div className="social-links">
<a target="_blank" rel="noreferrer" href="https://facebook.com/siameses.com.pe"><FbLogo /></a>
<a target="_blank" rel="noreferrer" href="https://linkedin.com/company/siameses/"><LiLogo /></a>
</div>
</ul>
<div className="mobile-menu" onClick={() => dispatch({type: 'TOGGLE_MOBILE_NAV'})}>
<MenuIcon />
</div>
</nav>
<MobileNavbar />
</>
)
}

client/src/components/layout/navbar/NavbarItem.js → client/components/layout/navbar/NavbarItem.js

client/src/components/layout/showcase/Showcase.js → client/components/layout/showcase/Showcase.js

58
client/components/layout/video/Video.js

@ -0,0 +1,58 @@
import React, { useRef, useState, useEffect } from 'react'
import PlayIcon from '../../../assets/icons/play.svg'
import PauseIcon from '../../../assets/icons/pause.svg'
import LoopIcon from '../../../assets/icons/loop.svg'
const Video = ({ src, isModalVisible, isModal }) => {
const [ videoState, setVideoState] = useState('paused')
const videoRef = useRef(null)
const handlePlayVideo = () => {
videoRef.current.play()
}
const handlePauseVideo = () => {
videoRef.current.pause()
}
const handleToggleVideo = () => {
if (videoRef.current.paused) {
handlePlayVideo()
setVideoState('playing')
} else {
handlePauseVideo()
setVideoState('paused')
}
}
const handleVideoEnded = () => {
setVideoState('ended')
}
useEffect(() => {
if (!isModalVisible && isModal) {
handlePauseVideo()
setVideoState('paused')
}
})
return (
<div className="video-wrapper">
<div className={`video-overlay${videoState === 'playing' ? ' hidden' : ''}`} onClick={handleToggleVideo}>
{videoState === 'paused' ?
<PlayIcon />
: videoState === 'ended' ?
<LoopIcon /> :
<PauseIcon />
}
</div>
<video
ref={videoRef}
onClick={handleToggleVideo}
onEnded={handleVideoEnded}
>
<source src={src} type="video/mp4"/>
</video>
</div>
)
}
export default Video

88
client/components/pages/About.js

@ -0,0 +1,88 @@
import React from 'react'
import Showcase from '../layout/showcase/Showcase'
import Modal from '../layout/modals/Modal'
import Cards from '../layout/cards/Cards'
import CarlosAvatar from '../../assets/img/carlos.png'
import MiguelAvatar from '../../assets/img/miguel.png'
import QualityIcon from '../../assets/icons/quality.svg'
import HealthIcon from '../../assets/icons/health.svg'
import TechnologyIcon from '../../assets/icons/technology.svg'
const About = () => (
<>
<Modal
title={<>Conoce <b>nuestra historia</b></>}
content={<><p>Siameses se origina en la búsqueda de uno de sus fundadores (Miguel) de una fuente de agua pura en la naturaleza. Un manantial de agua mineral que pudiera mejorar la salud de sus consumidores. Para ello, recorrió durante meses la vertiente del río Cañete, desde la costa hasta Huancaya. Durante su búsqueda conoció diferentes comunidades y muchos parajes de belleza natural.</p><p>Miguel evaluó diferentes alternativas y encontró lo que buscaba: Ser representante en el Perú de la marca líder a nivel mundial de purificadores de agua, Doulton Filters (Reino Unido). Logrando así su objetivo de brindar agua de calidad a las personas siendo responsable con el medio ambiente.</p><p>En este camino, le presenta a Carlos esta oportunidad. Ellos se conocen desde la infancia, tienen valores similares y comparten el entusiasmo por el agua como elemento fundamental para lograr una adecuada salud, el respeto por el medio ambiente y la importancia de la tecnología para lograr altos estándares de calidad.</p><p>Finalmente, acuerdan complementar sus capacidades profesionales y personales para emprender juntos el desarrollo de Siameses, tieniendo como principios: salud, calidad y tecnología.</p><p>Siameses representa la simbiosis entre el agua purificada de alta calidad en armonia con el bienestar de las personas.</p></>}
/>
<div className="about-wrapper">
<Showcase
type="bare"
title={<>¡Hola!<br/><b>Somos Siameses</b></>}
description="Ofrecemos soluciones de calidad y ecoamigables de purificación de agua para las familias y comercios del Perú."
buttons={[
{
content: 'Conoce nuestra historia',
type: 'modal'
}
]} />
<Cards
items={[
{
avatar: CarlosAvatar,
name: 'Carlos Siles Molinelli',
position: 'Director Ejecutivo',
socialLink: 'https://pe.linkedin.com/in/carlossilesmolinelli',
description: 'Siempre me interesó trabajar en sectores con impacto positivo en la calidad de vida de las personas. Siameses me permite sumar el manejo responsable del agua y el cuidado del medio ambiente.'
},
{
avatar: MiguelAvatar,
name: 'Miguel Moreno Revilla',
position: 'Director Ejecutivo',
socialLink: 'https://pe.linkedin.com/in/miguel-moreno-revilla',
description: 'Soy Ingeniero Industrial especialista en logística y un apasionado del agua, la sostenibilidad y el cuidado medioambiental.'
}
]}
/>
<Showcase
label="Nuestro compromiso"
title={<><b>Agua purificada para cuidar tu salud</b></>}
type="list"
bgColor="#E2F5F9"
items={[
{
title: 'Calidad',
description: 'Ofrecemos soluciones con certificaciones internacionales de calidad',
icon: <QualityIcon />
},
{
title: 'Salud',
description: 'Retener minerales que tu cuerpo necesita y eliminar elementos nocivos',
icon: <HealthIcon />
},
{
title: 'Tecnologia',
description: 'Nuestras soluciones incorporan los avances tecnológicos',
icon: <TechnologyIcon />
}
]}
/>
<Showcase
title={<>¿Te interesa unirte <b>al equipo?</b></>}
description={<>Si te gusta nuestra propuesta y quieres ser distribuidor o trabajar con nosotros, escríbenos a <a href="mailto:contacto@siameses.com.pe">contacto@siameses.com.pe</a></>}
orientation="center"
buttons={[
{
type: 'full',
content: 'Enviar correo',
path: {
uri: 'mailto:contacto@siameses.com.pe',
isExternal: true
}
}
]}
/>
</div>
</>
)
export default About

client/src/components/pages/Contact.js → client/components/pages/Contact.js

64
client/components/pages/Doulton.js

@ -0,0 +1,64 @@
import React from 'react'
import Showcase from '../layout/showcase/Showcase'
import DoultonBanner from '../../assets/img/doulton-banner.png'
import Video from '../layout/video/Video'
import DoultonVideo from '../../assets/videos/doulton_peru.mp4'
const Doulton = () => (
<div className="doulton-wrapper">
<Showcase
type='bare'
title={<>¡La marca Nº1 en <b>purificadores de agua</b> ya está aquí!</>}
description='Somos representantes de Doulton Filters ® del Reino Unido, para ofrecer la mejor calidad de agua purificada a las familias y comercios del Perú.'
buttons={[
{
content: 'Ir a Doulton.com.pe',
type: 'bare',
path: {
uri: 'https://doulton.com.pe',
isExternal: true
}
}
]}
/>
<Showcase
title="Prueba, saborea, confía y descubre la diferencia de Doulton ®."
type="list"
bgColor="#E2F5F9"
items={[
{
title: 'Pioneros en acceso al agua purificada desde 1826',
description: 'Doulton ® llega hoy con sus soluciones a millones de hogares y comercios en 140 países.'
},
{
title: 'Altos estándares de calidad',
description: 'Doulton ® cuenta con premios y certificaciones internacionales de calidad.',
},
{
title: 'Materiales 100% naturales',
description: 'Los filtros Doulton ® son biodegradables. Además, fomentan el cuidado del medio ambiente.'
}
]}
/>
<Video src={DoultonVideo} />
<Showcase
label='Doulton Filters'
type='center'
title='Conoce el catálogo de Doulton en Perú'
orientation='center'
bgImage={DoultonBanner}
buttons={[
{
type: 'alt',
content: 'Ver productos',
path: {
uri: 'https://doulton.com.pe/productos',
isExternal: true
}
}
]}
/>
</div>
)
export default Doulton

client/src/components/pages/Index.js → client/components/pages/Index.js

client/src/hooks/useFetch.js → client/hooks/useFetch.js

client/src/hooks/useFormInput.js → client/hooks/useFormInput.js

client/src/index.html → client/index.html

client/src/index.js → client/index.js

11284
client/package-lock.json
File diff suppressed because it is too large
View File

46
client/package.json

@ -1,46 +0,0 @@
{
"name": "siameses_client",
"version": "1.0.0",
"description": "Siameses front-end",
"main": "src/index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1",
"dev": "webpack serve --config webpack.dev.js --mode development",
"build": "webpack --config webpack.prod.js --mode production"
},
"repository": {
"type": "git",
"url": ""
},
"author": "",
"license": "AGPL-3.0",
"devDependencies": {
"@babel/core": "^7.10.2",
"@babel/preset-env": "^7.10.2",
"@babel/preset-react": "^7.12.10",
"@svgr/webpack": "^5.4.0",
"babel-loader": "^8.2.2",
"clean-webpack-plugin": "^3.0.0",
"css-loader": "^5.0.1",
"css-minimizer-webpack-plugin": "^1.2.0",
"file-loader": "^6.0.0",
"html-loader": "^1.3.2",
"html-webpack-plugin": "^4.5.1",
"mini-css-extract-plugin": "^1.3.3",
"mini-svg-data-uri": "^1.2.3",
"node-sass": "^5.0.0",
"resolve-url-loader": "^3.1.1",
"sass-loader": "^10.1.0",
"terser-webpack-plugin": "^5.1.1",
"url-loader": "^4.1.0",
"webpack": "^5.12.2",
"webpack-cli": "^4.3.1",
"webpack-dev-server": "^3.11.0",
"webpack-merge": "^5.7.3"
},
"dependencies": {
"react": "^17.0.1",
"react-dom": "^17.0.1",
"react-router-dom": "^5.2.0"
}
}

17
client/reducers/GlobalReducer.js

@ -0,0 +1,17 @@
const GlobalReducer = (state, action) => {
switch(action.type) {
case 'TOGGLE_MODAL':
return {
...state,
isModalVisible: !state.isModalVisible
}
case 'TOGGLE_MOBILE_NAV':
return {
...state,
isMobileNavVisible: !state.isMobileNavVisible
}
default: return state
}
}
export default GlobalReducer

10
client/src/assets/styles/base/_globals.scss

@ -1,10 +0,0 @@
*, :root {
padding: 0;
margin: 0;
border: none;
}
body {
background: white;
color: #747B8E;
font-family: $nunito-light;
}

90
client/src/assets/styles/components/_form.scss

@ -1,90 +0,0 @@
.form-wrapper {
padding: 3rem 0;
form {
@include flexbox-center;
@include flex-direction(column);
width: 100%;
.number-input {
@include flexbox;
@include align-items(flex-end);
}
.input-wrapper {
@include flexbox;
@include align-items(flex-end);
position: relative;
height: 5rem;
.label {
position: absolute;
bottom: 0.8rem;
left: 0.5rem;
-moz-user-select: -moz-none;
-khtml-user-select: none;
-webkit-user-select: none;
transition: transform 0.2s ease-in-out, font-size 0.2s ease-in-out,
color 0.1s ease-in;
}
.selected {
transform: translateY(-30px);
font-size: 0.8rem;
color: $navy_blue;
}
input {
width: 400px;
border: none;
background: transparent;
border-bottom: 1px solid $gray;
font-size: 1.1rem;
color: $dark_gray;
transition: border-bottom 0.2s ease-in-out;
font-family: $nunito-light;
padding: 0.8rem 0.5rem;
z-index: 2;
&:focus {
outline: 0;
}
@media only screen and (max-width: $mobile-landscape) {
width: 250px;
}
}
}
.input-wrapper.large {
@extend .input-wrapper;
height: 200px;
margin: 3rem 0 0 0;
box-sizing: border-box;
textarea {
resize: none;
width: 420px;
padding: 0.5rem;
height: 200px;
font-size: 14px;
font-family: inherit;
font-size: inherit;
color: $dark_gray;
bottom: 0;
border: none;
background: transparent;
border: 1px solid $gray;
z-index: 2;
box-sizing: border-box;
border-radius: 0.5rem;
transition: border 0.2s ease-in-out;
&:focus {
outline: 0;
}
@media only screen and (max-width: $mobile-landscape) {
width: 270px;
}
}
.label {
top: 1rem;
}
.selected {
transform: translateY(-40px);
font-size: 0.8rem;
color: $navy_blue;
}
}
}
}

44
client/src/assets/styles/components/_navbar.scss

@ -1,44 +0,0 @@
.nav-wrapper {
@include flexbox;
justify-content: space-between;
@include align-items(center);
font-family: 'nunito-light';
padding: 2rem .5rem 2rem 3rem;
.logo {
outline: none;
&:focus {
border: none;
}
img {
height: 30px;
width: auto;
outline: none;
&:focus {
border: none;
}
}
}
ul.navbar {
display: flex;
justify-content: center;
align-items: center;
flex-direction: row;
list-style-type: none;
a {
text-decoration: none;
color: $dark_blue;
font-size: 1.1rem;
padding: .5rem 2rem;
cursor: pointer;
outline: none;
&.active {
font-weight: bold;
}
}
.social-links {
a {
padding: .5rem;
}
}
}
}

39
client/src/components/layout/cards/CardItem.js

@ -1,39 +0,0 @@
import React from 'react'
import ButtonWrapper from '../button/ButtonWrapper'
const CardItem = ({ avatar, name, position, description, socialLink }) => (
<div className="card-item">
<div className="card-preview">
<div className="avatar">
<img src={avatar} alt="" />
</div>
<div className="details">
<span className="name">{name}</span>
<span className="position">{position}</span>
</div>
<ButtonWrapper
buttons={[
{
type: 'full',
content: 'Linkedin',
path: {
uri: socialLink,
isExternal: true
}
},
{
type: 'bare',
content: 'Ver más',
path: {
uri: socialLink,
isExternal: true
}
}
]}
/>
</div>
<div className="card-description">{description}</div>
</div>
)
export default CardItem

Some files were not shown because too many files changed in this diff

Loading…
Cancel
Save