├── 404.png
├── aboutme.png
├── backlog.png
├── mobile.png
├── tablet.png
├── .eslintrc.json
├── diabland.png
├── unit test.png
├── vehicles.png
├── splash screen.png
├── src
├── app
│ ├── favicon.ico
│ ├── error.tsx
│ ├── globals.css
│ ├── api
│ │ └── contact
│ │ │ └── route.js
│ ├── blog
│ │ ├── page.tsx
│ │ └── [category]
│ │ │ ├── page.tsx
│ │ │ └── [slug]
│ │ │ └── page.tsx
│ ├── layout.tsx
│ └── page.tsx
├── styles
│ └── fonts.css
└── components
│ ├── BackButton.tsx
│ ├── ScrollToTopButton.tsx
│ ├── ArticleCard.tsx
│ ├── ArticleClient.tsx
│ ├── CategoryClient.tsx
│ ├── Pagination.tsx
│ ├── NavigationMenu.tsx
│ ├── SkillCard.tsx
│ ├── ArticlesClient.tsx
│ ├── AboutSection.tsx
│ ├── ArticleNavigation.tsx
│ ├── Slider.tsx
│ ├── ContactForm.tsx
│ ├── ArticleLayout.tsx
│ ├── ArticleSlider.tsx
│ ├── Footer.tsx
│ └── TopNav.tsx
├── vehicle-details.png
├── public
├── fonts
│ ├── Vazir-FD-WOL.eot
│ ├── Vazir-FD-WOL.ttf
│ ├── Vazir-FD-WOL.woff
│ ├── Vazir-FD-WOL.woff2
│ ├── Vazir-Bold-FD-WOL.eot
│ ├── Vazir-Bold-FD-WOL.ttf
│ ├── Vazir-Thin-FD-WOL.eot
│ ├── Vazir-Thin-FD-WOL.ttf
│ ├── Vazir-Bold-FD-WOL.woff
│ ├── Vazir-Bold-FD-WOL.woff2
│ ├── Vazir-Light-FD-WOL.eot
│ ├── Vazir-Light-FD-WOL.ttf
│ ├── Vazir-Light-FD-WOL.woff
│ ├── Vazir-Medium-FD-WOL.eot
│ ├── Vazir-Medium-FD-WOL.ttf
│ ├── Vazir-Thin-FD-WOL.woff
│ ├── Vazir-Thin-FD-WOL.woff2
│ ├── Vazir-Light-FD-WOL.woff2
│ ├── Vazir-Medium-FD-WOL.woff
│ └── Vazir-Medium-FD-WOL.woff2
└── images
│ ├── about
│ ├── logo.webp
│ ├── azadeh.jpeg
│ └── azadeh.webp
│ ├── skill
│ ├── css.jpeg
│ ├── html.jpeg
│ ├── php.jpeg
│ ├── seo.jpeg
│ ├── ui.jpeg
│ ├── github.jpeg
│ ├── nextjs.jpeg
│ ├── react.jpeg
│ ├── redux.jpeg
│ ├── scrum.jpeg
│ ├── restapi.jpeg
│ ├── javascript.jpeg
│ ├── tailwindcss.jpeg
│ ├── typescript.jpeg
│ └── campainadvertising.jpeg
│ ├── slider
│ ├── header.jpeg
│ ├── header1.jpeg
│ ├── header3.jpeg
│ └── header4.jpeg
│ ├── github
│ └── what-is-the-github.jpeg
│ ├── nextjs
│ └── what-is-the-next.jpeg
│ ├── react
│ └── what-is-the-react.jpeg
│ ├── redux
│ └── what-is-the-redux.jpeg
│ ├── tailwindcss
│ └── what-is-the-tailwind.jpeg
│ └── typescript
│ └── what-is-the-typescript.jpeg
├── .github
├── ISSUE_TEMPLATE
│ ├── custom.md
│ ├── feature_request.md
│ └── bug_report.md
└── PULL_REQUEST_TEMPLATE.md
├── next.config.js
├── postcss.config.mjs
├── data
└── contacts.json
├── tailwind.config.ts
├── .gitignore
├── tsconfig.json
├── SECURITY.md
├── .prettierrc.json
├── package.json
├── LICENSE
├── CONTRIBUTING.md
├── README.md
└── CODE_OF_CONDUCT.md
/404.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/frau-azadeh/sunflowerdev/HEAD/404.png
--------------------------------------------------------------------------------
/aboutme.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/frau-azadeh/sunflowerdev/HEAD/aboutme.png
--------------------------------------------------------------------------------
/backlog.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/frau-azadeh/sunflowerdev/HEAD/backlog.png
--------------------------------------------------------------------------------
/mobile.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/frau-azadeh/sunflowerdev/HEAD/mobile.png
--------------------------------------------------------------------------------
/tablet.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/frau-azadeh/sunflowerdev/HEAD/tablet.png
--------------------------------------------------------------------------------
/.eslintrc.json:
--------------------------------------------------------------------------------
1 | {
2 | "extends": ["next/core-web-vitals", "next/typescript"]
3 | }
4 |
--------------------------------------------------------------------------------
/diabland.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/frau-azadeh/sunflowerdev/HEAD/diabland.png
--------------------------------------------------------------------------------
/unit test.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/frau-azadeh/sunflowerdev/HEAD/unit test.png
--------------------------------------------------------------------------------
/vehicles.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/frau-azadeh/sunflowerdev/HEAD/vehicles.png
--------------------------------------------------------------------------------
/splash screen.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/frau-azadeh/sunflowerdev/HEAD/splash screen.png
--------------------------------------------------------------------------------
/src/app/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/frau-azadeh/sunflowerdev/HEAD/src/app/favicon.ico
--------------------------------------------------------------------------------
/vehicle-details.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/frau-azadeh/sunflowerdev/HEAD/vehicle-details.png
--------------------------------------------------------------------------------
/public/fonts/Vazir-FD-WOL.eot:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/frau-azadeh/sunflowerdev/HEAD/public/fonts/Vazir-FD-WOL.eot
--------------------------------------------------------------------------------
/public/fonts/Vazir-FD-WOL.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/frau-azadeh/sunflowerdev/HEAD/public/fonts/Vazir-FD-WOL.ttf
--------------------------------------------------------------------------------
/public/images/about/logo.webp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/frau-azadeh/sunflowerdev/HEAD/public/images/about/logo.webp
--------------------------------------------------------------------------------
/public/images/skill/css.jpeg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/frau-azadeh/sunflowerdev/HEAD/public/images/skill/css.jpeg
--------------------------------------------------------------------------------
/public/images/skill/html.jpeg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/frau-azadeh/sunflowerdev/HEAD/public/images/skill/html.jpeg
--------------------------------------------------------------------------------
/public/images/skill/php.jpeg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/frau-azadeh/sunflowerdev/HEAD/public/images/skill/php.jpeg
--------------------------------------------------------------------------------
/public/images/skill/seo.jpeg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/frau-azadeh/sunflowerdev/HEAD/public/images/skill/seo.jpeg
--------------------------------------------------------------------------------
/public/images/skill/ui.jpeg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/frau-azadeh/sunflowerdev/HEAD/public/images/skill/ui.jpeg
--------------------------------------------------------------------------------
/public/fonts/Vazir-FD-WOL.woff:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/frau-azadeh/sunflowerdev/HEAD/public/fonts/Vazir-FD-WOL.woff
--------------------------------------------------------------------------------
/public/fonts/Vazir-FD-WOL.woff2:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/frau-azadeh/sunflowerdev/HEAD/public/fonts/Vazir-FD-WOL.woff2
--------------------------------------------------------------------------------
/public/images/about/azadeh.jpeg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/frau-azadeh/sunflowerdev/HEAD/public/images/about/azadeh.jpeg
--------------------------------------------------------------------------------
/public/images/about/azadeh.webp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/frau-azadeh/sunflowerdev/HEAD/public/images/about/azadeh.webp
--------------------------------------------------------------------------------
/public/images/skill/github.jpeg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/frau-azadeh/sunflowerdev/HEAD/public/images/skill/github.jpeg
--------------------------------------------------------------------------------
/public/images/skill/nextjs.jpeg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/frau-azadeh/sunflowerdev/HEAD/public/images/skill/nextjs.jpeg
--------------------------------------------------------------------------------
/public/images/skill/react.jpeg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/frau-azadeh/sunflowerdev/HEAD/public/images/skill/react.jpeg
--------------------------------------------------------------------------------
/public/images/skill/redux.jpeg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/frau-azadeh/sunflowerdev/HEAD/public/images/skill/redux.jpeg
--------------------------------------------------------------------------------
/public/images/skill/scrum.jpeg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/frau-azadeh/sunflowerdev/HEAD/public/images/skill/scrum.jpeg
--------------------------------------------------------------------------------
/public/fonts/Vazir-Bold-FD-WOL.eot:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/frau-azadeh/sunflowerdev/HEAD/public/fonts/Vazir-Bold-FD-WOL.eot
--------------------------------------------------------------------------------
/public/fonts/Vazir-Bold-FD-WOL.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/frau-azadeh/sunflowerdev/HEAD/public/fonts/Vazir-Bold-FD-WOL.ttf
--------------------------------------------------------------------------------
/public/fonts/Vazir-Thin-FD-WOL.eot:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/frau-azadeh/sunflowerdev/HEAD/public/fonts/Vazir-Thin-FD-WOL.eot
--------------------------------------------------------------------------------
/public/fonts/Vazir-Thin-FD-WOL.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/frau-azadeh/sunflowerdev/HEAD/public/fonts/Vazir-Thin-FD-WOL.ttf
--------------------------------------------------------------------------------
/public/images/skill/restapi.jpeg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/frau-azadeh/sunflowerdev/HEAD/public/images/skill/restapi.jpeg
--------------------------------------------------------------------------------
/public/images/slider/header.jpeg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/frau-azadeh/sunflowerdev/HEAD/public/images/slider/header.jpeg
--------------------------------------------------------------------------------
/public/images/slider/header1.jpeg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/frau-azadeh/sunflowerdev/HEAD/public/images/slider/header1.jpeg
--------------------------------------------------------------------------------
/public/images/slider/header3.jpeg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/frau-azadeh/sunflowerdev/HEAD/public/images/slider/header3.jpeg
--------------------------------------------------------------------------------
/public/images/slider/header4.jpeg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/frau-azadeh/sunflowerdev/HEAD/public/images/slider/header4.jpeg
--------------------------------------------------------------------------------
/public/fonts/Vazir-Bold-FD-WOL.woff:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/frau-azadeh/sunflowerdev/HEAD/public/fonts/Vazir-Bold-FD-WOL.woff
--------------------------------------------------------------------------------
/public/fonts/Vazir-Bold-FD-WOL.woff2:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/frau-azadeh/sunflowerdev/HEAD/public/fonts/Vazir-Bold-FD-WOL.woff2
--------------------------------------------------------------------------------
/public/fonts/Vazir-Light-FD-WOL.eot:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/frau-azadeh/sunflowerdev/HEAD/public/fonts/Vazir-Light-FD-WOL.eot
--------------------------------------------------------------------------------
/public/fonts/Vazir-Light-FD-WOL.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/frau-azadeh/sunflowerdev/HEAD/public/fonts/Vazir-Light-FD-WOL.ttf
--------------------------------------------------------------------------------
/public/fonts/Vazir-Light-FD-WOL.woff:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/frau-azadeh/sunflowerdev/HEAD/public/fonts/Vazir-Light-FD-WOL.woff
--------------------------------------------------------------------------------
/public/fonts/Vazir-Medium-FD-WOL.eot:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/frau-azadeh/sunflowerdev/HEAD/public/fonts/Vazir-Medium-FD-WOL.eot
--------------------------------------------------------------------------------
/public/fonts/Vazir-Medium-FD-WOL.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/frau-azadeh/sunflowerdev/HEAD/public/fonts/Vazir-Medium-FD-WOL.ttf
--------------------------------------------------------------------------------
/public/fonts/Vazir-Thin-FD-WOL.woff:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/frau-azadeh/sunflowerdev/HEAD/public/fonts/Vazir-Thin-FD-WOL.woff
--------------------------------------------------------------------------------
/public/fonts/Vazir-Thin-FD-WOL.woff2:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/frau-azadeh/sunflowerdev/HEAD/public/fonts/Vazir-Thin-FD-WOL.woff2
--------------------------------------------------------------------------------
/public/images/skill/javascript.jpeg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/frau-azadeh/sunflowerdev/HEAD/public/images/skill/javascript.jpeg
--------------------------------------------------------------------------------
/public/images/skill/tailwindcss.jpeg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/frau-azadeh/sunflowerdev/HEAD/public/images/skill/tailwindcss.jpeg
--------------------------------------------------------------------------------
/public/images/skill/typescript.jpeg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/frau-azadeh/sunflowerdev/HEAD/public/images/skill/typescript.jpeg
--------------------------------------------------------------------------------
/public/fonts/Vazir-Light-FD-WOL.woff2:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/frau-azadeh/sunflowerdev/HEAD/public/fonts/Vazir-Light-FD-WOL.woff2
--------------------------------------------------------------------------------
/public/fonts/Vazir-Medium-FD-WOL.woff:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/frau-azadeh/sunflowerdev/HEAD/public/fonts/Vazir-Medium-FD-WOL.woff
--------------------------------------------------------------------------------
/public/fonts/Vazir-Medium-FD-WOL.woff2:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/frau-azadeh/sunflowerdev/HEAD/public/fonts/Vazir-Medium-FD-WOL.woff2
--------------------------------------------------------------------------------
/public/images/github/what-is-the-github.jpeg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/frau-azadeh/sunflowerdev/HEAD/public/images/github/what-is-the-github.jpeg
--------------------------------------------------------------------------------
/public/images/nextjs/what-is-the-next.jpeg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/frau-azadeh/sunflowerdev/HEAD/public/images/nextjs/what-is-the-next.jpeg
--------------------------------------------------------------------------------
/public/images/react/what-is-the-react.jpeg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/frau-azadeh/sunflowerdev/HEAD/public/images/react/what-is-the-react.jpeg
--------------------------------------------------------------------------------
/public/images/redux/what-is-the-redux.jpeg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/frau-azadeh/sunflowerdev/HEAD/public/images/redux/what-is-the-redux.jpeg
--------------------------------------------------------------------------------
/public/images/skill/campainadvertising.jpeg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/frau-azadeh/sunflowerdev/HEAD/public/images/skill/campainadvertising.jpeg
--------------------------------------------------------------------------------
/public/images/tailwindcss/what-is-the-tailwind.jpeg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/frau-azadeh/sunflowerdev/HEAD/public/images/tailwindcss/what-is-the-tailwind.jpeg
--------------------------------------------------------------------------------
/public/images/typescript/what-is-the-typescript.jpeg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/frau-azadeh/sunflowerdev/HEAD/public/images/typescript/what-is-the-typescript.jpeg
--------------------------------------------------------------------------------
/.github/ISSUE_TEMPLATE/custom.md:
--------------------------------------------------------------------------------
1 | ---
2 | name: Custom issue template
3 | about: Describe this issue template's purpose here.
4 | title: ""
5 | labels: ""
6 | assignees: ""
7 | ---
8 |
--------------------------------------------------------------------------------
/next.config.js:
--------------------------------------------------------------------------------
1 | // next.config.js
2 | /** @type {import('next').NextConfig} */
3 | const nextConfig = {
4 | reactStrictMode: true,
5 | };
6 |
7 | module.exports = nextConfig;
8 |
--------------------------------------------------------------------------------
/postcss.config.mjs:
--------------------------------------------------------------------------------
1 | /** @type {import('postcss-load-config').Config} */
2 | const config = {
3 | plugins: {
4 | tailwindcss: {},
5 | },
6 | };
7 |
8 | export default config;
9 |
--------------------------------------------------------------------------------
/src/app/error.tsx:
--------------------------------------------------------------------------------
1 | "use client";
2 |
3 | import type { ReactNode } from "react";
4 |
5 | import Link from "next/link";
6 |
7 | export default function ErrorPage(): ReactNode {
8 | return (
9 |
10 |
Oops! Something Went Wrong...
11 | Go to Home page
12 |
13 | );
14 | }
15 |
--------------------------------------------------------------------------------
/src/app/globals.css:
--------------------------------------------------------------------------------
1 | @tailwind base;
2 | @tailwind components;
3 | @tailwind utilities;
4 |
5 | :root {
6 | --background: #ffffff;
7 | --foreground: #171717;
8 | }
9 |
10 | @media (prefers-color-scheme: dark) {
11 | :root {
12 | --background: #0a0a0a;
13 | --foreground: #ededed;
14 | }
15 | }
16 |
17 | body {
18 | color: var(--foreground);
19 | background: var(--background);
20 | @apply font-vazir;
21 | }
22 |
--------------------------------------------------------------------------------
/data/contacts.json:
--------------------------------------------------------------------------------
1 | [
2 | {
3 | "id": 1,
4 | "name": "آزاده شریفی سلطانی",
5 | "phone": "09122764435",
6 | "message": "سایت بسیار زیبایی دارید موفق باشید "
7 | },
8 | {
9 | "id": 2,
10 | "name": "آزاده شریفی سلطانی",
11 | "phone": "09122764435",
12 | "message": "موفق باشی و به درجات بالا برسی"
13 | },
14 | {
15 | "id": 3,
16 | "name": "آرزو شریفی سلطانی",
17 | "phone": "09223539879",
18 | "message": "موفق باشی خواهر عزیز تر از جانم"
19 | }
20 | ]
21 |
--------------------------------------------------------------------------------
/.github/PULL_REQUEST_TEMPLATE.md:
--------------------------------------------------------------------------------
1 | ## Description
2 |
3 | Please provide a brief description of the changes you made.
4 |
5 | ## Related Issue
6 |
7 | If this pull request is related to an issue, please link it here.
8 |
9 | ## Checklist
10 |
11 | - [ ] My code follows the style guidelines of this project.
12 | - [ ] I have performed a self-review of my code.
13 | - [ ] I have commented my code, particularly in hard-to-understand areas.
14 | - [ ] I have made corresponding changes to the documentation.
15 | - [ ] My changes generate no new warnings.
16 |
--------------------------------------------------------------------------------
/src/styles/fonts.css:
--------------------------------------------------------------------------------
1 | @font-face {
2 | font-family: "Vazir";
3 | src: url("../../public/fonts/Vazir-Bold-FD-WOL.woff2") format("woff2");
4 | font-weight: 400;
5 | font-style: normal;
6 | }
7 |
8 | @font-face {
9 | font-family: "Vazir";
10 | src: url("../../public/fonts/Vazir-Bold-FD-WOL.woff2") format("woff2");
11 | font-weight: 700;
12 | font-style: normal;
13 | }
14 |
15 | @font-face {
16 | font-family: "Vazir";
17 | src: url("../../public/fonts/Vazir-Bold-FD-WOL.woff2") format("woff2");
18 | font-weight: 300;
19 | font-style: normal;
20 | }
21 |
--------------------------------------------------------------------------------
/tailwind.config.ts:
--------------------------------------------------------------------------------
1 | import type { Config } from "tailwindcss";
2 |
3 | const config: Config = {
4 | content: [
5 | "./src/pages/**/*.{js,ts,jsx,tsx,mdx}",
6 | "./src/components/**/*.{js,ts,jsx,tsx,mdx}",
7 | "./src/app/**/*.{js,ts,jsx,tsx,mdx}",
8 | ],
9 | theme: {
10 | extend: {
11 | colors: {
12 | background: "var(--background)",
13 | foreground: "var(--foreground)",
14 | },
15 | fontFamily: {
16 | vazir: ["Vazir"],
17 | },
18 | },
19 | },
20 | plugins: [],
21 | };
22 | export default config;
23 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # See https://help.github.com/articles/ignoring-files/ for more about ignoring files.
2 |
3 | # dependencies
4 | /node_modules
5 | /.pnp
6 | .pnp.*
7 | .yarn/*
8 | !.yarn/patches
9 | !.yarn/plugins
10 | !.yarn/releases
11 | !.yarn/versions
12 |
13 | # testing
14 | /coverage
15 |
16 | # next.js
17 | /.next/
18 | /out/
19 |
20 | # production
21 | /build
22 |
23 | # misc
24 | .DS_Store
25 | *.pem
26 |
27 | # debug
28 | npm-debug.log*
29 | yarn-debug.log*
30 | yarn-error.log*
31 |
32 | # env files (can opt-in for commiting if needed)
33 | .env*
34 |
35 | # vercel
36 | .vercel
37 |
38 | # typescript
39 | *.tsbuildinfo
40 | next-env.d.ts
41 |
--------------------------------------------------------------------------------
/.github/ISSUE_TEMPLATE/feature_request.md:
--------------------------------------------------------------------------------
1 | ---
2 | name: Feature request
3 | about: Suggest an idea for this project
4 | title: ""
5 | labels: ""
6 | assignees: ""
7 | ---
8 |
9 | **Is your feature request related to a problem? Please describe.**
10 | A clear and concise description of what the problem is. Ex. I'm always frustrated when [...]
11 |
12 | **Describe the solution you'd like**
13 | A clear and concise description of what you want to happen.
14 |
15 | **Describe alternatives you've considered**
16 | A clear and concise description of any alternative solutions or features you've considered.
17 |
18 | **Additional context**
19 | Add any other context or screenshots about the feature request here.
20 |
--------------------------------------------------------------------------------
/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "compilerOptions": {
3 | "target": "ES2017",
4 | "lib": ["dom", "dom.iterable", "esnext"],
5 | "allowJs": true,
6 | "skipLibCheck": true,
7 | "strict": true,
8 | "noEmit": true,
9 | "esModuleInterop": true,
10 | "module": "esnext",
11 | "moduleResolution": "bundler",
12 | "resolveJsonModule": true,
13 | "isolatedModules": true,
14 | "jsx": "preserve",
15 | "incremental": true,
16 | "plugins": [
17 | {
18 | "name": "next"
19 | }
20 | ],
21 | "paths": {
22 | "@/*": ["./src/*"]
23 | }
24 | },
25 | "include": [
26 | "next-env.d.ts",
27 | "**/*.ts",
28 | "**/*.tsx",
29 | ".next/types/**/*.ts",
30 | "next.config.js"
31 | ],
32 | "exclude": ["node_modules"]
33 | }
34 |
--------------------------------------------------------------------------------
/SECURITY.md:
--------------------------------------------------------------------------------
1 | # Security Policy
2 |
3 | ## Supported Versions
4 |
5 | Use this section to tell people about which versions of your project are
6 | currently being supported with security updates.
7 |
8 | | Version | Supported |
9 | | ------- | ------------------ |
10 | | 5.1.x | :white_check_mark: |
11 | | 5.0.x | :x: |
12 | | 4.0.x | :white_check_mark: |
13 | | < 4.0 | :x: |
14 |
15 | ## Reporting a Vulnerability
16 |
17 | Use this section to tell people how to report a vulnerability.
18 |
19 | Tell them where to go, how often they can expect to get an update on a
20 | reported vulnerability, what to expect if the vulnerability is accepted or
21 | declined, etc.
22 | If you discover a security vulnerability, please email us at [designweb.azadeh@gmail.com].
23 |
--------------------------------------------------------------------------------
/src/components/BackButton.tsx:
--------------------------------------------------------------------------------
1 | "use client";
2 |
3 | import { useEffect, useState } from "react";
4 |
5 | const BackButton: React.FC = () => {
6 | const [isVisible, setIsVisible] = useState(false);
7 |
8 | const goBack = () => {
9 | window.history.back();
10 | };
11 |
12 | const handleScroll = () => {
13 | if (window.scrollY > 100) {
14 | setIsVisible(true);
15 | } else {
16 | setIsVisible(false);
17 | }
18 | };
19 |
20 | useEffect(() => {
21 | window.addEventListener("scroll", handleScroll);
22 | return () => window.removeEventListener("scroll", handleScroll);
23 | }, []);
24 |
25 | return (
26 |
32 | صفحه قبل
33 |
34 | );
35 | };
36 |
37 | export default BackButton;
38 |
--------------------------------------------------------------------------------
/.github/ISSUE_TEMPLATE/bug_report.md:
--------------------------------------------------------------------------------
1 | ---
2 | name: Bug report
3 | about: Create a report to help us improve
4 | title: ""
5 | labels: ""
6 | assignees: ""
7 | ---
8 |
9 | **Describe the bug**
10 | A clear and concise description of what the bug is.
11 |
12 | **To Reproduce**
13 | Steps to reproduce the behavior:
14 |
15 | 1. Go to '...'
16 | 2. Click on '....'
17 | 3. Scroll down to '....'
18 | 4. See error
19 |
20 | **Expected behavior**
21 | A clear and concise description of what you expected to happen.
22 |
23 | **Screenshots**
24 | If applicable, add screenshots to help explain your problem.
25 |
26 | **Desktop (please complete the following information):**
27 |
28 | - OS: [e.g. iOS]
29 | - Browser [e.g. chrome, safari]
30 | - Version [e.g. 22]
31 |
32 | **Smartphone (please complete the following information):**
33 |
34 | - Device: [e.g. iPhone6]
35 | - OS: [e.g. iOS8.1]
36 | - Browser [e.g. stock browser, safari]
37 | - Version [e.g. 22]
38 |
39 | **Additional context**
40 | Add any other context about the problem here.
41 |
--------------------------------------------------------------------------------
/src/app/api/contact/route.js:
--------------------------------------------------------------------------------
1 | import fs from "fs";
2 | import path from "path";
3 |
4 | const contactsFilePath = path.join(process.cwd(), "data", "contacts.json");
5 |
6 | export async function POST(req) {
7 | const { name, phone, message } = await req.json();
8 |
9 | if (!name || !phone || !message) {
10 | return new Response(JSON.stringify({ error: "همه فیلدها الزامی هستند" }), {
11 | status: 400,
12 | });
13 | }
14 |
15 | // خواندن دادهها از فایل JSON
16 | const fileData = fs.readFileSync(contactsFilePath, "utf-8");
17 | const contacts = JSON.parse(fileData);
18 |
19 | // اضافه کردن تماس جدید
20 | const newContact = { id: contacts.length + 1, name, phone, message };
21 | contacts.push(newContact);
22 |
23 | // نوشتن دادهها در فایل JSON
24 | fs.writeFileSync(contactsFilePath, JSON.stringify(contacts, null, 2));
25 |
26 | return new Response(JSON.stringify({ message: "پیام با موفقیت ذخیره شد" }), {
27 | status: 201,
28 | headers: { "Content-Type": "application/json" },
29 | });
30 | }
31 |
--------------------------------------------------------------------------------
/.prettierrc.json:
--------------------------------------------------------------------------------
1 | {
2 | "plugins": ["@trivago/prettier-plugin-sort-imports"],
3 | "importOrder": [
4 | "^(vite|@vitejs)(/(.*))?$",
5 | "^(react|react-dom)(/(.*))?$",
6 | "^react-router(/(.*))?$",
7 | "^react-error-boundary(/(.*))?$",
8 | "^(immer|use-immer)(/(.*))?$",
9 | "^zustand(/(.*))?$",
10 | "^@tanstack(/(.*))?$",
11 | "^@dnd-kit(/(.*))?$",
12 | "^react-toastify(/(.*))?$",
13 | "^(react-hook-form|@hookform/resolvers|zod)(/(.*))?$",
14 | "^clsx(/(.*))?$",
15 | "",
16 | "^@/api",
17 | "^@/components",
18 | "^@/context",
19 | "^@/data",
20 | "^@/dto",
21 | "^@/hooks",
22 | "^@/icons",
23 | "^@/layouts",
24 | "^@/modals",
25 | "^@/pages",
26 | "^@/providers",
27 | "^@/reducers",
28 | "^@/schemas",
29 | "^@/stores",
30 | "^@/types",
31 | "^@/utils",
32 | "^@/styles",
33 | "^(\\.|\\.\\.)/(.(?!.css))*$",
34 | "\\.css$"
35 | ],
36 | "importOrderSeparation": true,
37 | "importOrderSortSpecifiers": true,
38 | "importOrderGroupNamespaceSpecifiers": true
39 | }
40 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "sunflower",
3 | "version": "0.1.0",
4 | "private": true,
5 | "scripts": {
6 | "dev": "next dev",
7 | "build": "next build",
8 | "start": "next start",
9 | "lint": "next lint",
10 | "prettier:check": "prettier --check .",
11 | "prettier:fix": "prettier --write ."
12 | },
13 | "dependencies": {
14 | "@trivago/prettier-plugin-sort-imports": "^5.2.2",
15 | "@types/react-slick": "^0.23.13",
16 | "axios": "^1.7.7",
17 | "gray-matter": "^4.0.3",
18 | "next": "^14.2.17",
19 | "prettier": "^3.6.2",
20 | "react": "^18.3.1",
21 | "react-dom": "^18.3.1",
22 | "react-error-boundary": "^6.0.0",
23 | "react-icons": "^5.3.0",
24 | "react-slick": "^0.30.2",
25 | "slick-carousel": "^1.8.1",
26 | "swiper": "^11.1.14"
27 | },
28 | "devDependencies": {
29 | "@types/node": "^20",
30 | "@types/react": "^18",
31 | "@types/react-dom": "^18",
32 | "eslint": "^8",
33 | "eslint-config-next": "15.0.2",
34 | "postcss": "^8",
35 | "tailwindcss": "^3.4.1",
36 | "typescript": "^5"
37 | }
38 | }
39 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2025 Azadeh Sharifi Soltani
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 |
--------------------------------------------------------------------------------
/src/components/ScrollToTopButton.tsx:
--------------------------------------------------------------------------------
1 | "use client";
2 |
3 | import { memo, useCallback, useEffect, useMemo, useState } from "react";
4 |
5 | import { FaAngleDoubleUp } from "react-icons/fa";
6 |
7 | const ScrollToTopButton: React.FC = () => {
8 | const [isVisible, setIsVisible] = useState(false);
9 |
10 | useEffect(() => {
11 | const toggleVisibility = () => {
12 | if (window.scrollY > 300) {
13 | setIsVisible(true);
14 | } else {
15 | setIsVisible(false);
16 | }
17 | };
18 | window.addEventListener("scroll", toggleVisibility);
19 | return () => window.removeEventListener("scroll", toggleVisibility);
20 | }, []);
21 |
22 | const scrollToTop = useCallback(() => {
23 | window.scrollTo({
24 | top: 0,
25 | behavior: "smooth",
26 | });
27 | }, []);
28 |
29 | const buttonClass = useMemo(
30 | () =>
31 | `${
32 | isVisible ? "flex" : "hidden"
33 | } fixed bottom-28 left-12 w-10 h-10 bg-[#ffe082] text-[#56464d] rounded-full shadow-md justify-center items-center cursor-pointer z-10`,
34 | [isVisible],
35 | );
36 |
37 | return (
38 |
39 |
40 |
41 | );
42 | };
43 |
44 | export default memo(ScrollToTopButton);
45 |
--------------------------------------------------------------------------------
/src/components/ArticleCard.tsx:
--------------------------------------------------------------------------------
1 | import Image from "next/image";
2 | import Link from "next/link";
3 |
4 | interface ArticleCardProps {
5 | title: string;
6 | description: string;
7 | date: string;
8 | image: string;
9 | href: string;
10 | }
11 |
12 | export default function ArticleCard({
13 | title,
14 | description,
15 | date,
16 | image,
17 | href,
18 | }: ArticleCardProps) {
19 | return (
20 |
21 |
22 |
29 |
30 |
31 |
{title}
32 |
33 | {description}
34 |
35 |
36 |
37 | {date}
38 |
39 |
40 | ادامه مطلب
41 |
42 |
43 |
44 | );
45 | }
46 |
--------------------------------------------------------------------------------
/src/components/ArticleClient.tsx:
--------------------------------------------------------------------------------
1 | "use client";
2 |
3 | import { useEffect, useState } from "react";
4 |
5 | import ArticleLayout from "@/components/ArticleLayout";
6 | import ArticleNavigation from "@/components/ArticleNavigation";
7 |
8 | interface ArticleData {
9 | title: string;
10 | description: string;
11 | date: string;
12 | author: string;
13 | reading_time: string;
14 | image: string;
15 | content: { section_title: string; paragraphs: string[] }[];
16 | category: string;
17 | slug: string;
18 | }
19 |
20 | interface ArticleClientProps {
21 | article: ArticleData | null;
22 | articles: ArticleData[];
23 | }
24 |
25 | export default function ArticleClient({
26 | article,
27 | articles,
28 | }: ArticleClientProps) {
29 | const [loading, setLoading] = useState(true);
30 |
31 | useEffect(() => {
32 | if (article) {
33 | setLoading(false);
34 | }
35 | }, [article]);
36 |
37 | if (loading) {
38 | return در حال بارگذاری...
;
39 | }
40 |
41 | if (!article) {
42 | return مقاله مورد نظر یافت نشد.
;
43 | }
44 |
45 | return (
46 | <>
47 |
57 |
58 | >
59 | );
60 | }
61 |
--------------------------------------------------------------------------------
/src/components/CategoryClient.tsx:
--------------------------------------------------------------------------------
1 | "use client";
2 |
3 | import { useEffect, useState } from "react";
4 |
5 | import ArticleCard from "@/components/ArticleCard";
6 |
7 | interface ArticleData {
8 | title: string;
9 | description: string;
10 | date: string;
11 | image: string;
12 | slug: string;
13 | category: string;
14 | }
15 |
16 | interface CategoryClientProps {
17 | articles: ArticleData[];
18 | category: string;
19 | }
20 |
21 | export default function CategoryClient({
22 | articles,
23 | category,
24 | }: CategoryClientProps) {
25 | const [filteredArticles, setFilteredArticles] = useState([]);
26 |
27 | useEffect(() => {
28 | if (category && articles.length > 0) {
29 | const filtered = articles.filter(
30 | (article) => article.category.toLowerCase() === category.toLowerCase(),
31 | );
32 | setFilteredArticles(filtered);
33 | }
34 | }, [category, articles]);
35 |
36 | return (
37 |
38 | {filteredArticles.length > 0 ? (
39 | filteredArticles.map((article) => (
40 |
48 | ))
49 | ) : (
50 |
...
51 | )}
52 |
53 | );
54 | }
55 |
--------------------------------------------------------------------------------
/src/components/Pagination.tsx:
--------------------------------------------------------------------------------
1 | import React from "react";
2 |
3 | interface PaginationProps {
4 | currentPage: number;
5 | totalItems: number;
6 | itemsPerPage: number;
7 | onPageChange: (page: number) => void;
8 | }
9 |
10 | export default function Pagination({
11 | currentPage,
12 | totalItems,
13 | itemsPerPage,
14 | onPageChange,
15 | }: PaginationProps) {
16 | const totalPages = Math.ceil(totalItems / itemsPerPage);
17 |
18 | const handlePageClick = (page: number) => {
19 | if (page > 0 && page <= totalPages) {
20 | onPageChange(page);
21 | }
22 | };
23 |
24 | return (
25 |
26 | handlePageClick(currentPage - 1)}
28 | disabled={currentPage === 1}
29 | className="px-3 py-1 text-gray-400"
30 | >
31 | قبلی
32 |
33 | {[...Array(totalPages)].map((_, index) => (
34 | handlePageClick(index + 1)}
37 | className={`px-3 py-1 rounded ${
38 | currentPage === index + 1
39 | ? "bg-blue-500 text-white"
40 | : "bg-gray-200 hover:bg-gray-300"
41 | }`}
42 | >
43 | {index + 1}
44 |
45 | ))}
46 | handlePageClick(currentPage + 1)}
48 | disabled={currentPage === totalPages}
49 | className="px-3 py-1 text-gray-400"
50 | >
51 | بعدی
52 |
53 |
54 | );
55 | }
56 |
--------------------------------------------------------------------------------
/src/components/NavigationMenu.tsx:
--------------------------------------------------------------------------------
1 | import React from "react";
2 |
3 | import { AiFillInstagram } from "react-icons/ai";
4 | import { FaGithubSquare, FaLinkedin, FaPhoneSquare } from "react-icons/fa";
5 |
6 | const NavigationMenu: React.FC = () => {
7 | return (
8 |
43 | );
44 | };
45 |
46 | export default NavigationMenu;
47 |
--------------------------------------------------------------------------------
/src/components/SkillCard.tsx:
--------------------------------------------------------------------------------
1 | import React from "react";
2 |
3 | import Image from "next/image";
4 |
5 | interface SkillCardProps {
6 | title: string;
7 | description: string;
8 | imgSrc: string;
9 | proficiency: string;
10 | }
11 |
12 | const SkillCard: React.FC = ({
13 | title,
14 | description,
15 | imgSrc,
16 | proficiency,
17 | }) => {
18 | return (
19 |
20 |
21 |
22 |
29 |
30 |
{title}
31 |
{description}
32 |
33 | میزان تسلط من:
34 |
35 |
36 |
40 |
41 | {proficiency}
42 |
43 |
44 |
45 |
46 |
47 | );
48 | };
49 |
50 | export default SkillCard;
51 |
--------------------------------------------------------------------------------
/src/components/ArticlesClient.tsx:
--------------------------------------------------------------------------------
1 | "use client";
2 |
3 | import { useState } from "react";
4 |
5 | import ArticleCard from "@/components/ArticleCard";
6 | import Pagination from "@/components/Pagination";
7 |
8 | interface ArticleData {
9 | title: string;
10 | description: string;
11 | date: string;
12 | image: string;
13 | slug: string;
14 | category: string;
15 | href: string;
16 | }
17 | interface ArticlesClientProps {
18 | articles: ArticleData[];
19 | }
20 |
21 | export default function ArticlesClient({ articles }: ArticlesClientProps) {
22 | const [currentPage, setCurrentPage] = useState(1);
23 | const itemsPerPage = 3;
24 |
25 | const handlePageChange = (page: number) => {
26 | setCurrentPage(page);
27 | };
28 |
29 | const startIndex = (currentPage - 1) * itemsPerPage;
30 | const currentArticles = articles.slice(startIndex, startIndex + itemsPerPage);
31 |
32 | return (
33 |
34 |
35 | مقالات تخصصی برنامه نویسی :
36 |
37 |
38 | {currentArticles.length > 0 ? (
39 | currentArticles.map((article) => (
40 |
48 | ))
49 | ) : (
50 |
به روز رسانی ...
51 | )}
52 |
53 | {articles.length > itemsPerPage && (
54 |
60 | )}
61 |
62 | );
63 | }
64 |
--------------------------------------------------------------------------------
/CONTRIBUTING.md:
--------------------------------------------------------------------------------
1 | # 🚀 Contributing to Our Project
2 |
3 | We are thrilled that you are interested in contributing to our project. Your support and involvement are what make our community strong and our project better. Whether you're fixing a bug, adding a feature, or simply improving documentation, every contribution is valuable. 💪
4 |
5 | ## 📝 How to Contribute
6 |
7 | ### 1. Fork the Repository
8 |
9 | Click the _Fork_ button at the top right of this page to create a copy of the repository under your GitHub account.
10 |
11 | ### 2. Clone Your Fork
12 |
13 | bash
14 | git clone https://github.com/frau-azadeh/sunflowerdev.git
15 | cd REPOSITORY_NAME
16 |
17 | ### 3. Create a Branch
18 |
19 | Create a new branch for your changes:
20 |
21 | git checkout -b your-feature-name
22 |
23 | ### 4. Make Your Changes
24 |
25 | Edit the code, fix bugs, or improve the documentation. Remember to write clean and well-documented code.
26 |
27 | ### 5. Commit Your Changes
28 |
29 | git add .
30 | git commit -m "Brief description of your changes"
31 |
32 | ### 6. Push to Your Fork
33 |
34 | git push origin your-feature-name
35 |
36 | ### 7. Create a Pull Request
37 |
38 | Go to the original repository, click on _Pull Requests, and select \*\*New Pull Request_. Choose your branch and submit the PR for review.
39 |
40 | ## ✅ Contribution Guidelines
41 |
42 | - Ensure your code follows the existing style and conventions.
43 | - Write clear, concise commit messages.
44 | - Provide a detailed description of your changes in the pull request.
45 | - Test your changes before submitting.
46 |
47 | ## 🌟 Additional Ways to Contribute
48 |
49 | - Report issues 🐛
50 | - Suggest new features ✨
51 | - Improve documentation 📖
52 | - Share the project with others 💬
53 |
54 | ## 🤝 Code of Conduct
55 |
56 | Please note that we follow a [Code of Conduct](CODE_OF_CONDUCT.md) to ensure a welcoming and inclusive environment.
57 |
58 | ## 💬 Need Help?
59 |
60 | If you need any help or have questions, feel free to open an issue or reach out to us. We’re happy to help! 🚀
61 |
62 | Thank you for helping us make this project better! ❤️
63 |
--------------------------------------------------------------------------------
/src/components/AboutSection.tsx:
--------------------------------------------------------------------------------
1 | import Image from "next/image";
2 | import { FaLaptopCode } from "react-icons/fa";
3 |
4 | const AboutSection = () => {
5 | return (
6 | <>
7 |
8 | درباره من
9 |
10 |
11 |
12 |
13 |
14 |
15 |
19 |
20 |
27 |
آزاده شریفی سلطانی
28 |
29 | من آزاده شریفی سلطانی هستم؛ علاقهمند به برنامهنویسی و زبان آلمانی.
30 | تحصیلاتم را در مقطع کاردانی در رشتهی نرمافزار کامپیوتر از دانشگاه
31 | جامع علمیکاربردی به پایان رساندم و دورهی کارشناسی را در دانشگاه
32 | کومش سمنان ادامه دادم. پس از آن، با علاقه به زبان و آموزش، رشتهی
33 | آموزش زبان آلمانی را برای مقطع کارشناسی ارشد انتخاب کردم. در حال
34 | حاضر در شرکت فولاد حامیران مشغول به کار هستم و پیشتر نیز در
35 | شرکتهای نگین سبز خاورمیانه و پارس فعالیت داشتهام. در کنار مسیر
36 | شغلیام، برای توسعهی فردی و افزایش دانش مدیریتی، دورهی MBA را در
37 | دانشگاه تهران به پایان رساندهام.
38 |
39 |
40 |
41 | >
42 | );
43 | };
44 |
45 | export default AboutSection;
46 |
--------------------------------------------------------------------------------
/src/components/ArticleNavigation.tsx:
--------------------------------------------------------------------------------
1 | import Link from "next/link";
2 |
3 | interface Article {
4 | slug: string;
5 | category: string;
6 | title: string;
7 | date: string;
8 | }
9 |
10 | interface ArticleNavigationProps {
11 | articles: Article[];
12 | currentArticle: Article;
13 | }
14 |
15 | const ArticleNavigation: React.FC = ({
16 | articles,
17 | currentArticle,
18 | }) => {
19 | const sortedArticles = [...articles].sort(
20 | (a, b) => new Date(b.date).getTime() - new Date(a.date).getTime(),
21 | );
22 | const currentIndex = sortedArticles.findIndex(
23 | (article) =>
24 | article.slug === currentArticle.slug &&
25 | article.category === currentArticle.category,
26 | );
27 |
28 | const previousArticle = sortedArticles[currentIndex + 1];
29 | const nextArticle = sortedArticles[currentIndex - 1];
30 |
31 | return (
32 |
33 |
34 | مقالات پیشنهادی:
35 |
36 |
37 | {previousArticle ? (
38 |
42 |
43 | ← {previousArticle.title}
44 |
45 |
46 | ) : (
47 |
48 | )}
49 | {nextArticle ? (
50 |
54 |
55 | {nextArticle.title} →
56 |
57 |
58 | ) : (
59 |
60 | )}
61 |
62 |
63 | );
64 | };
65 |
66 | export default ArticleNavigation;
67 |
--------------------------------------------------------------------------------
/src/components/Slider.tsx:
--------------------------------------------------------------------------------
1 | "use client";
2 |
3 | import { useEffect, useState } from "react";
4 |
5 | import Image from "next/image";
6 | import { FaAngleDoubleLeft, FaAngleDoubleRight } from "react-icons/fa";
7 |
8 | interface Slide {
9 | image: string;
10 | title: string;
11 | description: string;
12 | }
13 |
14 | const slides: Slide[] = [
15 | {
16 | image: "/images/slider/header.jpeg",
17 | title: "اسلاید ۱",
18 | description: "توضیحات اسلاید ۱",
19 | },
20 | {
21 | image: "/images/slider/header1.jpeg",
22 | title: "اسلاید ۲",
23 | description: "توضیحات اسلاید ۲",
24 | },
25 | {
26 | image: "/images/slider/header3.jpeg",
27 | title: "اسلاید ۳",
28 | description: "توضیحات اسلاید ۳",
29 | },
30 | {
31 | image: "/images/slider/header4.jpeg",
32 | title: "اسلاید 4",
33 | description: "توضیحات اسلاید 4",
34 | },
35 | ];
36 |
37 | const Slider = () => {
38 | const [currentIndex, setCurrentIndex] = useState(0);
39 |
40 | useEffect(() => {
41 | const interval = setInterval(() => {
42 | setCurrentIndex((prevIndex) =>
43 | prevIndex === slides.length - 1 ? 0 : prevIndex + 1,
44 | );
45 | }, 5000);
46 |
47 | return () => clearInterval(interval);
48 | }, []);
49 |
50 | const handlePrev = () => {
51 | const newIndex = currentIndex === 0 ? slides.length - 1 : currentIndex - 1;
52 | setCurrentIndex(newIndex);
53 | };
54 |
55 | const handleNext = () => {
56 | const newIndex = currentIndex === slides.length - 1 ? 0 : currentIndex + 1;
57 | setCurrentIndex(newIndex);
58 | };
59 |
60 | return (
61 |
62 |
63 |
70 |
71 |
75 |
76 |
77 |
81 |
82 |
83 |
84 | );
85 | };
86 |
87 | export default Slider;
88 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # 🌻 Sunflower Website
2 |
3 | A beautifully crafted website using the latest web technologies. Built with passion, creativity, and modern tools, **Sunflower** is designed to deliver a seamless user experience.
4 |
5 | ## 📸 Screenshots
6 |
7 | ### 💻 Desktop View
8 |
9 | A clean and modern design for desktop users:
10 |
11 | 
12 |
13 | ---
14 |
15 | ### 📊 Tablet View
16 |
17 | Perfectly scales for tablets and mid-sized devices:
18 |
19 | 
20 |
21 | ### 📱 Mobile View
22 |
23 | Fully responsive and optimized for mobile devices:
24 |
25 | 
26 |
27 | ---
28 |
29 | ## 🚀 Features
30 |
31 | - **⚡ Next.js 14**: Leveraging the power of React with server-side rendering and API routes.
32 | - **🎨 Tailwind CSS**: For fast, responsive, and modern styling.
33 | - **🛠️ TypeScript**: Type-safe development for maintainable code.
34 | - **📡 Mockfly API**: Mock data service powering the dynamic content of the site.
35 | - **🌐 Vercel Deployment**: Deployed on Vercel for fast and reliable hosting.
36 |
37 | ## 🔗 Live Demo
38 |
39 | 👉 [Sunflower Website on Vercel](https://sunflowerdev.vercel.app)
40 |
41 | ---
42 |
43 | ## 🛠️ Tech Stack
44 |
45 | | Technology | Description |
46 | | -------------- | ------------------------------- |
47 | | **Next.js** | Framework for React |
48 | | **Tailwind** | Utility-first CSS Framework |
49 | | **TypeScript** | Static Typing for JavaScript |
50 | | **Mockfly** | API for mock data |
51 | | **Vercel** | Hosting and deployment platform |
52 |
53 | ---
54 |
55 | ## 📦 Installation
56 |
57 | ### Prerequisites
58 |
59 | - Node.js (v18 or higher)
60 | - npm or yarn
61 |
62 | ### Steps
63 |
64 | 1. Clone the repository:
65 | ```bash
66 | git clone https://github.com/frau-azadeh/sunflower-dev.git
67 | cd sunflower-dev
68 | ```
69 |
70 | ### Install dependencies
71 |
72 | npm install
73 | or
74 | yarn install
75 |
76 | ### Run the development server
77 |
78 | npm run dev
79 |
80 | ### Open the app your browser
81 |
82 | http://localhost:3000
83 |
84 | ## 🤝 Contributing
85 |
86 | Contributions are welcome! To contribute:
87 |
88 | Fork the repository.
89 | Create a new branch: git checkout -b feature/my-feature.
90 | Commit your changes: git commit -m "Add my feature".
91 | Push to the branch: git push origin feature/my-feature.
92 | Submit a pull request.
93 |
94 | Author : Azadeh Sharifi Soltani
95 |
--------------------------------------------------------------------------------
/src/app/blog/page.tsx:
--------------------------------------------------------------------------------
1 | import { Metadata } from "next";
2 |
3 | import ArticlesClient from "@/components/ArticlesClient";
4 | import BackButton from "@/components/BackButton";
5 | import Footer from "@/components/Footer";
6 | import NavigationMenu from "@/components/NavigationMenu";
7 | import ScrollToTopButton from "@/components/ScrollToTopButton";
8 | import TopNav from "@/components/TopNav";
9 |
10 | interface ArticleData {
11 | title: string;
12 | description: string;
13 | date: string;
14 | image: string;
15 | slug: string;
16 | category: string;
17 | href: string;
18 | }
19 |
20 | // data for seo
21 | export const metadata: Metadata = {
22 | title: "بلاگ - مقالات تخصصی برنامه نویسی",
23 | description:
24 | "در این بخش از وبسایت آزاده شریفی سلطانی، مقالات تخصصی و آموزنده در زمینه برنامه نویسی و توسعه وب منتشر میشود.",
25 | keywords: [
26 | "بلاگ",
27 | "برنامه نویسی",
28 | "مقالات تخصصی",
29 | "توسعه وب",
30 | "آموزش برنامه نویسی",
31 | ],
32 | openGraph: {
33 | title: "بلاگ - مقالات تخصصی برنامه نویسی",
34 | description:
35 | "در این بخش از وبسایت آزاده شریفی سلطانی، مقالات تخصصی و آموزنده در زمینه برنامه نویسی و توسعه وب منتشر میشود.",
36 | url: "https://sunflower-dev.com/blog",
37 | siteName: "وب سایت آزاده شریفی سلطانی",
38 | images: [
39 | {
40 | url: "/images/react/what-is-the-react.jpeg",
41 | width: 1200,
42 | height: 630,
43 | alt: "تصویری از مقالات بلاگ",
44 | },
45 | ],
46 | locale: "fa_IR",
47 | type: "website",
48 | },
49 | twitter: {
50 | card: "summary_large_image",
51 | title: "بلاگ - مقالات تخصصی برنامه نویسی",
52 | description:
53 | "در این بخش از وبسایت آزاده شریفی سلطانی، مقالات تخصصی و آموزنده در زمینه برنامه نویسی و توسعه وب منتشر میشود.",
54 | creator: "@Azadeh_sharifi",
55 | images: ["/images/react/what-is-the-react.jpeg"],
56 | },
57 | };
58 |
59 | async function fetchArticles(): Promise {
60 | const response = await fetch(
61 | "https://api.mockfly.dev/mocks/ef8e4ba5-5dc1-4b36-9bca-5f59afb45ebe/article",
62 | { cache: "no-store" },
63 | );
64 | const data = await response.json();
65 | return Array.isArray(data) ? data : data.articles || [];
66 | }
67 |
68 | export default async function ArticlesPage() {
69 | const articles = await fetchArticles();
70 |
71 | return (
72 | <>
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 | >
82 | );
83 | }
84 |
--------------------------------------------------------------------------------
/src/app/blog/[category]/page.tsx:
--------------------------------------------------------------------------------
1 | import { Metadata } from "next";
2 |
3 | import BackButton from "@/components/BackButton";
4 | import CategoryClient from "@/components/CategoryClient";
5 | import Footer from "@/components/Footer";
6 | import NavigationMenu from "@/components/NavigationMenu";
7 | import ScrollToTopButton from "@/components/ScrollToTopButton";
8 | import TopNav from "@/components/TopNav";
9 |
10 | interface ArticleData {
11 | title: string;
12 | description: string;
13 | date: string;
14 | image: string;
15 | slug: string;
16 | category: string;
17 | }
18 |
19 | async function fetchArticles(): Promise {
20 | const response = await fetch(
21 | "https://api.mockfly.dev/mocks/ef8e4ba5-5dc1-4b36-9bca-5f59afb45ebe/article",
22 | { cache: "no-store" },
23 | );
24 | const data = await response.json();
25 | return Array.isArray(data.articles) ? data.articles : [];
26 | }
27 |
28 | // SEO
29 | export async function generateMetadata({
30 | params,
31 | }: {
32 | params: { category: string };
33 | }): Promise {
34 | const category = params.category;
35 | return {
36 | title: `دستهبندی ${category} - وبلاگ`,
37 | description: `مقالات دستهبندی ${category} در وبلاگ ما. با جدیدترین مقالات تخصصی در حوزه برنامهنویسی و توسعه وب آشنا شوید.`,
38 | openGraph: {
39 | title: `دستهبندی ${category} - وبلاگ`,
40 | description: `مقالات دستهبندی ${category} در وبلاگ ما. با جدیدترین مقالات تخصصی در حوزه برنامهنویسی و توسعه وب آشنا شوید.`,
41 | url: `https://sunflower-dev.com/blog/${category}`,
42 | siteName: "وبلاگ برنامه نویسی",
43 | images: [
44 | {
45 | url: "/images/react/what-is-the-react.jpeg",
46 | width: 1200,
47 | height: 630,
48 | alt: `تصویری از دستهبندی ${category}`,
49 | },
50 | ],
51 | locale: "fa_IR",
52 | type: "website",
53 | },
54 | twitter: {
55 | card: "summary_large_image",
56 | title: `دستهبندی ${category} - وبلاگ`,
57 | description: `مقالات دستهبندی ${category} در وبلاگ ما. با جدیدترین مقالات تخصصی در حوزه برنامهنویسی و توسعه وب آشنا شوید.`,
58 | images: ["/images/react/what-is-the-react.jpeg"],
59 | },
60 | };
61 | }
62 |
63 | export default async function CategoryPage({
64 | params,
65 | }: {
66 | params: { category: string };
67 | }) {
68 | const articles = await fetchArticles();
69 | const category = params.category;
70 |
71 | return (
72 | <>
73 |
74 |
75 |
76 | مقالات دستهبندی: {category}
77 |
78 |
79 |
80 |
81 |
82 |
83 |
84 | >
85 | );
86 | }
87 |
--------------------------------------------------------------------------------
/src/components/ContactForm.tsx:
--------------------------------------------------------------------------------
1 | "use client";
2 |
3 | import React, { useState } from "react";
4 |
5 | import axios from "axios";
6 |
7 | const ContactForm: React.FC = () => {
8 | const [formData, setFormData] = useState({
9 | name: "",
10 | phone: "",
11 | message: "",
12 | });
13 | const [error, setError] = useState("");
14 | const [success, setSuccess] = useState("");
15 |
16 | const handleChange = (
17 | e: React.ChangeEvent,
18 | ) => {
19 | setFormData({ ...formData, [e.target.name]: e.target.value });
20 | };
21 |
22 | const handleSubmit = async (e: React.FormEvent) => {
23 | e.preventDefault();
24 | setSuccess(""); // delete previous massage
25 | setError(""); // delete previous error
26 |
27 | const phoneRegex = /^09\d{9}$/;
28 |
29 | if (!formData.name || !formData.phone || !formData.message) {
30 | setError("لطفاً تمامی فیلدها را پر کنید.");
31 | return;
32 | }
33 |
34 | if (!phoneRegex.test(formData.phone)) {
35 | setError("شماره تماس باید با 09 شروع شود و 11 رقم باشد.");
36 | return;
37 | }
38 |
39 | try {
40 | await axios.post("/api/contact", formData);
41 | setSuccess("پیام شما با موفقیت ارسال شد."); // ok
42 | setFormData({ name: "", phone: "", message: "" });
43 | } catch (error) {
44 | console.error("Error submitting form:", error);
45 | setError("خطایی در ارسال پیام رخ داده است.");
46 | }
47 | };
48 |
49 | return (
50 |
88 | );
89 | };
90 |
91 | export default ContactForm;
92 |
--------------------------------------------------------------------------------
/src/components/ArticleLayout.tsx:
--------------------------------------------------------------------------------
1 | import { FC } from "react";
2 |
3 | import Image from "next/image";
4 |
5 | interface ArticleLayoutProps {
6 | title: string;
7 | description: string;
8 | date: string;
9 | author: string;
10 | readingTime: string;
11 | image: string;
12 | category: string;
13 | content: { section_title: string; paragraphs: string[] }[];
14 | }
15 |
16 | const ArticleLayout: FC = ({
17 | title,
18 | date,
19 | author,
20 | readingTime,
21 | image,
22 | category,
23 | content,
24 | }) => {
25 | return (
26 |
27 |
28 | {/* Poster Section */}
29 |
30 |
37 |
38 |
39 | {title}
40 |
41 |
42 |
43 |
44 |
45 | {/* Info Section */}
46 |
47 |
48 |
49 | منتشر شده در تاریخ:
50 |
51 |
{date}
52 |
53 |
54 |
نویسنده:
55 |
{author}
56 |
57 |
58 |
دسته بندی:
59 |
{category}
60 |
61 |
62 |
مدت زمان خواندن:
63 |
{readingTime}
64 |
65 |
66 |
67 | {/* Content Section */}
68 |
69 | {content.map((section, index) => (
70 |
71 |
72 | {section.section_title}
73 |
74 | {section.paragraphs.map((paragraph, pIndex) => (
75 |
79 | {paragraph}
80 |
81 | ))}
82 |
83 | ))}
84 |
85 |
86 |
87 | );
88 | };
89 |
90 | export default ArticleLayout;
91 |
--------------------------------------------------------------------------------
/src/app/layout.tsx:
--------------------------------------------------------------------------------
1 | import type { Metadata } from "next";
2 |
3 | import "../styles/fonts.css";
4 | import "./globals.css";
5 |
6 | export const metadata: Metadata = {
7 | title: "وب سایت آزاده شریفی سلطانی",
8 | description:
9 | "من آزاده شریفی سلطانی هستم. سایت من در زمینه برنامه نویسی هست و خوشحال میشم با هم اطلاعاتمون رو اینجا به اشتراک بزاریم",
10 | authors: [{ name: "آزاده شریفی سلطانی", url: "https://sunflower-dev.com" }],
11 | keywords: [
12 | "آزاده شریفی سلطانی",
13 | "برنامه نویسی",
14 | "توسعه وب",
15 | "آموزش برنامه نویسی",
16 | "فرانت اند",
17 | ],
18 | openGraph: {
19 | title: "وب سایت آزاده شریفی سلطانی",
20 | description:
21 | "سایت من در زمینه برنامه نویسی هست و خوشحال میشم با هم اطلاعاتمون رو اینجا به اشتراک بزاریم.",
22 | url: "https://sunflower-dev.com",
23 | siteName: "وب سایت آزاده شریفی سلطانی",
24 | images: [
25 | {
26 | url: "/images/about/azadeh.webp",
27 | width: 1200,
28 | height: 630,
29 | alt: "آزاده شریفی سلطانی",
30 | },
31 | ],
32 | locale: "fa_IR",
33 | type: "website",
34 | },
35 | twitter: {
36 | card: "summary_large_image",
37 | title: "وب سایت آزاده شریفی سلطانی",
38 | description:
39 | "سایت من در زمینه برنامه نویسی هست و خوشحال میشم با هم اطلاعاتمون رو اینجا به اشتراک بزاریم.",
40 | creator: "@Azadeh_sharifi",
41 | images: ["/images/about/azadeh.webp"],
42 | },
43 | };
44 |
45 | export default function RootLayout({
46 | children,
47 | }: Readonly<{
48 | children: React.ReactNode;
49 | }>) {
50 | return (
51 |
52 |
53 | {/* JSON-LD */}
54 |
77 |
94 |
95 |
96 | {children}
97 |
98 |
99 | );
100 | }
101 |
--------------------------------------------------------------------------------
/src/app/blog/[category]/[slug]/page.tsx:
--------------------------------------------------------------------------------
1 | import { Metadata } from "next";
2 |
3 | import ArticleClient from "@/components/ArticleClient";
4 | import BackButton from "@/components/BackButton";
5 | import Footer from "@/components/Footer";
6 | import NavigationMenu from "@/components/NavigationMenu";
7 | import ScrollToTopButton from "@/components/ScrollToTopButton";
8 | import TopNav from "@/components/TopNav";
9 |
10 | interface ArticleData {
11 | title: string;
12 | description: string;
13 | date: string;
14 | author: string;
15 | reading_time: string;
16 | image: string;
17 | content: { section_title: string; paragraphs: string[] }[];
18 | category: string;
19 | slug: string;
20 | }
21 |
22 | async function fetchArticles(): Promise {
23 | const response = await fetch(
24 | "https://api.mockfly.dev/mocks/ef8e4ba5-5dc1-4b36-9bca-5f59afb45ebe/article",
25 | { cache: "no-store" },
26 | );
27 | const data = await response.json();
28 | return Array.isArray(data.articles) ? data.articles : [];
29 | }
30 |
31 | // پیشدریافت پارامترها برای صفحات استاتیک
32 | export async function generateStaticParams() {
33 | const articles = await fetchArticles();
34 | return articles.map((article) => ({
35 | category: article.category,
36 | slug: article.slug,
37 | }));
38 | }
39 |
40 | export async function generateMetadata({
41 | params,
42 | }: {
43 | params: { category: string; slug: string };
44 | }): Promise {
45 | const articles = await fetchArticles();
46 | const article = articles.find(
47 | (a) =>
48 | a.category.toLowerCase() === params.category.toLowerCase() &&
49 | a.slug === params.slug,
50 | );
51 |
52 | return {
53 | title: article ? `${article.title} - وبلاگ` : "مقاله - وبلاگ",
54 | description: article
55 | ? article.description
56 | : "مقالهای درباره برنامهنویسی و توسعه وب.",
57 | openGraph: {
58 | title: article ? `${article.title} - وبلاگ` : "مقاله - وبلاگ",
59 | description: article
60 | ? article.description
61 | : "مقالهای درباره برنامهنویسی و توسعه وب.",
62 | url: `https://sunflower-dev.com/blog/${params.category}/${params.slug}`,
63 | siteName: "وبلاگ برنامه نویسی",
64 | images: [
65 | {
66 | url: article ? article.image : "/default-image.jpg",
67 | width: 1200,
68 | height: 630,
69 | alt: article ? article.title : "مقاله",
70 | },
71 | ],
72 | locale: "fa_IR",
73 | type: "article",
74 | },
75 | twitter: {
76 | card: "summary_large_image",
77 | title: article ? `${article.title} - وبلاگ` : "مقاله - وبلاگ",
78 | description: article
79 | ? article.description
80 | : "مقالهای درباره برنامهنویسی و توسعه وب.",
81 | images: [article ? article.image : "/default-image.jpg"],
82 | },
83 | };
84 | }
85 |
86 | export default async function ArticlePage({
87 | params,
88 | }: {
89 | params: { category: string; slug: string };
90 | }) {
91 | const articles = await fetchArticles();
92 | const article = articles.find(
93 | (a) =>
94 | a.category.toLowerCase() === params.category.toLowerCase() &&
95 | a.slug === params.slug,
96 | );
97 |
98 | return (
99 | <>
100 |
101 |
104 |
105 |
106 |
107 |
108 | >
109 | );
110 | }
111 |
--------------------------------------------------------------------------------
/src/components/ArticleSlider.tsx:
--------------------------------------------------------------------------------
1 | "use client";
2 |
3 | import React, { useEffect, useState } from "react";
4 |
5 | import axios from "axios";
6 | import Image from "next/image";
7 | import { FaAngleDoubleLeft, FaAngleDoubleRight } from "react-icons/fa";
8 | import Slider, { CustomArrowProps, Settings } from "react-slick";
9 |
10 | import "slick-carousel/slick/slick-theme.css";
11 | import "slick-carousel/slick/slick.css";
12 |
13 | interface Article {
14 | slug: string;
15 | image: string;
16 | title: string;
17 | description: string;
18 | date: string;
19 | link: string;
20 | category: string;
21 | }
22 |
23 | const PrevArrow: React.FC = ({ onClick }) => (
24 |
28 |
29 |
30 | );
31 |
32 | const NextArrow: React.FC = ({ onClick }) => (
33 |
37 |
38 |
39 | );
40 |
41 | const ArticleSlider: React.FC = () => {
42 | const [articles, setArticles] = useState([]);
43 |
44 | useEffect(() => {
45 | const fetchArticles = async () => {
46 | try {
47 | const response = await axios.get(
48 | "https://api.mockfly.dev/mocks/ef8e4ba5-5dc1-4b36-9bca-5f59afb45ebe/article",
49 | );
50 |
51 | const articlesData = Array.isArray(response.data)
52 | ? response.data
53 | : response.data.articles;
54 |
55 | if (Array.isArray(articlesData)) {
56 | setArticles(articlesData.slice(-6));
57 | } else {
58 | console.error("دادههای دریافتی از API به صورت آرایه نیست.");
59 | }
60 | } catch (error) {
61 | console.error("خطا در دریافت مقالات:", error);
62 | }
63 | };
64 |
65 | fetchArticles();
66 | }, []);
67 |
68 | const settings: Settings = {
69 | dots: false,
70 | infinite: true,
71 | speed: 500,
72 | slidesToShow: 4,
73 | slidesToScroll: 1,
74 | autoplay: true,
75 | autoplaySpeed: 3000,
76 | arrows: true,
77 | prevArrow: ,
78 | nextArrow: ,
79 | responsive: [
80 | {
81 | breakpoint: 1024,
82 | settings: {
83 | slidesToShow: 2,
84 | },
85 | },
86 | {
87 | breakpoint: 768,
88 | settings: {
89 | slidesToShow: 1,
90 | },
91 | },
92 | {
93 | breakpoint: 480,
94 | settings: {
95 | slidesToShow: 1,
96 | },
97 | },
98 | ],
99 | };
100 |
101 | return (
102 |
103 |
104 | {articles.map((article) => (
105 |
106 |
107 |
108 |
115 |
116 |
117 |
118 | {" "}
119 | {article.title}
120 |
121 |
125 | {article.description}
126 |
127 |
128 |
129 | {article.date}
130 |
131 |
135 | ادامه مطلب
136 |
137 |
138 |
139 |
140 | ))}
141 |
142 |
143 | );
144 | };
145 |
146 | export default ArticleSlider;
147 |
--------------------------------------------------------------------------------
/src/components/Footer.tsx:
--------------------------------------------------------------------------------
1 | "use client";
2 |
3 | import React, { useEffect, useState } from "react";
4 |
5 | import Link from "next/link";
6 | import { AiFillInstagram } from "react-icons/ai";
7 | import { FaGithubSquare, FaLinkedin, FaPhoneSquare } from "react-icons/fa";
8 |
9 | import ContactForm from "./ContactForm";
10 |
11 | interface ArticleData {
12 | title: string;
13 | slug: string;
14 | category: string;
15 | }
16 |
17 | const Footer: React.FC = () => {
18 | const [articles, setArticles] = useState([]);
19 |
20 | useEffect(() => {
21 | const fetchArticles = async () => {
22 | try {
23 | const response = await fetch(
24 | "https://api.mockfly.dev/mocks/ef8e4ba5-5dc1-4b36-9bca-5f59afb45ebe/article",
25 | );
26 | const data = await response.json();
27 | setArticles(data.articles.slice(0, 4));
28 | } catch (error) {
29 | console.error("Error fetching articles:", error);
30 | }
31 | };
32 | fetchArticles();
33 | }, []);
34 |
35 | return (
36 |
144 | );
145 | };
146 |
147 | export default Footer;
148 |
--------------------------------------------------------------------------------
/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 | designweb.azadeh@gmail.com.
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 |
--------------------------------------------------------------------------------
/src/app/page.tsx:
--------------------------------------------------------------------------------
1 | import React from "react";
2 |
3 | import { GrArticle } from "react-icons/gr";
4 | import { HiAcademicCap } from "react-icons/hi";
5 |
6 | import Slider from "@/components/Slider";
7 | import TopNav from "@/components/TopNav";
8 |
9 | import AboutSection from "../components/AboutSection";
10 | import ArticleSlider from "../components/ArticleSlider";
11 | import Footer from "../components/Footer";
12 | import NavigationMenu from "../components/NavigationMenu";
13 | import ScrollToTopButton from "../components/ScrollToTopButton";
14 | import SkillCard from "../components/SkillCard";
15 |
16 | const page = () => {
17 | return (
18 |
19 |
20 |
21 |
22 |
23 |
24 | مهارتهای من
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
38 |
44 |
50 |
56 |
62 |
68 |
74 |
80 |
86 |
92 |
98 |
104 |
110 |
116 |
122 |
123 |
124 |
125 |
126 |
127 | مقالات جدید :{" "}
128 |
129 |
130 |
131 |
132 |
133 |
134 |
135 |
136 |
137 | );
138 | };
139 |
140 | export default page;
141 |
--------------------------------------------------------------------------------
/src/components/TopNav.tsx:
--------------------------------------------------------------------------------
1 | "use client";
2 |
3 | import { useEffect, useState } from "react";
4 |
5 | import Link from "next/link";
6 | import { usePathname } from "next/navigation";
7 |
8 | interface Article {
9 | slug: string;
10 | category: string;
11 | title: string;
12 | }
13 |
14 | const baseSiteUrl =
15 | process.env.NEXT_PUBLIC_BASE_SITE_URL || "https://sunflower-dev.com";
16 |
17 | const TopNav = () => {
18 | const [isOpen, setIsOpen] = useState(false);
19 | const [searchTerm, setSearchTerm] = useState("");
20 | const [allArticles, setAllArticles] = useState([]);
21 | const [searchResults, setSearchResults] = useState([]);
22 | const [noResults, setNoResults] = useState(false);
23 | const pathname = usePathname();
24 |
25 | const toggleMenu = () => {
26 | setIsOpen(!isOpen);
27 | };
28 |
29 | useEffect(() => {
30 | console.log("Base Site URL:", baseSiteUrl);
31 | const fetchArticles = async () => {
32 | try {
33 | const response = await fetch(
34 | `https://api.mockfly.dev/mocks/ef8e4ba5-5dc1-4b36-9bca-5f59afb45ebe/article`,
35 | );
36 | const data = await response.json();
37 |
38 | if (Array.isArray(data)) {
39 | setAllArticles(data);
40 | } else if (data && Array.isArray(data.articles)) {
41 | setAllArticles(data.articles);
42 | } else {
43 | setAllArticles([]);
44 | }
45 | } catch (error) {
46 | console.error("خطا در دریافت مقالات:", error);
47 | }
48 | };
49 |
50 | fetchArticles();
51 | }, []);
52 |
53 | const handleSearch = (event: React.ChangeEvent) => {
54 | const term = event.target.value;
55 | setSearchTerm(term);
56 |
57 | if (term.length > 2) {
58 | const filteredResults = allArticles.filter((article) =>
59 | article.title.toLowerCase().includes(term.toLowerCase()),
60 | );
61 | setSearchResults(filteredResults);
62 | setNoResults(filteredResults.length === 0);
63 | } else {
64 | setSearchResults([]);
65 | setNoResults(false);
66 | }
67 | };
68 |
69 | const isActive = (href: string) => {
70 | const currentUrl = new URL(href, baseSiteUrl);
71 |
72 | // اگر لینک شامل # است، فقط hash را مقایسه کن
73 | if (currentUrl.hash) {
74 | return (
75 | typeof window !== "undefined" &&
76 | window.location.hash === currentUrl.hash
77 | );
78 | }
79 |
80 | // در غیر این صورت، مسیر (pathname) را مقایسه کن
81 | return pathname === currentUrl.pathname;
82 | };
83 |
84 | return (
85 |
86 |
87 |
88 |
89 |
98 | صفحه اصلی
99 |
100 |
109 | درباره من
110 |
111 |
120 | مهارتهای من
121 |
122 |
132 | ارتباط با من
133 |
134 |
143 | مقالات من
144 |
145 |
146 |
147 | {/* Search */}
148 |
149 |
156 |
157 | {searchResults.length > 0
158 | ? searchResults.map((article) => (
159 |
165 | {article.title}
166 |
167 | ))
168 | : noResults && (
169 |
170 | مقالهای پیدا نشد.
171 |
172 | )}
173 |
174 |
175 |
176 | {/* Responsive for mobile */}
177 |
178 |
182 |
189 | {isOpen ? (
190 |
196 | ) : (
197 |
203 | )}
204 |
205 |
206 |
207 |
208 |
209 |
210 | {/* Mobile Menu */}
211 | {isOpen && (
212 |
213 |
218 | صفحه اصلی
219 |
220 |
225 | درباره من
226 |
227 |
232 | مهارتهای من
233 |
234 |
240 | ارتباط با من
241 |
242 |
247 | مقالات من
248 |
249 |
250 | )}
251 |
252 | );
253 | };
254 |
255 | export default TopNav;
256 |
--------------------------------------------------------------------------------