├── .env-init ├── .eslintrc.cjs ├── .gitignore ├── CODE_OF_CONDUCT.md ├── LICENSE ├── README.md ├── SECURITY.md ├── fullpage.png ├── index.html ├── me.svg ├── package-lock.json ├── package.json ├── postcss.config.js ├── public ├── .htaccess └── vite.svg ├── screenshot.jpg ├── src ├── App.css ├── App.tsx ├── assets │ ├── fonts │ │ ├── font1.woff2 │ │ ├── font2.woff2 │ │ ├── font3.woff2 │ │ └── font4.woff2 │ ├── icons │ │ ├── adobexdicon.svg │ │ ├── apiicon.svg │ │ ├── axiosicon.svg │ │ ├── canvaicon.svg │ │ ├── car-icon.svg │ │ ├── cssicon.svg │ │ ├── expressicon.svg │ │ ├── expressiconwhite.svg │ │ ├── figmaicon.svg │ │ ├── hardware-icon.svg │ │ ├── htmlicon.svg │ │ ├── javascripticon.svg │ │ ├── jwticon.svg │ │ ├── mongoicon.svg │ │ ├── netlifyicon.svg │ │ ├── nextjsicon.svg │ │ ├── nextjsiconwhite.svg │ │ ├── nodejsicon.svg │ │ ├── reacticon.svg │ │ ├── rendericon.svg │ │ ├── sassicon.svg │ │ ├── shopifyicon.svg │ │ ├── spotifyicon.svg │ │ ├── tailwindicon.svg │ │ ├── travel-icon.svg │ │ ├── trelloicon.svg │ │ ├── typescripticon.svg │ │ ├── vueicon.svg │ │ ├── webflowicon.svg │ │ └── wordpressicon.svg │ ├── img │ │ ├── bannerbg.webp │ │ ├── instor_mockup.webp │ │ ├── mask.svg │ │ ├── me.webp │ │ ├── me2.webp │ │ ├── silentmoon_mockup.webp │ │ └── tasty_mockup.webp │ └── lib │ │ ├── data.tsx │ │ ├── hooks.tsx │ │ └── types.tsx ├── components │ ├── AboutMe.tsx │ ├── BannerQuote.tsx │ ├── Button.tsx │ ├── Contact.tsx │ ├── Divider.tsx │ ├── Footer.tsx │ ├── HeaderIntro.tsx │ ├── Imprint.tsx │ ├── LanguageSwitch.tsx │ ├── Listener.tsx │ ├── NavBar.tsx │ ├── ParallaxText.tsx │ ├── Privacy.tsx │ ├── ProjectSlider.tsx │ ├── RadialGradient.tsx │ ├── ScrollProgress.tsx │ ├── ServiceStatus.tsx │ ├── SideBarRight.tsx │ ├── SiteBarLeft.tsx │ ├── SkillSection.tsx │ ├── TechStack.tsx │ └── theme-switch.tsx ├── context │ ├── active-section-context.tsx │ ├── language-context.tsx │ └── theme-context.tsx ├── hooks │ └── useQuoteAnimation.tsx ├── index.css ├── layout │ └── layout.tsx ├── main.tsx ├── pages │ └── Home.tsx └── vite-env.d.ts ├── tailwind.config.js ├── tsconfig.json ├── tsconfig.node.json └── vite.config.ts /.env-init: -------------------------------------------------------------------------------- 1 | API_BASE_URL="" your backend for sending form requests 2 | -------------------------------------------------------------------------------- /.eslintrc.cjs: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | root: true, 3 | env: { browser: true, es2020: true }, 4 | extends: [ 5 | 'eslint:recommended', 6 | 'plugin:@typescript-eslint/recommended', 7 | 'plugin:react-hooks/recommended', 8 | ], 9 | ignorePatterns: ['dist', '.eslintrc.cjs'], 10 | parser: '@typescript-eslint/parser', 11 | plugins: ['react-refresh'], 12 | rules: { 13 | 'react-refresh/only-export-components': [ 14 | 'warn', 15 | { allowConstantExport: true }, 16 | ], 17 | }, 18 | } 19 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Logs 2 | logs 3 | *.log 4 | npm-debug.log* 5 | yarn-debug.log* 6 | yarn-error.log* 7 | pnpm-debug.log* 8 | lerna-debug.log* 9 | .env 10 | node_modules 11 | dist 12 | dist-ssr 13 | *.local 14 | 15 | # Editor directories and files 16 | .vscode/* 17 | !.vscode/extensions.json 18 | .idea 19 | .DS_Store 20 | *.suo 21 | *.ntvs* 22 | *.njsproj 23 | *.sln 24 | *.sw? 25 | -------------------------------------------------------------------------------- /CODE_OF_CONDUCT.md: -------------------------------------------------------------------------------- 1 | # Contributor Covenant Code of Conduct 2 | 3 | ## Our Pledge 4 | 5 | We as members, contributors, and leaders pledge to make participation in our 6 | community a harassment-free experience for everyone, regardless of age, body 7 | size, visible or invisible disability, ethnicity, sex characteristics, gender 8 | identity and expression, level of experience, education, socio-economic status, 9 | nationality, personal appearance, race, religion, or sexual identity 10 | and orientation. 11 | 12 | We pledge to act and interact in ways that contribute to an open, welcoming, 13 | diverse, inclusive, and healthy community. 14 | 15 | ## Our Standards 16 | 17 | Examples of behavior that contributes to a positive environment for our 18 | community include: 19 | 20 | * Demonstrating empathy and kindness toward other people 21 | * Being respectful of differing opinions, viewpoints, and experiences 22 | * Giving and gracefully accepting constructive feedback 23 | * Accepting responsibility and apologizing to those affected by our mistakes, 24 | and learning from the experience 25 | * Focusing on what is best not just for us as individuals, but for the 26 | overall community 27 | 28 | Examples of unacceptable behavior include: 29 | 30 | * The use of sexualized language or imagery, and sexual attention or 31 | advances of any kind 32 | * Trolling, insulting or derogatory comments, and personal or political attacks 33 | * Public or private harassment 34 | * Publishing others' private information, such as a physical or email 35 | address, without their explicit permission 36 | * Other conduct which could reasonably be considered inappropriate in a 37 | professional setting 38 | 39 | ## Enforcement Responsibilities 40 | 41 | Community leaders are responsible for clarifying and enforcing our standards of 42 | acceptable behavior and will take appropriate and fair corrective action in 43 | response to any behavior that they deem inappropriate, threatening, offensive, 44 | or harmful. 45 | 46 | Community leaders have the right and responsibility to remove, edit, or reject 47 | comments, commits, code, wiki edits, issues, and other contributions that are 48 | not aligned to this Code of Conduct, and will communicate reasons for moderation 49 | decisions when appropriate. 50 | 51 | ## Scope 52 | 53 | This Code of Conduct applies within all community spaces, and also applies when 54 | an individual is officially representing the community in public spaces. 55 | Examples of representing our community include using an official e-mail address, 56 | posting via an official social media account, or acting as an appointed 57 | representative at an online or offline event. 58 | 59 | ## Enforcement 60 | 61 | Instances of abusive, harassing, or otherwise unacceptable behavior may be 62 | reported to the community leaders responsible for enforcement at 63 | hello@alpaycelik.dev. 64 | All complaints will be reviewed and investigated promptly and fairly. 65 | 66 | All community leaders are obligated to respect the privacy and security of the 67 | reporter of any incident. 68 | 69 | ## Enforcement Guidelines 70 | 71 | Community leaders will follow these Community Impact Guidelines in determining 72 | the consequences for any action they deem in violation of this Code of Conduct: 73 | 74 | ### 1. Correction 75 | 76 | **Community Impact**: Use of inappropriate language or other behavior deemed 77 | unprofessional or unwelcome in the community. 78 | 79 | **Consequence**: A private, written warning from community leaders, providing 80 | clarity around the nature of the violation and an explanation of why the 81 | behavior was inappropriate. A public apology may be requested. 82 | 83 | ### 2. Warning 84 | 85 | **Community Impact**: A violation through a single incident or series 86 | of actions. 87 | 88 | **Consequence**: A warning with consequences for continued behavior. No 89 | interaction with the people involved, including unsolicited interaction with 90 | those enforcing the Code of Conduct, for a specified period of time. This 91 | includes avoiding interactions in community spaces as well as external channels 92 | like social media. Violating these terms may lead to a temporary or 93 | permanent ban. 94 | 95 | ### 3. Temporary Ban 96 | 97 | **Community Impact**: A serious violation of community standards, including 98 | sustained inappropriate behavior. 99 | 100 | **Consequence**: A temporary ban from any sort of interaction or public 101 | communication with the community for a specified period of time. No public or 102 | private interaction with the people involved, including unsolicited interaction 103 | with those enforcing the Code of Conduct, is allowed during this period. 104 | Violating these terms may lead to a permanent ban. 105 | 106 | ### 4. Permanent Ban 107 | 108 | **Community Impact**: Demonstrating a pattern of violation of community 109 | standards, including sustained inappropriate behavior, harassment of an 110 | individual, or aggression toward or disparagement of classes of individuals. 111 | 112 | **Consequence**: A permanent ban from any sort of public interaction within 113 | the community. 114 | 115 | ## Attribution 116 | 117 | This Code of Conduct is adapted from the [Contributor Covenant][homepage], 118 | version 2.0, available at 119 | https://www.contributor-covenant.org/version/2/0/code_of_conduct.html. 120 | 121 | Community Impact Guidelines were inspired by [Mozilla's code of conduct 122 | enforcement ladder](https://github.com/mozilla/diversity). 123 | 124 | [homepage]: https://www.contributor-covenant.org 125 | 126 | For answers to common questions about this code of conduct, see the FAQ at 127 | https://www.contributor-covenant.org/faq. Translations are available at 128 | https://www.contributor-covenant.org/translations. 129 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2023 Alpay Celik 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Portfolio Webseite 2 | 3 | This is a portfolio website built using React, Tailwind CSS, and TypeScript. The website showcases my skills and projects as a full-stack developer. For the contactform i used a backend, which is build on node.js and express. 4 | 5 | ## Demo 6 | 7 | Screenshot 8 | 9 | You can also check out the live demo of the portfolio website [here](https://alpaycelik.dev). 10 | 11 | ## Features 12 | 13 | - SEO optimized 14 | - User settings stored in session storage 15 | - Dark and Light mode available 16 | - Easy data modification through a single `data.tsx` file 17 | - Gziped and lazy loaded Data 18 | - Developed first with the Mobile First methodology, then for desktop. 19 | - Compatible with all mobile devices and with a beautiful and pleasant user interface. 20 | - Smooth scrolling in each section.Contains animations when scrolling. 21 | - Uptime Service with colored animation 22 | 23 | ## Installation 24 | 25 | Clone the Repo 26 | 27 | ```bash 28 | git clone 29 | ``` 30 | 31 | Installation of dependencies 32 | 33 | ```bash 34 | npm i or npm install 35 | ``` 36 | 37 | Start Server 38 | 39 | ```bash 40 | npm run dev 41 | ``` 42 | 43 | ## Environment Variables 44 | 45 | To run this project, you will need to add the following environment variables to your .env file. See .env-init in root directory 46 | 47 | `API_BASE_URL` 48 | 49 | `API_SERVICESTATUS_URL` 50 | 51 | ## Tech Stack 52 | 53 | **Client:** React, React Router Dom, Tailwind CSS, Typescript, Axios, Framer Motion, GSAP, Prism React Renderer, React Icons, React Intersection Observer, React Toastify, React Tooltip, Reactjs Popup, Swiper, Rollup Plugin Gzip 54 | 55 | **Server:** Node, Express, NodeMailer 56 | 57 | ## Support 58 | 59 | If you find this project helpful or would like to support my work, you can ⭐ this Repo 60 | -------------------------------------------------------------------------------- /SECURITY.md: -------------------------------------------------------------------------------- 1 | # Security Policy 2 | 3 | ## Reporting Security Issues 4 | 5 | If you believe you have found a security vulnerability, we encourage you to let us know right away. 6 | 7 | We will investigate all legitimate reports and do our best to quickly fix the problem. 8 | 9 | Email hello@alpaycelik.dev to disclose any security vulnerabilities. 10 | -------------------------------------------------------------------------------- /fullpage.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AlpayC/portfolio_site/2677889a6f23fb2be16f18a1327124600c9ab550/fullpage.png -------------------------------------------------------------------------------- /index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 11 | Alpay Celik - Fullstack Webentwickler | Portfolioseite 12 | 13 | 14 |
15 | 16 | 17 | 18 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "finaleseite2", 3 | "private": true, 4 | "version": "0.0.0", 5 | "type": "module", 6 | "scripts": { 7 | "dev": "vite", 8 | "build": "tsc && vite build", 9 | "lint": "eslint . --ext ts,tsx --report-unused-disable-directives --max-warnings 0", 10 | "preview": "vite preview" 11 | }, 12 | "dependencies": { 13 | "@emailjs/browser": "^3.11.0", 14 | "@motionone/utils": "^10.16.3", 15 | "@types/dotenv": "^8.2.0", 16 | "axios": "^1.5.1", 17 | "dotenv": "^16.3.1", 18 | "framer-motion": "^10.16.4", 19 | "gsap": "^3.12.2", 20 | "prism-react-renderer": "^2.0.6", 21 | "react": "^18.2.0", 22 | "react-dom": "^18.2.0", 23 | "react-icons": "^4.11.0", 24 | "react-intersection-observer": "^9.5.2", 25 | "react-router-dom": "^6.15.0", 26 | "react-toastify": "^9.1.3", 27 | "react-tooltip": "^5.21.1", 28 | "reactjs-popup": "^2.0.6", 29 | "swiper": "^10.2.0", 30 | "web-vitals": "^3.5.0" 31 | }, 32 | "devDependencies": { 33 | "@types/react": "^18.2.21", 34 | "@types/react-dom": "^18.2.7", 35 | "@typescript-eslint/eslint-plugin": "^6.0.0", 36 | "@typescript-eslint/parser": "^6.0.0", 37 | "@vitejs/plugin-react": "^4.0.3", 38 | "autoprefixer": "^10.4.15", 39 | "eslint": "^8.45.0", 40 | "eslint-plugin-react-hooks": "^4.6.0", 41 | "eslint-plugin-react-refresh": "^0.4.3", 42 | "postcss": "^8.4.28", 43 | "rollup-plugin-gzip": "^3.1.0", 44 | "tailwindcss": "^3.3.3", 45 | "typescript": "^5.0.2", 46 | "vite": "^4.4.5" 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /postcss.config.js: -------------------------------------------------------------------------------- 1 | export default { 2 | plugins: { 3 | tailwindcss: {}, 4 | autoprefixer: {}, 5 | }, 6 | } 7 | -------------------------------------------------------------------------------- /public/.htaccess: -------------------------------------------------------------------------------- 1 | # ---------------------------------------------------------------------- 2 | # | GZip pre-compressed content | 3 | # ---------------------------------------------------------------------- 4 | 5 | # Serve gzip compressed CSS, JS, HTML, SVG, ICS, and JSON files if they exist 6 | # and if the client accepts gzip encoding. 7 | # 8 | # (!) To make this part relevant, you need to generate encoded files by your 9 | # own. Enabling this part will not auto-generate gziped files. 10 | # 11 | # https://httpd.apache.org/docs/current/mod/mod_deflate.html#precompressed 12 | # 13 | # (1) Removing default MIME Type for .gz files allowing to add custom 14 | # sub-types. 15 | # You may prefer using less generic extensions such as .html_gz in order to 16 | # keep the default behavior regarding .gz files. 17 | # https://httpd.apache.org/docs/current/mod/mod_mime.html#removetype 18 | 19 | 20 | 21 | RewriteCond %{HTTP:Accept-Encoding} gzip 22 | RewriteCond %{REQUEST_FILENAME}\.gz -f 23 | RewriteRule \.(css|ics|js|json|html|svg)$ %{REQUEST_URI}.gz [L] 24 | 25 | # Prevent mod_deflate double gzip 26 | RewriteRule \.gz$ - [E=no-gzip:1] 27 | 28 | 29 | 30 | 31 | # (1) 32 | RemoveType gz 33 | 34 | # Serve correct content types 35 | AddType text/css css.gz 36 | AddType text/calendar ics.gz 37 | AddType text/javascript js.gz 38 | AddType application/json json.gz 39 | AddType text/html html.gz 40 | AddType image/svg+xml svg.gz 41 | 42 | # Serve correct content charset 43 | AddCharset utf-8 .css.gz \ 44 | .ics.gz \ 45 | .js.gz \ 46 | .json.gz 47 | 48 | 49 | 50 | # Force proxies to cache gzipped and non-gzipped files separately 51 | Header append Vary Accept-Encoding 52 | 53 | 54 | 55 | 56 | 57 | # Serve correct encoding type 58 | AddEncoding gzip .gz 59 | 60 | 61 | -------------------------------------------------------------------------------- /public/vite.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /screenshot.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AlpayC/portfolio_site/2677889a6f23fb2be16f18a1327124600c9ab550/screenshot.jpg -------------------------------------------------------------------------------- /src/App.css: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AlpayC/portfolio_site/2677889a6f23fb2be16f18a1327124600c9ab550/src/App.css -------------------------------------------------------------------------------- /src/App.tsx: -------------------------------------------------------------------------------- 1 | import "./App.css"; 2 | import { BrowserRouter, Routes, Route } from "react-router-dom"; 3 | import Home from "./pages/Home"; 4 | import ActiveSectionContextProvider from "./context/active-section-context"; 5 | import ThemeContextProvider from "./context/theme-context"; 6 | import LanguageContextProvider from "./context/language-context"; 7 | 8 | function App() { 9 | return ( 10 | <> 11 | 12 | 13 | 14 | 15 | 16 | }> 17 | }> 18 | }> 19 | 20 | 21 | 22 | 23 | 24 | 25 | ); 26 | } 27 | 28 | export default App; 29 | -------------------------------------------------------------------------------- /src/assets/fonts/font1.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AlpayC/portfolio_site/2677889a6f23fb2be16f18a1327124600c9ab550/src/assets/fonts/font1.woff2 -------------------------------------------------------------------------------- /src/assets/fonts/font2.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AlpayC/portfolio_site/2677889a6f23fb2be16f18a1327124600c9ab550/src/assets/fonts/font2.woff2 -------------------------------------------------------------------------------- /src/assets/fonts/font3.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AlpayC/portfolio_site/2677889a6f23fb2be16f18a1327124600c9ab550/src/assets/fonts/font3.woff2 -------------------------------------------------------------------------------- /src/assets/fonts/font4.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AlpayC/portfolio_site/2677889a6f23fb2be16f18a1327124600c9ab550/src/assets/fonts/font4.woff2 -------------------------------------------------------------------------------- /src/assets/icons/adobexdicon.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /src/assets/icons/apiicon.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /src/assets/icons/axiosicon.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /src/assets/icons/canvaicon.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /src/assets/icons/car-icon.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /src/assets/icons/cssicon.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /src/assets/icons/expressicon.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /src/assets/icons/expressiconwhite.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /src/assets/icons/figmaicon.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /src/assets/icons/hardware-icon.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /src/assets/icons/htmlicon.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /src/assets/icons/javascripticon.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /src/assets/icons/jwticon.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /src/assets/icons/mongoicon.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 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 | -------------------------------------------------------------------------------- /src/assets/icons/netlifyicon.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /src/assets/icons/nextjsicon.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /src/assets/icons/nextjsiconwhite.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /src/assets/icons/nodejsicon.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /src/assets/icons/reacticon.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /src/assets/icons/rendericon.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /src/assets/icons/sassicon.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /src/assets/icons/shopifyicon.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /src/assets/icons/spotifyicon.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /src/assets/icons/tailwindicon.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /src/assets/icons/travel-icon.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /src/assets/icons/trelloicon.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | -------------------------------------------------------------------------------- /src/assets/icons/typescripticon.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /src/assets/icons/vueicon.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /src/assets/icons/webflowicon.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /src/assets/icons/wordpressicon.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /src/assets/img/bannerbg.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AlpayC/portfolio_site/2677889a6f23fb2be16f18a1327124600c9ab550/src/assets/img/bannerbg.webp -------------------------------------------------------------------------------- /src/assets/img/instor_mockup.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AlpayC/portfolio_site/2677889a6f23fb2be16f18a1327124600c9ab550/src/assets/img/instor_mockup.webp -------------------------------------------------------------------------------- /src/assets/img/mask.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /src/assets/img/me.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AlpayC/portfolio_site/2677889a6f23fb2be16f18a1327124600c9ab550/src/assets/img/me.webp -------------------------------------------------------------------------------- /src/assets/img/me2.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AlpayC/portfolio_site/2677889a6f23fb2be16f18a1327124600c9ab550/src/assets/img/me2.webp -------------------------------------------------------------------------------- /src/assets/img/silentmoon_mockup.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AlpayC/portfolio_site/2677889a6f23fb2be16f18a1327124600c9ab550/src/assets/img/silentmoon_mockup.webp -------------------------------------------------------------------------------- /src/assets/img/tasty_mockup.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AlpayC/portfolio_site/2677889a6f23fb2be16f18a1327124600c9ab550/src/assets/img/tasty_mockup.webp -------------------------------------------------------------------------------- /src/assets/lib/data.tsx: -------------------------------------------------------------------------------- 1 | import adobexdicon from "../../assets/icons/adobexdicon.svg"; 2 | import canvaicon from "../../assets/icons/canvaicon.svg"; 3 | import figmaicon from "../../assets/icons/figmaicon.svg"; 4 | import htmlicon from "../../assets/icons/htmlicon.svg"; 5 | import cssicon from "../../assets/icons/cssicon.svg"; 6 | import javascripticon from "../../assets/icons/javascripticon.svg"; 7 | import typescripticon from "../../assets/icons/typescripticon.svg"; 8 | import reacticon from "../../assets/icons/reacticon.svg"; 9 | import nextjsicon from "../../assets/icons/nextjsicon.svg"; 10 | import nodejsicon from "../../assets/icons/nodejsicon.svg"; 11 | import tailwindcssicon from "../../assets/icons/tailwindicon.svg"; 12 | import mongodbicon from "../../assets/icons/mongoicon.svg"; 13 | import vuejsicon from "../../assets/icons/vueicon.svg"; 14 | import expressicon from "../../assets/icons/expressicon.svg"; 15 | import sassscssicon from "../../assets/icons/sassicon.svg"; 16 | import trelloicon from "../../assets/icons/trelloicon.svg"; 17 | import apiicon from "../../assets/icons/apiicon.svg"; 18 | import axiosicon from "../../assets/icons/axiosicon.svg"; 19 | import spotifyicon from "../../assets/icons/spotifyicon.svg"; 20 | import netlifyicon from "../../assets/icons/netlifyicon.svg"; 21 | import rendericon from "../../assets/icons/rendericon.svg"; 22 | import jwticon from "../../assets/icons/jwticon.svg"; 23 | import wordpressicon from "../../assets/icons/wordpressicon.svg"; 24 | import shopifyicon from "../../assets/icons/shopifyicon.svg"; 25 | import webflowicon from "../../assets/icons/webflowicon.svg"; 26 | import tastyMockup from "../../assets/img/tasty_mockup.webp"; 27 | import instorMockup from "../../assets/img/instor_mockup.webp"; 28 | import silentmoonMockup from "../../assets/img/silentmoon_mockup.webp"; 29 | import profilepicture from "../img/me2.webp"; 30 | import caricon from "../../assets/icons/car-icon.svg"; 31 | import travelicon from "../../assets/icons/travel-icon.svg"; 32 | import hardwareicon from "../../assets/icons/hardware-icon.svg"; 33 | import nextjsiconwhite from "../../assets/icons/nextjsiconwhite.svg"; 34 | import expressiconwhite from "../../assets/icons/expressiconwhite.svg"; 35 | import { GoHome, GoPerson, GoMail, GoStack, GoProject } from "react-icons/go"; 36 | import { FiGithub, FiLink, FiLinkedin, FiMail } from "react-icons/fi"; 37 | import Imprint from "../../components/Imprint"; 38 | import Privacy from "../../components/Privacy"; 39 | 40 | export const headerIntroData = { 41 | title: { 42 | de: "Hi, ich bin Alpay", 43 | en: "Hi, I'm Alpay", 44 | }, 45 | subtitle: "Fullstack Developer ", 46 | description: { 47 | de: "Ich bin Alpay, ein Fullstack-Entwickler mit dem Ziel, meine Karriere voranzutreiben und an inspirierenden Projekten teilzunehmen. Hier präsentiere ich meine Arbeiten und meine Leidenschaft für die Webentwicklung. Lassen Sie uns gemeinsam digitale Lösungen gestalten und die Zukunft formen!", 48 | en: "I'm Alpay, a fullstack developer with the goal of advancing my career and participating in inspiring projects. Here I present my work and my passion for web development. Let's shape digital solutions together and shape the future!", 49 | }, 50 | buttons: [ 51 | { 52 | name: "Contact", 53 | label: { 54 | de: "Kontaktiere mich", 55 | en: "Contact me", 56 | }, 57 | icon: FiMail, 58 | color: "main-btn", 59 | }, 60 | { 61 | name: "Projects", 62 | label: { 63 | de: "Meine Projekte", 64 | en: "My Projects", 65 | }, 66 | icon: FiGithub, 67 | color: "secondary-btn", 68 | }, 69 | ], 70 | profilepicture: profilepicture, 71 | } as const; 72 | 73 | export const projectsData = [ 74 | { 75 | title: "Tasty App", 76 | description: 77 | "Eine Rezepte App, die wir als Team mit React und der MealDB API gebaut haben. Ich war der Front-End Entwickler und habe Features wie Voice Search oder Print to PDF programmiert. Das Design wurde mit Figma erstellt. Die Website ist responsive und mobile-optimiert.", 78 | description_EN: 79 | "A recipe app that we built as a team with React and the MealDB API. I was the front-end developer and programmed features like voice search or print to PDF. The design was created with Figma. The website is responsive and mobile-optimized.", 80 | technologies: [ 81 | { name: "Html", icon: htmlicon }, 82 | { name: "CSS", icon: cssicon }, 83 | { name: "JavaScript", icon: javascripticon }, 84 | { name: "REST Api", icon: apiicon }, 85 | { name: "React", icon: reacticon }, 86 | { name: "Figma", icon: figmaicon }, 87 | { name: "Canva", icon: canvaicon }, 88 | { name: "Netlify", icon: netlifyicon }, 89 | { name: "Trello", icon: trelloicon }, 90 | ], 91 | image: tastyMockup, 92 | deploymenturl: "https://delightful-cheesecake-9b19f0.netlify.app/", 93 | githuburl: "https://github.com/AlpayC/Frontend_Abschlussprojekt_Tasty", 94 | githubicon: FiGithub, 95 | deploymenticon: FiLink, 96 | colors: { 97 | main: "main-btn", 98 | second: "secondary-btn", 99 | icon: "white", 100 | projectcolor: "#70B9BE", 101 | }, 102 | }, 103 | { 104 | title: "Silentmoon", 105 | description: 106 | "Eine Yoga und Meditations App, die wir als Team mit React, MongoDB, Express und Node.js gebaut haben. Meine Aufgabe als Gitmaster und Backend Entwickler bestand darin, das Backend mit Anbindung anhand einer Restful API zu programmieren und die Datenbank in MongoDB zu modellieren.", 107 | description_EN: 108 | "A yoga and meditation app that we built as a team with React, MongoDB, Express and Node.js. My task as a gitmaster and backend developer was to program the backend with connection using a restful API and to model the database in MongoDB.", 109 | technologies: [ 110 | { name: "Html", icon: htmlicon }, 111 | { name: "CSS", icon: cssicon }, 112 | { name: "JavaScript", icon: javascripticon }, 113 | { name: "Spotify Api", icon: spotifyicon }, 114 | { name: "React", icon: reacticon }, 115 | { name: "JWT & Bcrypt", icon: jwticon }, 116 | { name: "Axios", icon: axiosicon }, 117 | { name: "MongoDB", icon: mongodbicon }, 118 | { name: "Express", icon: expressiconwhite }, 119 | { name: "Node.js", icon: nodejsicon }, 120 | { name: "Figma", icon: figmaicon }, 121 | { name: "Render", icon: rendericon }, 122 | ], 123 | image: silentmoonMockup, 124 | deploymenturl: "https://silentmoon-grpw.onrender.com/", 125 | githuburl: 126 | "https://github.com/AlpayC/Fullstack_Abschlussprojekt_SilentMoon", 127 | githubicon: FiGithub, 128 | deploymenticon: FiLink, 129 | colors: { 130 | main: "main-btn", 131 | second: "secondary-btn", 132 | icon: "white", 133 | projectcolor: "#FFD5BD", 134 | }, 135 | }, 136 | { 137 | title: "Furniture Organizer", 138 | description: 139 | "Eine Möbel-Organizer App, die wir als Duo-Team mit React, MongoDB, Express und Node.js programmiert haben. Als Gitmaster habe ich die Verknüpfung des Frontends mit dem Backend und die Datenbankmodellierung übernommen. Die App ist responsive und mobile-optimiert.", 140 | description_EN: 141 | "A furniture organizer app that we programmed as a duo team with React, MongoDB, Express and Node.js. As a gitmaster, I took over the connection of the frontend to the backend and the database modeling. The app is responsive and mobile-optimized.", 142 | technologies: [ 143 | { name: "Html", icon: htmlicon }, 144 | { name: "CSS", icon: cssicon }, 145 | { name: "JavaScript", icon: javascripticon }, 146 | { name: "React", icon: reacticon }, 147 | { name: "JWT & Bcrypt", icon: jwticon }, 148 | { name: "Axios", icon: axiosicon }, 149 | { name: "MongoDB", icon: mongodbicon }, 150 | { name: "Express", icon: expressiconwhite }, 151 | { name: "Node.js", icon: nodejsicon }, 152 | { name: "Figma", icon: figmaicon }, 153 | { name: "Render", icon: rendericon }, 154 | { name: "Trello", icon: trelloicon }, 155 | ], 156 | image: instorMockup, 157 | deploymenturl: "https://mern-haushaltsbuch.onrender.com/", 158 | githuburl: "https://github.com/AlpayC/Furniture_MERN", 159 | githubicon: FiGithub, 160 | deploymenticon: FiLink, 161 | colors: { 162 | main: "main-btn", 163 | second: "secondary-btn", 164 | icon: "white", 165 | projectcolor: "#E3964A", 166 | }, 167 | }, 168 | ] as const; 169 | 170 | export const liveTickerData = { 171 | content: { 172 | de: "Weitere Projekte auf Github", 173 | en: "More Projects on Github", 174 | }, 175 | } as const; 176 | 177 | export const skillsDataWeb = [ 178 | { 179 | skillsTitle: "WebDevelopment", 180 | skills: [ 181 | { 182 | title: "HTML", 183 | hash: "#html", 184 | icon: htmlicon, 185 | color: "#F1662A", 186 | }, 187 | { 188 | title: "CSS", 189 | hash: "#CSS", 190 | icon: cssicon, 191 | color: "#1572B6", 192 | }, 193 | { 194 | title: "JavaScript", 195 | hash: "#JavaScript", 196 | icon: javascripticon, 197 | color: "#F7DF1E", 198 | }, 199 | { 200 | title: "TypeScript", 201 | hash: "#TypeScript", 202 | icon: typescripticon, 203 | color: "#007ACC", 204 | }, 205 | { 206 | title: "React", 207 | hash: "#React", 208 | icon: reacticon, 209 | color: "#61DAFB", 210 | }, 211 | { 212 | title: "Next.js", 213 | hash: "#Next.js", 214 | icon: [nextjsicon, nextjsiconwhite], 215 | color: ["#000000", "#FFFFFF"], 216 | }, 217 | { 218 | title: "Node.js", 219 | hash: "#Node.js", 220 | icon: nodejsicon, 221 | color: "#339933", 222 | }, 223 | { 224 | title: "Tailwind", 225 | hash: "#Tailwind", 226 | icon: tailwindcssicon, 227 | color: "#38B2AC", 228 | }, 229 | { 230 | title: "MongoDB", 231 | hash: "#MongoDB", 232 | icon: mongodbicon, 233 | color: "#449C45", 234 | }, 235 | { 236 | title: "Vue.js", 237 | hash: "#Vue.js", 238 | icon: vuejsicon, 239 | color: "#4FC08D", 240 | }, 241 | { 242 | title: "Express", 243 | hash: "#Express", 244 | icon: [expressicon, expressiconwhite], 245 | color: ["#000000", "#FFFFFF"], 246 | }, 247 | { 248 | title: "SASS/SCSS", 249 | hash: "#SASS/SCSS", 250 | icon: sassscssicon, 251 | color: "#CC6699", 252 | }, 253 | ], 254 | }, 255 | ] as const; 256 | 257 | export const skillsDataDesign = [ 258 | { 259 | skillsTitle: "Design", 260 | skills: [ 261 | { title: "Figma", hash: "#Figma", icon: figmaicon, color: "#F24E1E" }, 262 | { 263 | title: "Adobe XD", 264 | hash: "#Adobe XD", 265 | icon: adobexdicon, 266 | color: "#FF61F6", 267 | }, 268 | { title: "Canva", hash: "#Canva", icon: canvaicon, color: "#00C4CC" }, 269 | ], 270 | }, 271 | ] as const; 272 | 273 | export const skillsDataCMS = [ 274 | { 275 | skillsTitle: "CMS", 276 | skills: [ 277 | { 278 | title: "WordPress", 279 | hash: "#WordPress", 280 | icon: wordpressicon, 281 | color: "#21759B", 282 | }, 283 | { 284 | title: "Shopify", 285 | hash: "#Shopify", 286 | icon: shopifyicon, 287 | color: "#7AB55C", 288 | }, 289 | { 290 | title: "Webflow", 291 | hash: "#Webflow", 292 | icon: webflowicon, 293 | color: "#4353FF", 294 | }, 295 | ], 296 | }, 297 | ] as const; 298 | 299 | export const navLinks = [ 300 | { de: "Home", en: "Home", hash: "#home", icon: GoHome }, 301 | { de: "Skills", en: "Skills", hash: "#skills", icon: GoStack }, 302 | { de: "Projekte", en: "Projects", hash: "#projects", icon: GoProject }, 303 | { de: "Über mich", en: "About me", hash: "#about-me", icon: GoPerson }, 304 | { de: "Kontakt", en: "Contact", hash: "#contact", icon: GoMail }, 305 | ] as const; 306 | 307 | export const FooterLinks = [ 308 | { de: "Impressum", en: "Imprint", hash: "#imprint", data: }, 309 | { de: "Datenschutz", en: "Privacy", hash: "#privacy", data: }, 310 | ] as const; 311 | 312 | export const sideBarRightMail = { 313 | link: "mailto:myemail@com", 314 | text: "myemail@com", 315 | } as const; 316 | 317 | export const sideBarLeftSocials = [ 318 | { 319 | link: "https://www.linkedin.com/in/alpay/", 320 | icon: FiLinkedin, 321 | altimgname: "linkedin", 322 | }, 323 | { 324 | link: "https://github.com/AlpayC", 325 | icon: FiGithub, 326 | altimgname: "github", 327 | }, 328 | { 329 | link: "mailto:myemail@com", 330 | icon: FiMail, 331 | altimgname: "mail", 332 | }, 333 | ] as const; 334 | 335 | export const quotesData = [ 336 | { 337 | de: '"Es ist überhaupt nicht wichtig, es beim ersten Mal richtig zu machen. Es ist entscheidend, es beim letzten Mal richtig zu machen."', 338 | en: `"It's not at all important to get it right the first time. It's vitally important to get it right the last time."`, 339 | author: "Andrew Hunt", 340 | }, 341 | { 342 | de: '"Das Web ist wie eine Leinwand und der Code ist die Farbe. Erschaffe dein Meisterwerk."', 343 | en: `"The web is like a canvas, and code is the paint. Create your masterpiece."`, 344 | }, 345 | ] as const; 346 | 347 | export const aboutMeData = { 348 | title: "Über mich", 349 | title_EN: "About me", 350 | description: "Ein paar Codeschnippsel über mich", 351 | description_EN: "A few code snippets about me", 352 | paragraphs_DE: [ 353 | { 354 | title: "Die Schaltkreise meines Herzens", 355 | description: 356 | "Wenn ich nicht in der digitalen Welt unterwegs bin, durchstreife ich die faszinierende Welt der Technik und Hardware. Schaltkreise und Lötstellen sind für mich wie Puzzleteile eines aufregenden Abenteuers.", 357 | icon: hardwareicon, 358 | }, 359 | { 360 | title: "Auf der Überholspur des Lebens", 361 | description: 362 | "Neben dem Coden befinde ich mich gerne auf der Überholspur – im wahrsten Sinne des Wortes. Autos sind meine Leidenschaft, und ich genieße es, mit PS-starken Maschinen auf unbekannten Straßen unterwegs zu sein.", 363 | icon: caricon, 364 | }, 365 | { 366 | title: "Entdeckungsfreude als Lebensmotto", 367 | description: 368 | "Meine Reise als Webentwickler ist nur ein Teil meines Lebenswegs. Ich lebe nach dem Motto, dass das Abenteuer erst beginnt, wenn man das Bekannte hinter sich lässt. Das Entdecken neuer Orte ist meine Form der kreativen Inspiration.", 369 | icon: travelicon, 370 | }, 371 | ], 372 | paragraphs_EN: [ 373 | { 374 | title: "The Circuits of My Heart", 375 | description: 376 | "When I'm not navigating the digital world, I explore the fascinating realm of technology and hardware. Circuits and solder joints are like puzzle pieces to me in an exciting adventure.", 377 | icon: hardwareicon, 378 | }, 379 | { 380 | title: "On the Fast Lane of Life", 381 | description: 382 | "Besides coding, I like to be on the fast lane - in the truest sense of the word. Cars are my passion, and I enjoy being on unknown roads with powerful machines.", 383 | icon: caricon, 384 | }, 385 | { 386 | title: "The Joy of Discovery as a Life Motto", 387 | description: 388 | "My journey as a web developer is only a part of my life path. I live by the motto that the adventure only begins when you leave the familiar behind. Discovering new places and cultures is my form of creative inspiration.", 389 | icon: travelicon, 390 | }, 391 | ], 392 | }; 393 | 394 | export const contactData = { 395 | title: { 396 | de: "Kontakt", 397 | en: "Contact", 398 | }, 399 | description: { 400 | de: "Schreib mir eine Nachricht und ich melde mich bei dir.", 401 | en: "Write me a message and I will get back to you.", 402 | }, 403 | inputfields: [ 404 | { 405 | name: "name", 406 | placeholder: { 407 | de: "Dein Name", 408 | en: "Your Name", 409 | }, 410 | type: "text", 411 | validation: { 412 | de: "Bitte gebe deinen Namen ein", 413 | en: "Please fill in your name", 414 | }, 415 | pattern: "{2}", 416 | }, 417 | { 418 | name: "email", 419 | placeholder: { 420 | de: "Deine E-Mail Adresse", 421 | en: "Your E-Mail", 422 | }, 423 | type: "email", 424 | validation: { 425 | de: "Bitte gebe deine Email ein", 426 | en: "Please fill in your email", 427 | }, 428 | pattern: "[@]{4}", 429 | }, 430 | { 431 | name: "subject", 432 | placeholder: { 433 | de: "Deine Betreff", 434 | en: "Your Subject", 435 | }, 436 | type: "text", 437 | validation: { 438 | de: "Bitte gebe einen Betreff ein", 439 | en: "Please fill in your subject", 440 | }, 441 | pattern: "{10}", 442 | }, 443 | ], 444 | textarea: { 445 | placeholder: { 446 | de: "Deine Nachricht", 447 | en: "Your Message", 448 | }, 449 | name: "message", 450 | rows: 10, 451 | validation: { 452 | de: "Bitte gebe deine Nachricht ein", 453 | en: "Please fill in your message", 454 | }, 455 | pattern: "{10}", 456 | }, 457 | button: { 458 | value: { 459 | de: "Absenden", 460 | en: "Send", 461 | }, 462 | }, 463 | icon: FiMail, 464 | iconcolor: "#FFFFFF", 465 | colors: { 466 | main: "main-btn", 467 | second: "secondary-btn", 468 | icon: "white", 469 | }, 470 | privacyOptIn: { 471 | checkbox: { 472 | de: "Ich stimme zu, dass Alpay meine personenbezogenen Daten (Name und E-Mail-Adresse) verwenden darf, um mit mir Kontakt aufzunehmen.", 473 | en: "I agree that Alpay may use my personal data (name and e-mail address) to contact me.", 474 | }, 475 | description: { 476 | de: "Durch Übermittlung dieser Anfrage bestätigen Sie, dass Sie die Datenschutzerklärung gelesen haben", 477 | en: "By submitting this request, you acknowledge that you have read the Private Policy", 478 | }, 479 | }, 480 | } as const; 481 | 482 | export const toastMessages = { 483 | loadingProject: { 484 | de: "🦄 Die Live Demo wird gleich geöffnet. Server werden gestartet...", 485 | en: "🦄 The live demo will open shortly. Starting servers...", 486 | }, 487 | successEmailSent: { 488 | de: "🦄 Vielen Dank für deine Email. Ich werde mich schnellstmöglich bei dir melden", 489 | en: "🦄 Thank you for your email. I will get back to you as soon as possible", 490 | }, 491 | failedEmailSent: { 492 | de: "🦄 Leider hat der Versand deiner Email nicht geklappt. Bitte versuche es später noch einmal", 493 | en: "🦄 Unfortunately the sending of your email did not work. Please try again later", 494 | }, 495 | failedValidationName: { 496 | de: "Bitte gebe deinen Namen ein", 497 | en: "Please fill in your name", 498 | }, 499 | } as const; 500 | 501 | export const buttonLabels = { 502 | language: { 503 | de: "DE", 504 | en: "EN", 505 | }, 506 | } as const; 507 | 508 | export const directionStyles: Record = { 509 | "outer-right-to-inner-left": { 510 | marginRight: "4rem", 511 | }, 512 | "outer-left-to-inner-right": { 513 | marginLeft: "4rem", 514 | transform: "scaleX(-1)", 515 | }, 516 | "inner-right-to-middle": { 517 | width: "100%", 518 | transform: "scaleY(1)", 519 | display: "flex", 520 | flexDirection: "column", 521 | justifyContent: "center", 522 | alignItems: "center", 523 | }, 524 | "inner-left-to-middle": { 525 | width: "100%", 526 | transform: "scaleX(-1)", 527 | display: "flex", 528 | flexDirection: "column", 529 | justifyContent: "center", 530 | alignItems: "center", 531 | overflow: "hidden", 532 | }, 533 | "middle-to-inner-right": { 534 | width: "100%", 535 | transform: "scale(1,-1)", 536 | }, 537 | "middle-to-inner-left": { 538 | width: "100%", 539 | transform: "scale(-1,-1)", 540 | display: "flex", 541 | flexDirection: "column", 542 | justifyContent: "center", 543 | alignItems: "center", 544 | }, 545 | middle: { 546 | width: "100%", 547 | transform: "scaleX(-1)", 548 | display: "flex", 549 | flexDirection: "column", 550 | alignItems: "center", 551 | }, 552 | }; 553 | 554 | export const heightStyles: Record = { 555 | small: { 556 | heights: ["25rem", "15rem"], 557 | }, 558 | middle: { 559 | heights: ["35rem", "25rem"], 560 | }, 561 | large: { 562 | heights: ["45rem", "35rem"], 563 | }, 564 | extraLarge: { 565 | heights: ["55rem", "45rem"], 566 | }, 567 | }; 568 | 569 | export const spaceStyles: Record = { 570 | "outer-right-to-inner-left": { 571 | marginTop: "-6rem", 572 | width: "100%", 573 | }, 574 | "outer-left-to-inner-right": { 575 | marginTop: "-6rem", 576 | width: "100%", 577 | }, 578 | "inner-right-to-middle": { 579 | marginTop: "-20rem", 580 | width: "50%", 581 | zIndex: "-10", 582 | }, 583 | "inner-left-to-middle": { 584 | marginTop: "-10rem", 585 | width: "50%", 586 | zIndex: "-10", 587 | }, 588 | "middle-to-inner-right": { 589 | width: "75%", 590 | }, 591 | "middle-to-inner-left": { 592 | marginTop: "-2.5rem", 593 | width: "50%", 594 | }, 595 | middle: { 596 | marginTop: "-2.5rem", 597 | width: "0%", 598 | display: "none", 599 | }, 600 | }; 601 | 602 | export const widthStyles: Record = { 603 | "outer-right-to-inner-left": { 604 | widths: ["74.45%", "74.45%"], 605 | }, 606 | "outer-left-to-inner-right": { 607 | widths: ["75%", "75%"], 608 | }, 609 | "inner-right-to-middle": { 610 | widths: ["50.1%", "49%"], 611 | }, 612 | "inner-left-to-middle": { 613 | widths: ["50.1%", "49%"], 614 | }, 615 | "middle-to-inner-right": { 616 | widths: ["33.4%", "50.03%"], 617 | }, 618 | "middle-to-inner-left": { 619 | widths: ["50.1%", "49%"], 620 | }, 621 | middle: { 622 | widths: ["0%", "0%"], 623 | }, 624 | }; 625 | -------------------------------------------------------------------------------- /src/assets/lib/hooks.tsx: -------------------------------------------------------------------------------- 1 | import { useActiveSectionContext } from "../../context/active-section-context"; 2 | import { useEffect, useState } from "react"; 3 | import { useInView } from "react-intersection-observer"; 4 | import type { SectionName } from "./types"; 5 | 6 | export function useSectionInView(sectionName: SectionName, threshold = 0.75) { 7 | const isMobile = window.innerWidth <= 1024; 8 | const { ref, inView } = useInView({ 9 | threshold: isMobile ? 0.1 : threshold, 10 | }); 11 | const { setActiveSection, timeOfLastClick } = useActiveSectionContext(); 12 | 13 | useEffect(() => { 14 | if (inView && Date.now() - timeOfLastClick > 1000) { 15 | setActiveSection(sectionName); 16 | } 17 | }, [inView, setActiveSection, timeOfLastClick, sectionName]); 18 | 19 | return { 20 | ref, 21 | }; 22 | } 23 | 24 | export function useMousePosition() { 25 | const [mousePosition, setMousePosition] = useState({ x: null, y: null }); 26 | 27 | const updateMousePosition = (e: any) => { 28 | setMousePosition({ x: e.clientX, y: e.clientY }); 29 | }; 30 | 31 | useEffect(() => { 32 | window.addEventListener("mousemove", updateMousePosition); 33 | 34 | return () => window.removeEventListener("mousemove", updateMousePosition); 35 | }, []); 36 | 37 | return mousePosition; 38 | } 39 | -------------------------------------------------------------------------------- /src/assets/lib/types.tsx: -------------------------------------------------------------------------------- 1 | import { navLinks } from "./data"; 2 | 3 | export type SectionName = (typeof navLinks)[number]["en"]; 4 | -------------------------------------------------------------------------------- /src/components/AboutMe.tsx: -------------------------------------------------------------------------------- 1 | import React, { useRef } from "react"; 2 | import me from "../assets/img/me.webp"; 3 | import { aboutMeData } from "../assets/lib/data"; 4 | import { Autoplay, Pagination, Navigation } from "swiper/modules"; 5 | import { Swiper, SwiperSlide } from "swiper/react"; 6 | import { motion, useScroll, useTransform } from "framer-motion"; 7 | import "swiper/css"; 8 | import "swiper/css/pagination"; 9 | import "swiper/css/navigation"; 10 | import { useSectionInView } from "../assets/lib/hooks"; 11 | import { useLanguage } from "../context/language-context"; 12 | 13 | const AboutMe: React.FC = () => { 14 | const progressCircle = useRef(null); 15 | const progressContent = useRef(null); 16 | const { ref } = useSectionInView("About me"); 17 | const { language } = useLanguage(); 18 | const animationReference = useRef(null); 19 | const { scrollYProgress } = useScroll({ 20 | target: animationReference, 21 | offset: ["0 1", "1.33 1"], 22 | }); 23 | const scaleProgess = useTransform(scrollYProgress, [0, 1], [0.8, 1]); 24 | const opacityProgess = useTransform(scrollYProgress, [0, 1], [0.6, 1]); 25 | const onAutoplayTimeLeft = (_s: any, time: number, progress: number) => { 26 | if (progressCircle.current && progressContent.current) { 27 | progressCircle.current.style.setProperty( 28 | "--progress", 29 | String(1 - progress) 30 | ); 31 | progressContent.current.textContent = `${Math.ceil(time / 1000)}s`; 32 | } 33 | }; 34 | const paragraphs = 35 | language === "DE" ? aboutMeData.paragraphs_DE : aboutMeData.paragraphs_EN; 36 | 37 | return ( 38 | 39 |
40 |
41 | 49 |

50 | < 51 | {language === "DE" ? aboutMeData.title : aboutMeData.title_EN} 52 | /> 53 |

54 | 55 |

56 | {language === "DE" 57 | ? aboutMeData.description 58 | : aboutMeData.description_EN} 59 |

60 |
61 |
62 |
63 |
64 | {me} 65 |
66 | 80 | {paragraphs.map((paragraph, index) => ( 81 | 85 |
86 |
87 | {paragraph.icon} 92 |
93 |
94 |

{paragraph.title}

95 |
96 |
97 |
98 |
99 |

100 | <h3 101 | /> 102 |

103 |
104 |
105 |
106 |
107 |
108 |

109 | <h3 110 | /> 111 |

112 |
113 |
114 |

115 | {paragraph.description} 116 |

117 |
118 |
119 |
120 | ))} 121 |
125 | 126 | 127 | 128 | 129 |
130 |
131 |
132 |
133 |
134 | ); 135 | }; 136 | 137 | export default AboutMe; 138 | -------------------------------------------------------------------------------- /src/components/BannerQuote.tsx: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | 3 | import bannerBg from "../assets/img/bannerbg.webp"; 4 | import { quotesData } from "../assets/lib/data"; 5 | import { useLanguage } from "../context/language-context"; 6 | import { useQuoteAnimation } from "../hooks/useQuoteAnimation"; 7 | 8 | interface BannerProps { 9 | style: "withBG" | "noBG"; 10 | quoteIndex: number; 11 | containerType: string; 12 | } 13 | 14 | const BannerQuote: React.FC = ({ 15 | style, 16 | quoteIndex, 17 | containerType, 18 | }) => { 19 | const { language } = useLanguage(); 20 | 21 | const quoteTranslation = 22 | language === "DE" ? quotesData[quoteIndex].de : quotesData[quoteIndex].en; 23 | 24 | useQuoteAnimation(`.${containerType}-container h2`); 25 | 26 | return style === "withBG" ? ( 27 | 28 |
29 |
38 |
39 |

40 | {quoteTranslation} 41 |

42 |

{quotesData[0].author}

43 |
44 |
45 |
46 |
47 | ) : ( 48 | 49 |
50 |
51 |
52 |

53 | {quoteTranslation} 54 |

55 |
56 |
57 |
58 |
59 | ); 60 | }; 61 | 62 | export default BannerQuote; 63 | -------------------------------------------------------------------------------- /src/components/Button.tsx: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | import { Link } from "react-router-dom"; 3 | 4 | interface ButtonProps { 5 | onClick?: () => void; 6 | label?: string; 7 | value?: string; 8 | className?: string; 9 | link?: string; 10 | iconcolor?: string; 11 | iconSVG?: React.FC<{ className: string }>; 12 | buttoncolor?: string; 13 | buttonhovercolor?: string; 14 | type?: "button" | "submit" | "reset"; 15 | elementType?: "input" | "button"; 16 | } 17 | 18 | const Button: React.FC = ({ 19 | onClick, 20 | label, 21 | link, 22 | value, 23 | iconSVG: IconSVGComponent, 24 | buttoncolor, 25 | buttonhovercolor, 26 | type, 27 | elementType, 28 | }) => { 29 | const commonProps = { 30 | onClick, 31 | type, 32 | className: `text-white drop-shadow-2xl border-none py-4 px-8 rounded-lg text-[1.6rem] transition-all duration-200 flex flex-row gap-4 justify-center items-center cursor-pointer ${buttoncolor} ${buttonhovercolor} max-lg:text-3xl max-lg:py-8 max-lg:px-16 max-lg:rounded-xl 33 | shadow-xl hover:scale-100 hover:-translate-y-2 hover:drop-shadow-xl transition-all duration-200 w-max`, 34 | }; 35 | 36 | if (elementType === "input") { 37 | return ; 38 | } else { 39 | return ( 40 | 41 | 53 | 54 | ); 55 | } 56 | }; 57 | 58 | export default Button; 59 | -------------------------------------------------------------------------------- /src/components/Contact.tsx: -------------------------------------------------------------------------------- 1 | import React, { useState, useEffect, useRef } from "react"; 2 | import Button from "./Button"; 3 | import axios from "axios"; 4 | import { Highlight, themes } from "prism-react-renderer"; 5 | import { contactData, toastMessages } from "../assets/lib/data.tsx"; 6 | import { useSectionInView } from "../assets/lib/hooks"; 7 | import { useLanguage } from "../context/language-context"; 8 | import { ToastContainer, toast } from "react-toastify"; 9 | import { useTheme } from "../context/theme-context"; 10 | import { motion, useScroll, useTransform } from "framer-motion"; 11 | import "react-toastify/dist/ReactToastify.css"; 12 | 13 | const Contact: React.FC = () => { 14 | const apiBaseUrl = import.meta.env.VITE_API_BASE_URL || ""; 15 | 16 | const [name, setName] = useState(""); 17 | const [email, setEmail] = useState(""); 18 | const [subject, setSubject] = useState(""); 19 | const [message, setMessage] = useState(""); 20 | const [cursor, setCursor] = useState(""); 21 | const [lastUpdatedField, setLastUpdatedField] = useState(null); 22 | const { ref } = useSectionInView("Contact"); 23 | const { language } = useLanguage(); 24 | const { theme } = useTheme(); 25 | const [error, setError] = useState(null); 26 | 27 | const animationReference = useRef(null); 28 | const { scrollYProgress } = useScroll({ 29 | target: animationReference, 30 | offset: ["0 1", "1.33 1"], 31 | }); 32 | const scaleProgess = useTransform(scrollYProgress, [0, 1], [0.8, 1]); 33 | const opacityProgess = useTransform(scrollYProgress, [0, 1], [0.6, 1]); 34 | 35 | const notifySentForm: React.FormEventHandler = async (e) => { 36 | setError(null); 37 | console.log(error); 38 | 39 | e.preventDefault(); 40 | const data = new FormData(e.currentTarget); 41 | 42 | try { 43 | const response = await axios.post(apiBaseUrl, data); 44 | console.log(response); 45 | if (language === "DE") { 46 | toast.success(toastMessages.successEmailSent.de); 47 | } else { 48 | toast.success(toastMessages.successEmailSent.en); 49 | } 50 | } catch (error) { 51 | console.log(error); 52 | if (language === "DE") { 53 | toast.error(toastMessages.failedEmailSent.de); 54 | } else { 55 | toast.error(toastMessages.failedEmailSent.en); 56 | } 57 | setError("An Error occured, try again later"); 58 | } 59 | }; 60 | 61 | const handleInputFocus = (fieldName: string) => { 62 | setCursor(`${fieldName}${cursor}`); 63 | }; 64 | 65 | const wordWrap = ( 66 | text: string, 67 | maxLineLength: number, 68 | indentation: string 69 | ) => { 70 | const words = text.split(" "); 71 | let lines: string[] = []; 72 | let currentLine = ""; 73 | 74 | words.forEach((word) => { 75 | if (currentLine.length + word.length <= maxLineLength) { 76 | currentLine += word + " "; 77 | } else { 78 | lines.push(currentLine.trim()); 79 | currentLine = `${indentation}${word} `; 80 | } 81 | }); 82 | 83 | if (currentLine) { 84 | lines.push(currentLine.trim()); 85 | } 86 | 87 | return lines.join("\n"); 88 | }; 89 | 90 | const handleInputChange = ( 91 | e: 92 | | React.ChangeEvent 93 | | React.ChangeEvent 94 | ) => { 95 | const { name, value } = e.target; 96 | 97 | if (name === "name") { 98 | setName(value); 99 | } else if (name === "email") { 100 | setEmail(value); 101 | } else if (name === "subject") { 102 | setSubject(value); 103 | } else if (name === "message") { 104 | setMessage(value); 105 | } 106 | 107 | setLastUpdatedField(name); 108 | }; 109 | 110 | const [cursorBlink, setCursorBlink] = useState(true); 111 | 112 | useEffect(() => { 113 | const blinkInterval = setInterval(() => { 114 | setCursorBlink((prev) => !prev); 115 | }, 400); 116 | 117 | return () => { 118 | clearInterval(blinkInterval); 119 | }; 120 | }, []); 121 | 122 | const codeSnippet = ` 123 | import { useState } from "react"; 124 | 125 | // 🌈 Spreading Stardust: 126 | // Crafting Cosmic Email 🌌 127 | 128 | const [sender, setSender] = "${name}${ 129 | lastUpdatedField === "name" ? (cursorBlink ? "|" : " ") : "" 130 | }🚀"; 131 | const [recipient, setRecipient] = "${email}${ 132 | lastUpdatedField === "email" ? (cursorBlink ? "|" : " ") : "" 133 | }📧"; 134 | const [subject, setSubject] = \n"${subject}${ 135 | lastUpdatedField === "subject" ? (cursorBlink ? "|" : " ") : "" 136 | }✨"; 137 | const [message, setMessage] = 138 | \`Hello, intrepid traveler! 👋\n 139 | Across the cosmos, a message for you:\n 140 | "${wordWrap(message, 40, " ")}${ 141 | lastUpdatedField === "message" ? (cursorBlink ? "|" : " ") : "" 142 | }"\n 143 | Wishing you stardust dreams,\n 144 | ${name}${lastUpdatedField === "name" ? (cursorBlink ? "|" : " ") : ""} 145 | \``; 146 | 147 | // const codeSnippet2 = ` 148 | // // 🚀 Initiating Quantum Email Transmission 🪐 149 | // const launchEmail = async () => { 150 | // try { 151 | // const response = await fetch('https://alpaycelik.dev/send',{ 152 | // method: 'POST', 153 | // headers: {'Content-Type': 'application/json'}, 154 | // body: JSON.stringify({ 155 | // sender, 156 | // recipient, 157 | // subject, 158 | // message 159 | // }) 160 | // }); 161 | 162 | // if (response.ok) { 163 | // console.log('🌌 Transmission successful!'); 164 | // } else { 165 | // console.error('🌠 Cosmic glitch encountered...'); 166 | // } 167 | // } catch (error) { 168 | // console.error('🌪 Quantum disturbance detected:', error); 169 | // } 170 | // }; 171 | // // 🚀 Ready for Liftoff? 🛸 172 | // launchEmail();`; 173 | 174 | return ( 175 | 176 |
180 |
184 | 192 |

193 | < 194 | {language === "DE" ? contactData.title.de : contactData.title.en} 195 | /> 196 |

197 | 198 |

199 | {language === "DE" 200 | ? contactData.description.de 201 | : contactData.description.en} 202 |

203 |
204 |
205 |
206 |
207 | 212 | {({ className, style, tokens, getLineProps, getTokenProps }) => ( 213 |
214 |                   {tokens.map((line, i) => (
215 |                     
216 | {line.map((token, key) => ( 217 | 218 | ))} 219 |
220 | ))} 221 |
222 | )} 223 |
224 |
225 |
230 | {contactData.inputfields.map((input, index) => ( 231 | { 251 | handleInputFocus(input.name); 252 | setLastUpdatedField(input.name); 253 | }} 254 | onMouseEnter={() => { 255 | handleInputFocus(input.name); 256 | setLastUpdatedField(input.name); 257 | }} 258 | onChange={handleInputChange} 259 | className={`${ 260 | theme === "dark" 261 | ? "bg-[--blackblue] dark-mode-shadow " 262 | : "bg-[--icewhite] dark-shadow " 263 | }`} 264 | /> 265 | ))} 266 |