From d07f15b60b6c7094281ce2a16b90545b8eb136f5 Mon Sep 17 00:00:00 2001 From: ahmedmgamal94 <98055904+ahmedmgamal94@users.noreply.github.com> Date: Wed, 28 Aug 2024 08:57:14 -0700 Subject: [PATCH] landing-page-update --- package-lock.json | 85 ++++++++++++++++-- package.json | 6 +- src/app/routes/Landing.tsx | 99 ++++++++++----------- src/components/FeatureSlider.tsx | 143 ++++++++++++++++++++++++++++++ src/features/auth/BungieLogin.tsx | 23 ++++- 5 files changed, 299 insertions(+), 57 deletions(-) create mode 100644 src/components/FeatureSlider.tsx diff --git a/package-lock.json b/package-lock.json index 08e457f..25e83dd 100644 --- a/package-lock.json +++ b/package-lock.json @@ -15,6 +15,7 @@ "@mui/system": "^5.15.20", "@reduxjs/toolkit": "^2.2.6", "@tanstack/react-table": "^8.17.3", + "@types/react-slick": "^0.23.13", "axios": "^1.7.2", "dexie": "^4.0.8", "dexie-react-hooks": "^1.1.7", @@ -25,9 +26,12 @@ "react-dom": "^18.2.0", "react-redux": "^9.1.2", "react-router-dom": "^6.23.1", + "react-slick": "^0.30.2", "react-spring": "^9.7.4", "react-window": "^1.8.10", - "redux": "^5.0.1" + "redux": "^5.0.1", + "slick-carousel": "^1.8.1", + "use-scramble": "^2.2.15" }, "devDependencies": { "@types/node": "^20.14.8", @@ -4870,6 +4874,14 @@ "@types/react": "*" } }, + "node_modules/@types/react-slick": { + "version": "0.23.13", + "resolved": "https://registry.npmjs.org/@types/react-slick/-/react-slick-0.23.13.tgz", + "integrity": "sha512-bNZfDhe/L8t5OQzIyhrRhBr/61pfBcWaYJoq6UDqFtv5LMwfg4NsVDD2J8N01JqdAdxLjOt66OZEp6PX+dGs/A==", + "dependencies": { + "@types/react": "*" + } + }, "node_modules/@types/react-transition-group": { "version": "4.4.11", "resolved": "https://registry.npmjs.org/@types/react-transition-group/-/react-transition-group-4.4.11.tgz", @@ -5699,6 +5711,11 @@ "node": ">=8" } }, + "node_modules/classnames": { + "version": "2.5.1", + "resolved": "https://registry.npmjs.org/classnames/-/classnames-2.5.1.tgz", + "integrity": "sha512-saHYOzhIQs6wy2sVxTM6bUDsQO4F50V9RQ22qBpEdCW+I+/Wmke2HOl6lS6dTpdxVhb88/I6+Hs+438c3lfUow==" + }, "node_modules/cli-cursor": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-3.1.0.tgz", @@ -6211,6 +6228,11 @@ "node": ">= 0.8" } }, + "node_modules/enquire.js": { + "version": "2.1.6", + "resolved": "https://registry.npmjs.org/enquire.js/-/enquire.js-2.1.6.tgz", + "integrity": "sha512-/KujNpO+PT63F7Hlpu4h3pE3TokKRHN26JYmQpPyjkRD/N57R7bPDNojMXdi7uveAKjYB7yQnartCxZnFWr0Xw==" + }, "node_modules/env-paths": { "version": "2.2.1", "resolved": "https://registry.npmjs.org/env-paths/-/env-paths-2.2.1.tgz", @@ -8532,6 +8554,12 @@ "@sideway/pinpoint": "^2.0.0" } }, + "node_modules/jquery": { + "version": "3.7.1", + "resolved": "https://registry.npmjs.org/jquery/-/jquery-3.7.1.tgz", + "integrity": "sha512-m4avr8yL8kmFN8psrbFFFmB/If14iN5o9nw/NgnnM+kybDJpRsAynV2BsfpTYrTRysYUdADVD7CkUUizgkpLfg==", + "peer": true + }, "node_modules/js-tokens": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", @@ -8703,6 +8731,14 @@ "integrity": "sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==", "dev": true }, + "node_modules/json2mq": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/json2mq/-/json2mq-0.2.0.tgz", + "integrity": "sha512-SzoRg7ux5DWTII9J2qkrZrqV1gt+rTaoufMxEzXbS26Uid0NwaJd123HcoB80TgubEppxxIGdNxCx50fEoEWQA==", + "dependencies": { + "string-convert": "^0.2.0" + } + }, "node_modules/json5": { "version": "2.2.3", "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz", @@ -8854,8 +8890,7 @@ "node_modules/lodash.debounce": { "version": "4.0.8", "resolved": "https://registry.npmjs.org/lodash.debounce/-/lodash.debounce-4.0.8.tgz", - "integrity": "sha512-FT1yDzDYEoYWhnSGnpE/4Kj1fLZkDFyqRb7fNt6FdYOSxlUWAtp42Eh6Wb0rGIv/m9Bgo7x4GhQbm5Ys4SG5ow==", - "peer": true + "integrity": "sha512-FT1yDzDYEoYWhnSGnpE/4Kj1fLZkDFyqRb7fNt6FdYOSxlUWAtp42Eh6Wb0rGIv/m9Bgo7x4GhQbm5Ys4SG5ow==" }, "node_modules/lodash.merge": { "version": "4.6.2", @@ -11078,6 +11113,22 @@ "react-dom": ">=16.8" } }, + "node_modules/react-slick": { + "version": "0.30.2", + "resolved": "https://registry.npmjs.org/react-slick/-/react-slick-0.30.2.tgz", + "integrity": "sha512-XvQJi7mRHuiU3b9irsqS9SGIgftIfdV5/tNcURTb5LdIokRA5kIIx3l4rlq2XYHfxcSntXapoRg/GxaVOM1yfg==", + "dependencies": { + "classnames": "^2.2.5", + "enquire.js": "^2.1.6", + "json2mq": "^0.2.0", + "lodash.debounce": "^4.0.8", + "resize-observer-polyfill": "^1.5.0" + }, + "peerDependencies": { + "react": "^0.14.0 || ^15.0.1 || ^16.0.0 || ^17.0.0 || ^18.0.0", + "react-dom": "^0.14.0 || ^15.0.1 || ^16.0.0 || ^17.0.0 || ^18.0.0" + } + }, "node_modules/react-spring": { "version": "9.7.4", "resolved": "https://registry.npmjs.org/react-spring/-/react-spring-9.7.4.tgz", @@ -11326,8 +11377,7 @@ "node_modules/resize-observer-polyfill": { "version": "1.5.1", "resolved": "https://registry.npmjs.org/resize-observer-polyfill/-/resize-observer-polyfill-1.5.1.tgz", - "integrity": "sha512-LwZrotdHOo12nQuZlHEmtuXdqGoOD0OhaxopaNFxWzInpEgaLWoVuAMbTzixuosCx2nEG58ngzW3vxdWoxIgdg==", - "peer": true + "integrity": "sha512-LwZrotdHOo12nQuZlHEmtuXdqGoOD0OhaxopaNFxWzInpEgaLWoVuAMbTzixuosCx2nEG58ngzW3vxdWoxIgdg==" }, "node_modules/resolve": { "version": "1.22.8", @@ -11756,6 +11806,14 @@ "node": ">=6" } }, + "node_modules/slick-carousel": { + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/slick-carousel/-/slick-carousel-1.8.1.tgz", + "integrity": "sha512-XB9Ftrf2EEKfzoQXt3Nitrt/IPbT+f1fgqBdoxO3W/+JYvtEOW6EgxnWfr9GH6nmULv7Y2tPmEX3koxThVmebA==", + "peerDependencies": { + "jquery": ">=1.8.0" + } + }, "node_modules/source-map": { "version": "0.5.7", "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", @@ -11875,6 +11933,11 @@ ], "peer": true }, + "node_modules/string-convert": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/string-convert/-/string-convert-0.2.1.tgz", + "integrity": "sha512-u/1tdPl4yQnPBjnVrmdLo9gtuLvELKsAoRapekWggdiQNvvvum+jYF329d84NAa660KQw7pB2n36KrIKVoXa3A==" + }, "node_modules/string-width": { "version": "4.2.3", "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", @@ -12448,6 +12511,18 @@ "punycode": "^2.1.0" } }, + "node_modules/use-scramble": { + "version": "2.2.15", + "resolved": "https://registry.npmjs.org/use-scramble/-/use-scramble-2.2.15.tgz", + "integrity": "sha512-3+ngTV6OpkY9JT75FM4JYcspmpP7cd/h0/5KqsMU2jcdBD+SAuBMmLqLu0N3/7t8NsfdwJjD3BBeKtT+qZWKew==", + "engines": { + "node": ">=10" + }, + "peerDependencies": { + "react": ">=16", + "react-dom": ">=16" + } + }, "node_modules/use-sync-external-store": { "version": "1.2.2", "resolved": "https://registry.npmjs.org/use-sync-external-store/-/use-sync-external-store-1.2.2.tgz", diff --git a/package.json b/package.json index a4d95c3..d506eb4 100644 --- a/package.json +++ b/package.json @@ -17,6 +17,7 @@ "@mui/system": "^5.15.20", "@reduxjs/toolkit": "^2.2.6", "@tanstack/react-table": "^8.17.3", + "@types/react-slick": "^0.23.13", "axios": "^1.7.2", "dexie": "^4.0.8", "dexie-react-hooks": "^1.1.7", @@ -27,9 +28,12 @@ "react-dom": "^18.2.0", "react-redux": "^9.1.2", "react-router-dom": "^6.23.1", + "react-slick": "^0.30.2", "react-spring": "^9.7.4", "react-window": "^1.8.10", - "redux": "^5.0.1" + "redux": "^5.0.1", + "slick-carousel": "^1.8.1", + "use-scramble": "^2.2.15" }, "devDependencies": { "@types/node": "^20.14.8", diff --git a/src/app/routes/Landing.tsx b/src/app/routes/Landing.tsx index 43976f7..cb81994 100644 --- a/src/app/routes/Landing.tsx +++ b/src/app/routes/Landing.tsx @@ -5,42 +5,20 @@ import { regenerateTokens } from '../../lib/bungie_api/token-services'; import { isAuthenticated } from '../../lib/bungie_api/Authorization'; import { Container, Grid, Paper, Box, Typography } from '@mui/material'; import pyramidBackground from '../../assets/pyramid.jpg'; +import FeatureSlider from '../../components/FeatureSlider'; +import { useScramble } from 'use-scramble'; -const FogOverlay = () => ( - -); - -export const LandingRoute = () => { +export const LandingRoute: React.FC = () => { const navigate = useNavigate(); const [hidden, setHidden] = useState(true); + const { ref, replay } = useScramble({ + text: 'D2Loadouts', + speed: 0.3, + tick: 1, + step: 1, + scramble: 10, + seed: 0.5, + }); useEffect(() => { setTimeout(async () => { @@ -57,8 +35,14 @@ export const LandingRoute = () => { }, 300); }, [navigate]); + useEffect(() => { + if (!hidden) { + replay(); + } + }, [hidden, replay]); + if (hidden) { - return null; + return
Loading...
; } return ( @@ -73,8 +57,10 @@ export const LandingRoute = () => { backgroundPosition: 'center', backgroundRepeat: 'no-repeat', display: 'flex', + flexDirection: 'column', alignItems: 'center', justifyContent: 'center', + fontFamily: 'Helvetica, Arial, sans-serif', '&::before': { content: '""', position: 'absolute', @@ -87,7 +73,6 @@ export const LandingRoute = () => { }, }} > - { border: '1px solid rgba(255,255,255,0.1)', }} > - - + + - D2Loadouts - + sx={{ + textShadow: '2px 2px 4px rgba(0,0,0,0.5)', + fontFamily: 'Helvetica, Arial, sans-serif', + fontWeight: 'bold', + }} + /> - + D2Loadouts requires permission to read your Destiny 2 information - + + + + + + Made by Rorschach and Dragoni +
); }; diff --git a/src/components/FeatureSlider.tsx b/src/components/FeatureSlider.tsx new file mode 100644 index 0000000..192f1ca --- /dev/null +++ b/src/components/FeatureSlider.tsx @@ -0,0 +1,143 @@ +import React from 'react'; +import Slider from 'react-slick'; +import { Box, Card, CardContent, CardMedia, Typography, useTheme } from '@mui/material'; +import 'slick-carousel/slick/slick.css'; +import 'slick-carousel/slick/slick-theme.css'; + +interface Feature { + title: string; + description: string; + image: string; +} + +const features: Feature[] = [ + { + title: 'Select Your Exotic', + description: + 'D2Loadout lets you select or search for the desired exotic armor or exotic class item based on perks to your build.', + image: 'https://i.imgur.com/BpXCQ1O.gif', + }, + { + title: 'Customize Your Subclass', + description: + 'Experience a modern UI, mirroring the in-game interface, where you can apply aspects and fragments, factoring in stat bonuses and penalties.', + image: 'https://imgur.com/8vl4y6S.gif', + }, + { + title: 'Optimize Your Stats', + description: + 'Choose the highest stats and best armor combinations with advanced filters to refine your build based on your needs.', + image: 'https://imgur.com/VPxoQzB.gif', + }, + { + title: 'Armor Selection', + description: 'Easily sort and select armor based on mod capacity, energy cost, and armor type.', + image: 'https://imgur.com/SmEXjTL.gif', + }, + { + title: 'Apply Armor Mods', + description: + 'Apply all in-game armor mods and fine-tune your build—all in one convenient place.', + image: 'https://imgur.com/N3LRQ0L.gif', + }, + { + title: 'Equip Your Loadout', + description: + 'Equip your loadout from offline or in orbit. If your inventory is full, items are automatically transferred to your vault to make space.', + image: 'https://imgur.com/z69q3wD.gif', + }, + { + title: 'Share Your Build', + description: + 'Generate a link that captures your preferred stats, armor mods, and subclass mods. Share it with friends or followers, enabling them to apply the loadout in-game with a single click.', + image: 'https://via.placeholder.com/400x200?text=Share+Your+Build', + }, + { + title: 'Looking Ahead!', + description: + "Future updates will include a community hub for sharing builds, complete with a survey system to gather player feedback and a ranking system for popular streamers' recommended builds.", + image: 'https://via.placeholder.com/400x200?text=Looking+Ahead', + }, +]; + +const FeatureSlider: React.FC = () => { + const theme = useTheme(); + + const settings = { + dots: true, + infinite: true, + speed: 500, + slidesToShow: 1, + slidesToScroll: 1, + autoplay: true, + autoplaySpeed: 10000, + cssEase: 'cubic-bezier(0.600, -0.280, 0.735, 0.045)', + arrows: false, + }; + + return ( + + + {features.map((feature, index) => ( + + ))} + + + ); +}; + +const FeatureCard: React.FC<{ feature: Feature }> = ({ feature }) => { + return ( + + + + + + {feature.title} + + + {feature.description} + + + + + ); +}; + +export default FeatureSlider; diff --git a/src/features/auth/BungieLogin.tsx b/src/features/auth/BungieLogin.tsx index 06adb00..ff745f8 100644 --- a/src/features/auth/BungieLogin.tsx +++ b/src/features/auth/BungieLogin.tsx @@ -1,12 +1,33 @@ import React from 'react'; import { authenticate } from '../../lib/bungie_api/Authorization'; +import { Button } from '@mui/material'; const BungieLogin: React.FC = () => { function onLogIn() { authenticate(); } - return ; + return ( + + ); }; export default BungieLogin;