├── .eslintrc.cjs
├── .gitignore
├── README.md
├── index.html
├── package-lock.json
├── package.json
├── postcss.config.js
├── public
├── Desktop.png
├── banner.jpeg
├── bombing-lg.png
├── bombing.png
├── couple.jpeg
├── girl.png
├── login.png
├── logo.png
├── otpimage.png
└── vite.svg
├── src
├── App.jsx
├── components
│ ├── Footer
│ │ └── footer.jsx
│ ├── Hamberger
│ │ └── Hamberger.jsx
│ ├── Volunteer
│ │ ├── VolunteerCard.css
│ │ └── VolunteerCard.jsx
│ ├── abuse
│ │ └── abuseBanner.jsx
│ ├── cards
│ │ ├── CommunityPage.jsx
│ │ ├── StoryPage.jsx
│ │ ├── landingcard.jsx
│ │ └── storycard.jsx
│ ├── landing
│ │ └── banner.jsx
│ ├── message
│ │ ├── input.css
│ │ ├── inputmessage.jsx
│ │ └── message.jsx
│ └── navbar
│ │ └── navbar.jsx
├── constents.js
├── features
│ └── userSlice.js
├── index.css
├── main.jsx
├── pages
│ ├── abuse
│ │ └── abuse.jsx
│ ├── complaint
│ │ └── complaint.jsx
│ ├── help
│ │ └── help.jsx
│ ├── landing
│ │ └── landing.jsx
│ ├── login
│ │ └── login.jsx
│ ├── otp
│ │ └── otp.jsx
│ ├── register
│ │ └── register.jsx
│ └── story
│ │ ├── Community.jsx
│ │ └── Stories.jsx
└── store.js
├── tailwind.config.js
└── vite.config.js
/.eslintrc.cjs:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | root: true,
3 | env: { browser: true, es2020: true },
4 | extends: [
5 | 'eslint:recommended',
6 | 'plugin:react/recommended',
7 | 'plugin:react/jsx-runtime',
8 | 'plugin:react-hooks/recommended',
9 | ],
10 | ignorePatterns: ['dist', '.eslintrc.cjs'],
11 | parserOptions: { ecmaVersion: 'latest', sourceType: 'module' },
12 | settings: { react: { version: '18.2' } },
13 | plugins: ['react-refresh'],
14 | rules: {
15 | 'react/jsx-no-target-blank': 'off',
16 | 'react-refresh/only-export-components': [
17 | 'warn',
18 | { allowConstantExport: true },
19 | ],
20 | },
21 | }
22 |
--------------------------------------------------------------------------------
/.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 |
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 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # When She Knows
2 |
3 | ## Project Overview
4 |
5 | "When She Knows" is a transformative project dedicated to empowering women who are facing psychological abuse. Our platform provides a safe and supportive community where women can connect, share experiences, and find solace amidst the challenges of psychological trauma.
6 | fully responsive design for the better user interaction
7 |
8 | [Hosted Live Link ](https://whensheknows.vercel.app/)
9 | [Watch the demo video showcasing all functionalities and features](https://youtu.be/1cL-mstM7_o)
10 |
11 | ## Features:
12 |
13 | - **Community Space:** Join a vibrant community of like-minded individuals, offering support, understanding, and solidarity.
14 |
15 | - **Group Chat:** Engage in real-time conversations with fellow members, fostering connections and providing immediate support.
16 |
17 | - **Dynamic Storytelling:** Explore a curated collection of stories showcasing resilience and triumph over psychological abuse.
18 |
19 | - **Awareness Page:** Access informative resources and educational materials to deepen understanding about psychological abuse.
20 |
21 | - **Expert Consultation:** Connect with professionals and utilize an AI-integrated help desk for personalized guidance and support.
22 |
23 | - **Beautiful Landing Page:** Experience a visually stunning interface that invites users to embark on a journey of healing and self-discovery.
24 |
25 | ## Getting Started
26 |
27 | To set up the frontend locally, follow these steps:
28 |
29 | ### Prerequisites
30 |
31 | - Node.js installed on your machine.
32 | - Git installed on your machine.
33 | - An internet connection to fetch dependencies.
34 |
35 | ### Installation Steps
36 |
37 | 1. Clone the repository to your local machine:
38 | git clone https://github.com/asifxohd/hackathon-frontend.git
39 |
40 | 2. cd projec dir
41 | 3. npm install
42 | 4. npm run dev
43 |
44 |
--------------------------------------------------------------------------------
/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 | When: She Knows
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
19 |
20 |
21 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "frontend",
3 | "private": true,
4 | "version": "0.0.0",
5 | "type": "module",
6 | "scripts": {
7 | "dev": "vite",
8 | "build": "vite build",
9 | "lint": "eslint . --ext js,jsx --report-unused-disable-directives --max-warnings 0",
10 | "preview": "vite preview"
11 | },
12 | "dependencies": {
13 | "@material-tailwind/react": "^2.1.9",
14 | "@reduxjs/toolkit": "^2.2.1",
15 | "aos": "^2.3.4",
16 | "axios": "^1.6.7",
17 | "framer-motion": "^11.0.8",
18 | "js-cookie": "^3.0.5",
19 | "modal": "^1.2.0",
20 | "react": "^18.2.0",
21 | "react-cookie": "^7.1.0",
22 | "react-dom": "^18.2.0",
23 | "react-icons": "^5.0.1",
24 | "react-modal": "^3.16.1",
25 | "react-redux": "^9.1.0",
26 | "react-router-dom": "^6.22.3",
27 | "react-toastify": "^10.0.4"
28 | },
29 | "devDependencies": {
30 | "@types/react": "^18.2.56",
31 | "@types/react-dom": "^18.2.19",
32 | "@vitejs/plugin-react": "^4.2.1",
33 | "autoprefixer": "^10.4.18",
34 | "eslint": "^8.56.0",
35 | "eslint-plugin-react": "^7.33.2",
36 | "eslint-plugin-react-hooks": "^4.6.0",
37 | "eslint-plugin-react-refresh": "^0.4.5",
38 | "postcss": "^8.4.35",
39 | "tailwindcss": "^3.4.1",
40 | "vite": "^5.1.4"
41 | }
42 | }
43 |
--------------------------------------------------------------------------------
/postcss.config.js:
--------------------------------------------------------------------------------
1 | export default {
2 | plugins: {
3 | tailwindcss: {},
4 | autoprefixer: {},
5 | },
6 | }
7 |
--------------------------------------------------------------------------------
/public/Desktop.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/asifxohd/hackathon-frontend/0c7229e5d7f737a861b178cfb32fbeb9a23841ca/public/Desktop.png
--------------------------------------------------------------------------------
/public/banner.jpeg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/asifxohd/hackathon-frontend/0c7229e5d7f737a861b178cfb32fbeb9a23841ca/public/banner.jpeg
--------------------------------------------------------------------------------
/public/bombing-lg.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/asifxohd/hackathon-frontend/0c7229e5d7f737a861b178cfb32fbeb9a23841ca/public/bombing-lg.png
--------------------------------------------------------------------------------
/public/bombing.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/asifxohd/hackathon-frontend/0c7229e5d7f737a861b178cfb32fbeb9a23841ca/public/bombing.png
--------------------------------------------------------------------------------
/public/couple.jpeg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/asifxohd/hackathon-frontend/0c7229e5d7f737a861b178cfb32fbeb9a23841ca/public/couple.jpeg
--------------------------------------------------------------------------------
/public/girl.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/asifxohd/hackathon-frontend/0c7229e5d7f737a861b178cfb32fbeb9a23841ca/public/girl.png
--------------------------------------------------------------------------------
/public/login.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/asifxohd/hackathon-frontend/0c7229e5d7f737a861b178cfb32fbeb9a23841ca/public/login.png
--------------------------------------------------------------------------------
/public/logo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/asifxohd/hackathon-frontend/0c7229e5d7f737a861b178cfb32fbeb9a23841ca/public/logo.png
--------------------------------------------------------------------------------
/public/otpimage.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/asifxohd/hackathon-frontend/0c7229e5d7f737a861b178cfb32fbeb9a23841ca/public/otpimage.png
--------------------------------------------------------------------------------
/public/vite.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/App.jsx:
--------------------------------------------------------------------------------
1 |
2 | import { createContext, useState } from "react";
3 | import Landing from "./pages/landing/landing"
4 | import LoginForm from "./pages/login/login"
5 | import OtpForm from "./pages/otp/otp"
6 | import Register from "./pages/register/register"
7 | import Community from "./pages/story/Community"
8 | import Hamberger from "./components/Hamberger/Hamberger";
9 | import StoriesPage from "./pages/story/Stories";
10 | import Abuse from "./pages/abuse/abuse";
11 | import Help from "./pages/help/help";
12 | import { ToastContainer, toast } from 'react-toastify';
13 | import 'react-toastify/dist/ReactToastify.css';
14 | import Complaint from "./pages/complaint/complaint";
15 | import { BrowserRouter, Route, Routes } from 'react-router-dom'
16 | import { useSelector } from "react-redux";
17 |
18 |
19 | const MyContext = createContext();
20 |
21 |
22 | function App() {
23 |
24 | const [open, setOpen] = useState(false);
25 | const { user } = useSelector((state) => state.user);
26 |
27 | return (
28 | <>
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 | } />
39 | } />
40 | } />
41 | } />
42 | )} />
43 | )} />
44 | )} />
45 | } />
46 | } />
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 | >
55 | )
56 | }
57 |
58 | export { MyContext };
59 | export default App
60 |
--------------------------------------------------------------------------------
/src/components/Footer/footer.jsx:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 |
3 | const Footer = () => {
4 | return (
5 |
39 | );
40 | };
41 |
42 | export default Footer;
43 |
--------------------------------------------------------------------------------
/src/components/Hamberger/Hamberger.jsx:
--------------------------------------------------------------------------------
1 | import React, { useState } from "react";
2 | import { useSelector } from "react-redux";
3 |
4 | function Hamberger({ prop }) {
5 | const { open, setOpen } = prop;
6 | const { user } = useSelector((state) => state.user);
7 |
8 | return (
9 | <>
10 | {open && (
11 |
12 |
13 |
setOpen(false)}
16 | >
17 |
26 |
27 |
28 |
29 |
30 |
31 |
handleNavigation("stories")}
34 | >
35 | Stories
36 |
37 |
handleNavigation("legal-insights")}
40 | >
41 | Legal Insights
42 |
43 |
handleNavigation("who-we-are")}
46 | >
47 | Who We Are
48 |
49 |
handleNavigation("community")}
52 | >
53 | Community
54 |
55 | {user && (
56 |
handleNavigation("community")}
59 | >
60 | Login
61 |
62 | )}
63 |
64 |
65 |
66 | )}
67 | >
68 | );
69 | }
70 |
71 | export default Hamberger;
72 |
--------------------------------------------------------------------------------
/src/components/Volunteer/VolunteerCard.css:
--------------------------------------------------------------------------------
1 | .card {
2 | width: 190px;
3 | height: 254px;
4 | background: rgb(244, 229, 208);
5 | transition: all 0.4s;
6 | border-radius: 10px;
7 | font-size: 20px;
8 | font-weight: 900;
9 | }
10 |
11 | .card:hover {
12 | border-radius: 15px;
13 | cursor: pointer;
14 | transform: scale(1.2);
15 | box-shadow: 0px 0px 5px 1px rgba(0, 0, 0, 0.705);
16 | background: rgb(218, 219, 219);
17 | }
18 |
19 | .first-content {
20 | height: 100%;
21 | width: 100%;
22 | transition: all 0.4s;
23 | display: flex;
24 | justify-content: center;
25 | align-items: center;
26 | opacity: 1;
27 | border-radius: 15px;
28 | }
29 |
30 | .card:hover .first-content {
31 | height: 0px;
32 | opacity: 0;
33 | }
34 |
35 | .second-content {
36 | height: 0%;
37 | width: 100%;
38 | opacity: 0;
39 | display: flex;
40 | justify-content: center;
41 | align-items: center;
42 | border-radius: 15px;
43 | transition: all 0.4s;
44 | font-size: 0px;
45 | transform: rotate(90deg) scale(1);
46 | }
47 |
48 | .card:hover .second-content {
49 | opacity: 1;
50 | height: 100%;
51 | font-size: 1rem;
52 | transform: rotate(0deg);
53 | }
54 |
--------------------------------------------------------------------------------
/src/components/Volunteer/VolunteerCard.jsx:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import './VolunteerCard.css'
3 | function VolunteerCard({prop}) {
4 | return (
5 |
6 |
7 | {prop.name}
8 | {prop.location}
9 |
10 |
11 |
12 |
13 |
14 | {prop.name}
15 | {prop.number}
16 | {prop.location}
17 |
18 |
19 |
20 |
21 | );
22 | }
23 |
24 | export default VolunteerCard;
25 |
--------------------------------------------------------------------------------
/src/components/abuse/abuseBanner.jsx:
--------------------------------------------------------------------------------
1 | import Navbar from "../navbar/navbar";
2 |
3 | const AbuseBanner = () => {
4 |
5 | return (
6 | <>
7 |
8 |
9 |
10 |
11 |
12 |
13 |
What Exactly Is Psychological Abuse ?
14 |
Abuse means someone uses words or actions to make you feel bad about yourself all the time. They might say mean things or make you scared, even if you didn't do anything wrong. It's not okay for anyone to treat you like that. It can make you feel really sad and scared, but you're not alone. There are people who can help you feel better and safer. Remember, it's not your fault, and you deserve to be treated with kindness and respect
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
What Exactly Is Psychological Abuse ?
27 |
Abuse means someone uses words or actions to make you feel bad about yourself all the time. They might say mean things or make you scared, even if you didn't do anything wrong. It's not okay for anyone to treat you like that. It can make you feel really sad and scared, but you're not alone. There are people who can help you feel better and safer. Remember, it's not your fault, and you deserve to be treated with kindness and respect
28 |
29 |
30 |
31 |
32 |
33 |
34 | >
35 | );
36 | }
37 |
38 | export default AbuseBanner
--------------------------------------------------------------------------------
/src/components/cards/CommunityPage.jsx:
--------------------------------------------------------------------------------
1 | import { useState } from "react";
2 | import Modal from "react-modal";
3 |
4 | import { FaArrowRight } from "react-icons/fa";
5 | import { IoClose } from "react-icons/io5";
6 | import { Link } from "react-router-dom";
7 | import { BASE_URL, local } from "../../constents";
8 | import axios from "axios";
9 | import { toast } from "react-toastify";
10 |
11 | const StoryPageCard = () => {
12 |
13 | const [isModalOpen, setIsModalOpen] = useState(false);
14 | const [name, setName] = useState('')
15 | const [phoneNumber, setPhoneNumber] = useState('')
16 | const [location , setLocation] = useState('')
17 |
18 |
19 |
20 | const openModal = () => {
21 | setIsModalOpen(true);
22 | };
23 |
24 | const closeModal = () => {
25 | setName('')
26 | setPhoneNumber('')
27 | setLocation('')
28 | setIsModalOpen(false);
29 | };
30 |
31 |
32 | const handleVolunteerButtonClick = () => {
33 | const data = {
34 | name: name,
35 | number: phoneNumber,
36 | location: location
37 | };
38 |
39 | axios.post(BASE_URL+'add-volunteer', data)
40 | .then(response => {
41 | console.log('Request successful:', response.data);
42 | toast.success('Volunteer added successfully')
43 | closeModal()
44 | })
45 | .catch(error => {
46 | console.error('Error:', error);
47 | toast.error(error)
48 | });
49 | };
50 |
51 | return (
52 | <>
53 |
54 |
58 |
63 |
64 | "For years I thought I was losing my mind. My husband was always nice to me and doing thoughtful things for me, but then there were times he would subtly put me down and make me feel like I wasn’t worth anything. If I tried to bring up something he said to me and how it upset me, I was met with ‘You know I didn’t mean it that way’, ‘I NEVER said anything like that. Why would you think that I would say something like that?’, or ‘I think you are just being overly emotional and your depression/anxiety is making you feel that way’. Nothing was ever his fault, it was all mine. Even when I learned of an affair he had, it was my fault because I was neglecting him emotionally/sexually. Once I got free of the situation, I was able to see the control for what it was. I wasn’t losing my mind, I was just living with someone who tried to chip away my reality and personality.”
65 |
66 | Teresa
67 |
68 | Survivar of physical abuse
69 |
70 |
75 |
76 |
77 |
78 |
79 |
83 |
88 |
89 | "I didn't understand what was happening until I started googling my ex's bizarre behaviors and the subject of narcissism kept popping up. I was being gaslit and love bombed but didn't know what that was. I knew that he was playing mind games with me but didn't understand why. This all happened within the first year. Then there [were] the anger rages. That was another confusing behavior. After that I discovered the porn addiction and texting strange women. I was on and off for three years while trying to figure out what was happening and trying to make sense of it all. I was lucky the abuse never turned physical because I believe he was very capable of inflicting great harm. Then the discard begin. I finally ended it first and went 100% no contact because by then I had become educated on the subject."
90 |
91 | Justine
92 |
93 | survivor of physical abuse
94 |
95 |
96 |
97 |
98 |
99 |
100 | Load More
101 |
102 |
103 |
104 |
105 |
106 |
107 |
108 |
109 |
110 | Join Our Volunteer Team: Enriching Lives, Creating Change for Women
111 | Everywhere!
112 |
113 |
114 |
115 |
116 | Volunteer With Us: Make a Difference in Women's Lives. Are you
117 | passionate about making a positive impact in the lives of women?
118 | Join our dedicated volunteer team and be a part of something
119 | extraordinary. Together, we strive to create meaningful change,
120 | foster support networks, and uplift women from all walks of life.
121 | Your time, skills, and commitment can contribute to building a
122 | stronger, more inclusive community. Join us on this rewarding
123 | journey of empowerment and solidarity. Together, we can shape a
124 | brighter future for women everywhere.
125 |
126 |
127 |
128 |
132 |
133 | Become a volunteer
134 |
135 |
136 |
137 |
138 |
168 |
169 |
170 |
171 |
172 |
173 |
174 |
175 |
176 |
177 | Become A Volunteer
178 |
179 |
180 |
227 |
228 |
229 | >
230 | );
231 | };
232 |
233 | export default StoryPageCard;
234 |
--------------------------------------------------------------------------------
/src/components/cards/StoryPage.jsx:
--------------------------------------------------------------------------------
1 | import { useEffect, useState } from "react";
2 | import Modal from "react-modal";
3 | import { FaArrowRight } from "react-icons/fa";
4 | import { IoClose } from "react-icons/io5";
5 | import { BASE_URL, local } from "../../constents";
6 | import axios from "axios";
7 | import { toast } from "react-toastify";
8 |
9 | const StoryPage = () => {
10 | const [isModalOpen, setIsModalOpen] = useState(false);
11 | const [name, setName] = useState("");
12 | const [title, setTitle] = useState("");
13 | const [description, setDescription] = useState("");
14 | const [image, setImage] = useState(null);
15 | const [stories, setStories] = useState([]);
16 | const [count, setCount] = useState(3);
17 | useEffect(() => {
18 | axios
19 | .get(BASE_URL + "stories")
20 | .then((response) => {
21 | console.log(response.data.story);
22 | setStories(response.data.story);
23 | })
24 | .catch((error) => toast.error(error));
25 | }, []);
26 |
27 | function counterIncrease() {
28 | var i = 0;
29 | while (i < 3) {
30 | if (count <= stories.length) {
31 | setCount((count) => count + 1);
32 | i = i + 1;
33 | } else {
34 | break;
35 | }
36 | }
37 | }
38 |
39 | const openModal = () => {
40 | setIsModalOpen(true);
41 | };
42 |
43 | const closeModal = () => {
44 | setIsModalOpen(false);
45 | };
46 |
47 | const handleImageChange = (e) => {
48 | const file = e.target.files[0];
49 | if (file) {
50 | setImage(file);
51 |
52 | const reader = new FileReader();
53 | reader.onload = (e) => {
54 | const imageViewer = document.querySelector(".image-viewer");
55 | if (imageViewer) {
56 | imageViewer.style.backgroundImage = `url(${e.target.result})`; // Corrected
57 | imageViewer.style.display = "block";
58 | }
59 | };
60 | reader.readAsDataURL(file);
61 | }
62 | };
63 |
64 | const handleShare = () => {
65 | const formData = new FormData();
66 | formData.append("image", image);
67 | formData.append("name", name);
68 | formData.append("title", title);
69 | formData.append("description", description);
70 | axios
71 | .post(BASE_URL + "add-story", formData)
72 | .then((response) => {
73 | console.log(response.data);
74 | console.log("Request successful:", response.data);
75 | })
76 | .catch((error) => {
77 | console.error("Error:", error);
78 | });
79 |
80 | setName("");
81 | setTitle("");
82 | setDescription("");
83 | setImage(null);
84 | closeModal();
85 | };
86 |
87 | return (
88 | <>
89 | {stories.map((prop, index) => {
90 | if (index % 2 == 0 && index < count) {
91 | return (
92 |
93 |
97 |
102 |
103 | {prop.description}
104 |
105 | {prop.name}
106 |
107 | {prop.title}
108 |
109 |
114 |
115 |
116 | );
117 | } else if (index % 2 == 1 && index < count) {
118 | return (
119 |
120 |
124 |
129 |
130 | {prop.description}
131 |
132 | {prop.name}
133 |
134 | {prop.title}
135 |
136 |
137 |
138 | );
139 | }
140 | })}
141 |
142 | counterIncrease()}
145 | >
146 |
147 | Load More
148 |
149 |
150 |
151 |
152 |
153 |
154 |
155 |
156 |
157 | Add Stories
158 |
159 |
160 |
161 |
162 | Dive into the powerful narratives on our "Breaking Chains: Women's
163 | Stories of Resilience" page, where courage takes center stage. These
164 | are more than just stories—they're beacons of strength, showcasing
165 | women who've faced adversity and emerged victorious. In this
166 | collection, find inspiration, support, and a testament to the
167 | unyielding spirit that triumphs over the darkest moments. Join us as
168 | we celebrate the indomitable resilience of these women, proving that
169 | even in the face of abuse, the human spirit can break free and soar.
170 |
171 |
172 |
173 |
177 |
178 | Add Stories
179 |
180 |
181 |
182 |
183 |
213 |
214 |
215 |
216 |
217 |
218 |
219 |
220 |
221 |
222 | Share your Story
223 |
224 |
225 |
226 |
227 |
228 | Name
229 |
230 |
231 | setName(e.target.value)}
234 | placeholder="Enter your name "
235 | className="peer h-full w-full rounded-md border border-black border-opacity-20 focus:border-black focus:border-opacity-100 bg-transparent px-3 py-3 font-sans text-sm font-normal text-blue-gray-700 outline outline-0 transition-all placeholder-shown:border placeholder-shown:border-blue-gray-200 placeholder-shown:border-t-blue-gray-200 focus:outline-0 disabled:border-0 disabled:bg-blue-gray-50"
236 | />
237 |
238 |
239 | Title
240 |
241 |
242 | setTitle(e.target.value)}
245 | placeholder="Entere your Title"
246 | className="peer h-full w-full rounded-md border border-black border-opacity-20 focus:border-black focus:border-opacity-100 bg-transparent px-3 py-3 font-sans text-sm font-normal text-blue-gray-700 outline outline-0 transition-all placeholder-shown:border placeholder-shown:border-blue-gray-200 placeholder-shown:border-t-blue-gray-200 focus:outline-0 disabled:border-0 disabled:bg-blue-gray-50"
247 | />
248 |
249 |
250 | Description
251 |
252 |
253 | setDescription(e.target.value)}
256 | placeholder="Enter your story"
257 | className="peer h-full w-full rounded-md border border-black border-opacity-20 focus:border-black focus:border-opacity-100 bg-transparent px-3 py-3 font-sans text-sm font-normal text-blue-gray-700 outline outline-0 transition-all placeholder-shown:border placeholder-shown:border-blue-gray-200 placeholder-shown:border-t-blue-gray-200 focus:outline-0 disabled:border-0 disabled:bg-blue-gray-50"
258 | rows="4"
259 | />
260 |
261 |
262 |
263 | Upload Image
264 |
265 |
266 |
271 |
272 | {image ? (
273 |
274 | ) : (
275 | ""
276 | )}
277 |
278 |
279 |
284 | Share
285 |
286 |
287 |
288 |
289 | >
290 | );
291 | };
292 |
293 | export default StoryPage;
--------------------------------------------------------------------------------
/src/components/cards/landingcard.jsx:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 |
3 | const Card = ({prop}) => {
4 | return (
5 |
6 |
7 |
8 |
{prop.header}
9 |
{prop.content}
10 |
11 |
12 | );
13 | };
14 |
15 | export default Card;
16 |
--------------------------------------------------------------------------------
/src/components/cards/storycard.jsx:
--------------------------------------------------------------------------------
1 | import { useNavigate } from "react-router-dom";
2 | import { BASE_URL, local } from "../../constents";
3 |
4 |
5 | const StoryCard = ({prop}) => {
6 | const navigator=useNavigate()
7 | console.log(local+prop.image)
8 | return (
9 | navigator('/stories')} className=" max-sm:w-[70%] w-72 p-3 h-96 rounded-md overflow-hidden transform transition-transform duration-300 hover:scale-105">
10 |
11 |
12 |
{prop.title}
13 |
{prop.description}
14 |
read more
15 |
16 |
17 | );
18 | }
19 |
20 | export default StoryCard
--------------------------------------------------------------------------------
/src/components/landing/banner.jsx:
--------------------------------------------------------------------------------
1 |
2 | const Banner = () => {
3 | return (
4 |
5 |
6 |
7 |
8 |
9 |
From Hurt to Healing
10 |
Welcome to "From Hurt to Healing," a platform dedicated to supporting women who have experienced psychological abuse within their households. We understand the pain and trauma that can stem from such experiences, and we're here to provide a safe space for healing and empowerment.
11 |
12 |
13 |
14 |
15 |
16 | );
17 | }
18 |
19 | export default Banner;
20 |
--------------------------------------------------------------------------------
/src/components/message/input.css:
--------------------------------------------------------------------------------
1 | .messageBox {
2 | width: fit-content;
3 | height: 40px;
4 | display: flex;
5 | align-items: center;
6 | justify-content: center;
7 | background-color: #2d2d2d;
8 | padding: 0 15px;
9 | border-radius: 10px;
10 | border: 1px solid rgb(63, 63, 63);
11 | }
12 | .messageBox:focus-within {
13 | border: 1px solid rgb(110, 110, 110);
14 | }
15 | .fileUploadWrapper {
16 | width: fit-content;
17 | height: 100%;
18 | display: flex;
19 | align-items: center;
20 | justify-content: center;
21 | font-family: Arial, Helvetica, sans-serif;
22 | }
23 |
24 | #file {
25 | display: none;
26 | }
27 | .fileUploadWrapper label {
28 | cursor: pointer;
29 | width: fit-content;
30 | height: fit-content;
31 | display: flex;
32 | align-items: center;
33 | justify-content: center;
34 | position: relative;
35 | }
36 | .fileUploadWrapper label svg {
37 | height: 18px;
38 | }
39 | .fileUploadWrapper label svg path {
40 | transition: all 0.3s;
41 | }
42 | .fileUploadWrapper label svg circle {
43 | transition: all 0.3s;
44 | }
45 | .fileUploadWrapper label:hover svg path {
46 | stroke: #fff;
47 | }
48 | .fileUploadWrapper label:hover svg circle {
49 | stroke: #fff;
50 | fill: #3c3c3c;
51 | }
52 | .fileUploadWrapper label:hover .tooltip {
53 | display: block;
54 | opacity: 1;
55 | }
56 | .tooltip {
57 | position: absolute;
58 | top: -40px;
59 | display: none;
60 | opacity: 0;
61 | color: white;
62 | font-size: 10px;
63 | text-wrap: nowrap;
64 | background-color: #000;
65 | padding: 6px 10px;
66 | border: 1px solid #3c3c3c;
67 | border-radius: 5px;
68 | box-shadow: 0px 5px 10px rgba(0, 0, 0, 0.596);
69 | transition: all 0.3s;
70 | }
71 | #messageInput {
72 | width: 90%;
73 | height: 100%;
74 | background-color: transparent;
75 | outline: none;
76 | border: none;
77 | padding-left: 10px;
78 | color: white;
79 | }
80 | #messageInput:focus ~ #sendButton svg path,
81 | #messageInput:valid ~ #sendButton svg path {
82 | fill: #3c3c3c;
83 | stroke: white;
84 | }
85 |
86 | #sendButton {
87 | width: fit-content;
88 | height: 100%;
89 | background-color: transparent;
90 | outline: none;
91 | border: none;
92 | display: flex;
93 | align-items: center;
94 | justify-content: center;
95 | cursor: pointer;
96 | transition: all 0.3s;
97 | }
98 | #sendButton svg {
99 | height: 18px;
100 | transition: all 0.3s;
101 | }
102 | #sendButton svg path {
103 | transition: all 0.3s;
104 | }
105 | #sendButton:hover svg path {
106 | fill: #3c3c3c;
107 | stroke: white;
108 | }
109 |
--------------------------------------------------------------------------------
/src/components/message/inputmessage.jsx:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import './input.css'
3 | import axios from 'axios';
4 | import { BASE_URL } from '../../constents';
5 |
6 | const InputMessage = ({prop}) => {
7 |
8 | const {query,setQuery,setQuestion,setResult}=prop;
9 |
10 |
11 | async function submitMessage() {
12 | const data = {
13 | userPrompt: query,
14 | };
15 |
16 | await axios.post(BASE_URL+'chatbot', data)
17 | .then((response) => {
18 | console.log(response.data.response);
19 | setResult(response.data.response);
20 | })
21 | .catch((error) => {
22 | console.log(error);
23 | setResult("Give a valid input");
24 | });
25 | }
26 |
27 | return (
28 |
29 |
30 |
setQuery(e.target.value)} value={query} required="" placeholder="Message..." type="text" id="messageInput" />
31 |
{setQuestion(query)
32 | submitMessage()}} id="sendButton">
33 |
34 |
38 |
45 |
46 |
47 |
48 | );
49 | };
50 |
51 | export default InputMessage;
52 |
--------------------------------------------------------------------------------
/src/components/message/message.jsx:
--------------------------------------------------------------------------------
1 | import { useState } from "react";
2 | import { AiFillCloseSquare } from "react-icons/ai";
3 | import InputMessage from "./inputmessage";
4 | import { BiSolidMessageRoundedDetail } from "react-icons/bi";
5 |
6 |
7 | const Message = ({prop}) => {
8 | const {openMessage,setOpenMessage}=prop
9 | const [query,setQuery]=useState('')
10 | const [result,setResult]=useState('')
11 | const [question,setQuestion]=useState('')
12 |
13 | return(
14 | <>
15 | {(!openMessage)&&setOpenMessage(true)} className="fixed bg-black rounded-3xl z-20 h-[50px] w-[50px] sm:h-[70px] sm:w-[70px] bottom-28 sm:p-4 p-2 right-5">
}
16 | {(openMessage)&&
17 |
setOpenMessage(false)} className=" p-3 text-white w-full flex justify-between font-black mt-2">
Enter What You Need To Know!!
18 |
19 | {(question)&&
Question: {question}
}
20 | {(result)&&
Answer: {result}
}
21 |
22 |
23 |
24 |
25 |
26 |
27 |
}
28 | >
29 | );
30 | }
31 |
32 | export default Message
--------------------------------------------------------------------------------
/src/components/navbar/navbar.jsx:
--------------------------------------------------------------------------------
1 | import { useContext, useEffect, useState } from "react";
2 | import { MyContext } from "../../App";
3 | import { Link, useNavigate } from "react-router-dom";
4 | import { useDispatch, useSelector } from "react-redux";
5 | import { deleteUserData } from "../../features/userSlice";
6 |
7 |
8 | const Navbar = () => {
9 | const [scrolling, setScrolling] = useState(false);
10 | const {open,setOpen}=useContext(MyContext)
11 | const navigator=useNavigate()
12 | const dispatch = useDispatch();
13 | const { user } = useSelector((state) => state.user);
14 | console.log('user',user)
15 |
16 | useEffect(() => {
17 | const handleScroll = () => {
18 | if (window.scrollY > 0) {
19 | setScrolling(true);
20 | } else {
21 | setScrolling(false);
22 | }
23 | };
24 |
25 | window.addEventListener("scroll", handleScroll);
26 |
27 | return () => {
28 | window.removeEventListener("scroll", handleScroll);
29 | };
30 | }, []);
31 |
32 | return (
33 | <>
34 |
41 |
42 |
43 |
navigator('/')} className="">
44 |
49 |
54 |
55 |
56 |
57 |
58 |
59 | navigator('/')}
61 | className="text-black mx-4 font-serif font-bold hover:text-gray-600 cursor-pointer"
62 | >
63 | Home
64 |
65 | navigator('/abuse')}
67 | className="text-black mx-4 font-serif font-bold hover:text-gray-600 cursor-pointer"
68 | >
69 | Identify abuse
70 |
71 | navigator("/community")}
73 | className="text-black mx-4 font-serif font-bold hover:text-gray-600 cursor-pointer"
74 | >
75 | Community
76 |
77 | navigator("/stories")}
79 | className="text-black mx-4 font-serif font-bold hover:text-gray-600 cursor-pointer"
80 | >
81 | Stories
82 |
83 | navigator("/help")}
85 | className="text-black mx-4 font-serif font-bold hover:text-gray-600 cursor-pointer"
86 | >
87 | Help
88 |
89 | {(user)&&(navigator("/consult")}
91 | className="text-black mx-4 font-serif font-bold hover:text-gray-600 cursor-pointer"
92 | >
93 | Consult
94 | )
95 | }
96 |
97 |
98 |
99 |
100 | {(!user)?(
101 |
104 |
105 |
106 |
107 | Login{" "}
108 |
109 |
110 |
):(
{dispatch(deleteUserData())}} className="right-portion me-6 max-lg:hidden">
111 |
114 |
115 |
116 |
117 | Logout{" "}
118 |
119 |
120 |
)}
121 | {!open && (
122 |
setOpen(true)}
124 | className="center-portion flex lg:hidden justify-center pe-0"
125 | >
126 |
134 |
135 |
136 |
137 | )}
138 |
139 | >
140 | );
141 | };
142 |
143 | export default Navbar;
144 |
--------------------------------------------------------------------------------
/src/constents.js:
--------------------------------------------------------------------------------
1 | export const BASE_URL = "http://127.0.0.1:8000/api/users/"
2 | export const local ='http://127.0.0.1:8000/static/'
--------------------------------------------------------------------------------
/src/features/userSlice.js:
--------------------------------------------------------------------------------
1 | import { createSlice } from "@reduxjs/toolkit";
2 |
3 |
4 |
5 | const INITIAL_STATE = {
6 | user:null
7 | }
8 |
9 | const checkUserExist = () => {
10 | const user = localStorage.getItem('user');
11 | INITIAL_STATE.user = JSON.parse(user);
12 | return INITIAL_STATE
13 | }
14 |
15 |
16 |
17 | const userSlice = createSlice({
18 | name:'user',
19 | initialState:checkUserExist(),
20 | reducers:{
21 | deleteUserData: (state, action) => {
22 | state.user = null;
23 | localStorage.removeItem('user');
24 | },
25 |
26 | updateUserDetails : (state, action) => {
27 | console.log(action)
28 | state.user = action.payload;
29 | localStorage.setItem('user', JSON.stringify(action.payload))
30 | }
31 | }
32 | })
33 |
34 | export const { deleteUserData,updateUserDetails } = userSlice.actions;
35 |
36 | export default userSlice.reducer;
--------------------------------------------------------------------------------
/src/index.css:
--------------------------------------------------------------------------------
1 | @tailwind base;
2 | @tailwind components;
3 | @tailwind utilities;
--------------------------------------------------------------------------------
/src/main.jsx:
--------------------------------------------------------------------------------
1 | import React from 'react'
2 | import ReactDOM from 'react-dom/client'
3 | import { Provider } from 'react-redux'
4 | import App from './App.jsx'
5 | import './index.css'
6 | import store from './store.js'
7 |
8 | ReactDOM.createRoot(document.getElementById('root')).render(
9 |
10 |
11 |
12 |
13 | ,
14 | )
15 |
--------------------------------------------------------------------------------
/src/pages/abuse/abuse.jsx:
--------------------------------------------------------------------------------
1 | import Footer from "../../components/Footer/footer";
2 | import AbuseBanner from "../../components/abuse/abuseBanner";
3 |
4 | import Navbar from "../../components/navbar/navbar";
5 |
6 | const Abuse = () => {
7 |
8 | return (
9 | <>
10 |
11 |
12 |
13 |
14 |
Future Faking
15 |
Future faking is a manipulative tactic where the abuser deceives the victim by making promises or plans for the future that they have no intention of keeping. This creates a false sense of hope and commitment, keeping the victim emotionally invested in the relationship. For women, this can lead to feelings of betrayal, disappointment, and loss of trust. It perpetuates a cycle of dependency and manipulation, making it difficult for women to break free from abusive relationships and pursue a fulfilling future.
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
36 |
Love Bombing
37 |
In movies, we often see a romanticized version of a persistent man pursuing a woman who initially shows no interest. He goes to great lengths, often ignoring her boundaries, until she eventually falls for him. This unrealistic portrayal mirrors a phenomenon known as love bombing. Love bombing involves showering someone with excessive attention and affection to manipulate them. It's like smothering someone with love to control them emotionally. While it's commonly seen at the start of a relationship, it can happen at any stage, leaving the victim feeling overwhelmed and unsure.
38 |
39 |
40 |
41 |
42 |
43 |
44 |
46 |
47 |
48 |
Silence
49 |
Silence can be deafening, especially in intimate relationships where the silent treatment becomes a weapon of emotional manipulation. Often used as a form of control or punishment, prolonged periods of silence from a partner can inflict deep psychological wounds on women. This passive-aggressive tactic undermines their sense of worth, triggers anxiety, and fosters feelings of isolation. Recognizing and addressing this toxic behavior is essential for women to reclaim their emotional well-being and assert boundaries in their relationships.
50 |
51 |
52 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
How to Identify Psychological Abuse
67 |
68 |
69 |
70 |
71 |
72 | Outlined below are several typical indicators of psychological abuse. Should you recognize any of these signs in your own experiences, we encourage you to seek support from a trusted friend, family member, or professional. Remember, you are not facing this alone
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 | Manipulative Behavior: Your partner constantly manipulates situations or emotions to control you.
83 | Gaslighting: They deny your reality, making you doubt your perceptions and sanity.
84 | Isolation Tactics: They isolate you from friends, family, or support networks, making you reliant solely on them.
85 | Constant Criticism: They belittle you, criticize your actions, and undermine your self-esteem.
86 | Threats and Intimidation: They use threats or intimidation to instill fear and maintain control.
87 | Blaming and Shifting Responsibility: They blame you for their actions and shift responsibility for their behavior onto you.
88 | Withholding Affection or Support: They withhold affection, emotional support, or financial resources as a means of control.
89 | Humiliation and Degradation: They humiliate or degrade you in private or public settings to assert dominance.
90 | Monitoring and Surveillance: They excessively monitor your activities, invade your privacy, or track your movements without consent.
91 | Financial Control: They control your finances, limiting your access to money or resources to maintain power over you.
92 |
93 |
94 |
95 |
96 |
97 |
98 |
99 | >
100 |
101 |
102 | );
103 | }
104 | export default Abuse
--------------------------------------------------------------------------------
/src/pages/complaint/complaint.jsx:
--------------------------------------------------------------------------------
1 | import { useState } from "react";
2 | import Footer from "../../components/Footer/footer";
3 | import Navbar from "../../components/navbar/navbar";
4 | import { BASE_URL } from "../../constents";
5 | import axios from "axios";
6 | import { toast } from "react-toastify";
7 | import { useSelector } from "react-redux";
8 |
9 | const Complaint = () => {
10 |
11 | const [text, setText] = useState('')
12 | const { user } = useSelector((state) => state.user);
13 | console.log(user.email)
14 |
15 | const handleSubmit = async () => {
16 | if(user){
17 | try {
18 | const data = {
19 | complaints: text,
20 | email:user.email
21 | };
22 |
23 | const response = await axios.post(BASE_URL+'/add-complaints', data);
24 |
25 | console.log(response.data.response);
26 | setText('')
27 | toast.success("you will get your response on your email")
28 | } catch (error) {
29 | console.error('Error:', error);
30 | toast.error("Error:!!! please try again after some time")
31 | }
32 | }else{
33 | toast.error('Please Login for Consult')
34 | }
35 |
36 | };
37 | return (
38 | <>
39 |
40 |
41 |
42 |
43 | File Your Concerns
44 |
45 |
46 |
47 |
48 | Welcome to our concern filing system, where you can openly share any
49 | challenges or issues you are currently experiencing. Once you submit
50 | your concerns, our team will carefully analyze them, and we commit to
51 | delivering a comprehensive response to your provided email address as
52 | swiftly as possible. Your satisfaction and resolution are our top
53 | priorities, and we appreciate your trust in our support system
54 |
55 |
56 |
57 |
58 |
59 |
60 | setText(e.target.value)}
62 | className="p-6 w-full h-[350px] font-mono outline-none mb-3 resize-none"
63 | value={text}
64 | name=""
65 | id=""
66 | cols="30"
67 | rows="10"
68 | >
69 |
70 |
71 |
76 | Send Concerns
77 |
78 |
79 |
80 |
81 |
82 |
83 | >
84 | );
85 | };
86 |
87 | export default Complaint;
88 |
--------------------------------------------------------------------------------
/src/pages/help/help.jsx:
--------------------------------------------------------------------------------
1 | import { useEffect, useState } from "react";
2 | import Footer from "../../components/Footer/footer";
3 | import VolunteerCard from "../../components/Volunteer/VolunteerCard";
4 | import Message from "../../components/message/message";
5 | import Navbar from "../../components/navbar/navbar";
6 | import axios from "axios";
7 | import { BASE_URL } from "../../constents";
8 |
9 | const Help = () => {
10 | const [openMessage, setOpenMessage] = useState(false)
11 | const [volunteer, setValunteer] = useState([])
12 | const [search, setSearchText] = useState('')
13 |
14 |
15 | useEffect(() => {
16 | axios.get(`${BASE_URL}serach-volunteer/?query=${search}`).then((response) => setValunteer(response.data)).catch((error) => setValunteer([]))
17 | }, [search])
18 |
19 | useEffect(() => {
20 | const fetchData = async () => {
21 | try {
22 | const response = await axios.get(BASE_URL + 'volunteers');
23 | setValunteer(response.data.volunteers);
24 | console.log(response.data.volunteers);
25 | } catch (error) {
26 | console.error('Error fetching stories:', error);
27 | }
28 | };
29 |
30 | fetchData();
31 | }, []);
32 |
33 | return (
34 | <>
35 |
36 |
37 |
38 |
41 |
42 |
43 |
44 |
45 | Welcome to our volunteer search platform. If you encounter any challenges in the future, rest assured that we are here to assist you. Our dedicated team is committed to helping you find the right volunteers for your needs. Please explore the options below to connect with volunteers who can support your cause effectively.
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
58 |
59 |
setSearchText(e.target.value)}
61 | value={search}
62 | className="peer h-full w-full outline-none text-sm text-gray-700 pr-2"
63 | type="text"
64 | id="search"
65 | placeholder="Enter current Location"
66 | />
67 |
68 |
69 |
70 |
71 |
72 | {volunteer.slice(0, 10).map((item, i) => (
73 |
74 | ))}
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 |
83 | If you have any questions, feel free to ask with the help of our AI assistant.
84 |
85 |
86 |
setOpenMessage(true)} className="mx-auto mt-5 bg-transparent hover:bg-gray-700 text-gray-700 font-semibold hover:text-white py-2 px-4 border border-gray-500 hover:border-transparent rounded">
87 | Click Here and See The Magic
88 |
89 |
90 |
91 |
92 |
93 |
94 | >
95 | );
96 | }
97 |
98 | export default Help;
99 |
--------------------------------------------------------------------------------
/src/pages/landing/landing.jsx:
--------------------------------------------------------------------------------
1 | import React, { useEffect, useState } from 'react';
2 | import Footer from "../../components/Footer/footer";
3 | import Card from "../../components/cards/landingcard";
4 | import StoryCard from "../../components/cards/storycard";
5 | import Banner from "../../components/landing/banner";
6 | import Message from "../../components/message/message";
7 | import Navbar from "../../components/navbar/navbar";
8 | import axios from 'axios';
9 | import { BASE_URL } from '../../constents';
10 |
11 | const Landing = () => {
12 | const [stories,setStories]=useState([])
13 | useEffect(() => {
14 | axios
15 | .get(BASE_URL + "stories")
16 | .then((response) => {
17 | console.log(response.data.story.slice(0,4))
18 | setStories(response.data.story.slice(0,4))
19 | })
20 | .catch((error) => toast.error(error));
21 | },[])
22 |
23 | return (
24 | <>
25 |
26 |
27 |
28 |
29 |
Together, We Shine: Unity Makes Us Stronger
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
BREAKING SILENCE, REVEALING PAIN: EXPOSING THE EPIDEMIC OF PSYCHOLOGICAL AGGRESSION IN INTIMATE PARTNERSHIPS ACROSS INDIA
44 |
45 |
46 |
47 |
Stories of Wonder Womens
48 |
49 |
50 |
51 | {stories.map((prop,ind)=>{
52 | return(
53 |
54 | )
55 | })}
56 |
57 |
58 |
59 |
60 |
61 |
We are women who are passionate about understanding and preventing psychological abuse. Together, we can make a real difference.
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 | >
72 | );
73 | }
74 |
75 | export default Landing;
--------------------------------------------------------------------------------
/src/pages/login/login.jsx:
--------------------------------------------------------------------------------
1 | import axios from "axios";
2 | import React, { useEffect, useState } from "react";
3 | import { Link, useNavigate } from "react-router-dom";
4 | import { toast } from "react-toastify";
5 | import { BASE_URL } from "../../constents";
6 | import { useDispatch, useSelector } from "react-redux";
7 | import { updateUserDetails } from "../../features/userSlice";
8 |
9 | const LoginForm = () => {
10 | const [email, setEmail] = useState("");
11 | const [password, setPassword] = useState("");
12 | const [EmailError, setEmailError] = useState("");
13 | const [PasswordError, setPasswordError] = useState("");
14 | const { user } = useSelector((state) => state.user);
15 | const dispatch = useDispatch();
16 | const navigator=useNavigate()
17 | console.log(user,'this')
18 |
19 | useEffect(()=>{
20 | if (user){
21 | navigator('/')
22 | }
23 | },[])
24 |
25 |
26 | const validateEmail = (value) => {
27 | const regex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
28 | setEmailError(regex.test(value) ? "" : "Invalid email");
29 | };
30 | function handleEmailChange(e) {
31 | const value = e.target.value;
32 | setEmail(value);
33 | validateEmail(value);
34 | }
35 |
36 | const validatePassword = (value) => {
37 | const regex = /^.{8,}$/;
38 | setPasswordError(
39 | regex.test(value) ? "" : "Password must be at least 8 characters"
40 | );
41 | };
42 | function handlePasswordChange(e) {
43 | const value = e.target.value;
44 | setPassword(value);
45 | validatePassword(value);
46 | }
47 |
48 | function submitForm(e) {
49 | e.preventDefault();
50 | if (!EmailError && !PasswordError) {
51 | const data = {
52 | username: email,
53 | password: password,
54 | };
55 |
56 | console.log(data);
57 | axios
58 | .post(BASE_URL + "login", data)
59 | .then((response) => {
60 | console.log("response",response);
61 | if (response.success == 400) {
62 | toast.error("Give Proper Credentials");
63 | } else {
64 | toast.success("User logined Successfully");
65 | console.log(response)
66 | localStorage.setItem('user', JSON.stringify(response.data.user));
67 | dispatch(updateUserDetails(response.data.user))
68 | setTimeout(() => {
69 | navigator("/");
70 | },2500);
71 | }
72 | console.log(response)
73 | })
74 | .catch((error) =>{ toast.error(error.response.data.message)});
75 | } else {
76 | toast.error(EmailError ? EmailError : PasswordError);
77 | }
78 | }
79 |
80 | return (
81 | <>
82 |
83 |
84 |
89 |
90 |
91 |
92 |
93 | Login
94 |
95 |
96 |
97 |
98 |
99 | Your Email
100 |
101 |
102 | handleEmailChange(e)}
103 | placeholder="name@mail.com"
104 | className="peer h-full w-full rounded-md border border-black border-opacity-20 focus:border-black focus:border-opacity-100 bg-transparent px-3 py-3 font-sans text-sm font-normal text-blue-gray-700 outline outline-0 transition-all placeholder-shown:border placeholder-shown:border-blue-gray-200 placeholder-shown:border-t-blue-gray-200 focus:outline-0 disabled:border-0 disabled:bg-blue-gray-50"
105 | />
106 |
107 |
108 | Password
109 |
110 |
111 | handlePasswordChange(e)}
112 | type="password"
113 | placeholder="********"
114 | className="peer h-full w-full rounded-md border border-black border-opacity-20 focus:border-black focus:border-opacity-100 bg-transparent px-3 py-3 font-sans text-sm font-normal text-blue-gray-700 outline outline-0 transition-all placeholder-shown:border placeholder-shown:border-blue-gray-200 placeholder-shown:border-t-blue-gray-200 focus:outline-0 disabled:border-0 disabled:bg-blue-gray-50"
115 | />
116 |
117 |
118 |
119 | submitForm(e)}
120 | className="mt-6 block w-full select-none rounded-lg bg-gray-900 py-3 px-6 text-center align-middle font-sans text-xs font-bold uppercase text-white shadow-md shadow-gray-900/10 transition-all hover:shadow-lg hover:shadow-gray-900/20 focus:opacity-[0.85] focus:shadow-none active:opacity-[0.85] active:shadow-none disabled:pointer-events-none disabled:opacity-50 disabled:shadow-none"
121 | type="button"
122 | >
123 | Sign in
124 |
125 |
126 | Don't have an account?
127 |
128 | Sign Up
129 |
130 |
131 |
132 |
133 |
134 |
135 | >
136 | );
137 | };
138 |
139 | export default LoginForm;
140 |
--------------------------------------------------------------------------------
/src/pages/otp/otp.jsx:
--------------------------------------------------------------------------------
1 | import axios from "axios";
2 | import React, { useEffect, useState } from "react";
3 | import { Link, useNavigate } from "react-router-dom";
4 | import { toast } from "react-toastify";
5 | import { BASE_URL } from "../../constents";
6 |
7 | const OtpForm = () => {
8 | const[otp,setOtp]=useState('')
9 | const [inp1,setInp1]=useState('')
10 | const [inp2,setInp2]=useState('')
11 | const [inp3,setInp3]=useState('')
12 | const [inp4,setInp4]=useState('')
13 | const [inp5,setInp5]=useState('')
14 | const [inp6,setInp6]=useState('')
15 | const navigate=useNavigate()
16 |
17 | useEffect(()=>{
18 | setOtp(inp1+inp2+inp3+inp4+inp5+inp6)
19 | console.log(otp)
20 | },[inp1,inp2,inp3,inp4,inp5,inp6,submission])
21 |
22 | function submission(){
23 | if (otp) {
24 | const data={
25 | otp:otp,
26 | }
27 | console.log('ijjjdfdf')
28 | axios.post(BASE_URL + "otpverify", data)
29 | .then((response) => {
30 | if (response.status == 404) {
31 | toast.error(response.message);
32 | console.log('false')
33 | } else {
34 | toast.success("Otp Verified Successfully");
35 | navigate("/login");
36 | }
37 | console.log(response)
38 | })
39 |
40 | .catch((error) => toast.error(error));
41 | } else {
42 | toast.error("Enter otp");
43 | }
44 | console.log('-------')
45 | }
46 |
47 | return (
48 | <>
49 |
50 |
51 |
56 |
57 |
58 |
59 |
60 | Enter OTP
61 |
62 |
63 |
64 |
108 |
109 | submission()}
110 | className="mt-6 block w-full select-none rounded-lg bg-gray-900 py-3 px-6 text-center align-middle font-sans text-xs font-bold uppercase text-white shadow-md shadow-gray-900/10 transition-all hover:shadow-lg hover:shadow-gray-900/20 focus:opacity-[0.85] focus:shadow-none active:opacity-[0.85] active:shadow-none disabled:pointer-events-none disabled:opacity-50 disabled:shadow-none"
111 | type="button"
112 | >
113 | Verify
114 |
115 |
116 | Didn't receive OTP? Resend OTP
117 |
118 |
119 |
120 |
121 |
122 | >
123 | );
124 | };
125 |
126 | export default OtpForm;
127 |
--------------------------------------------------------------------------------
/src/pages/register/register.jsx:
--------------------------------------------------------------------------------
1 | import axios from "axios";
2 | import React, { useCallback, useEffect, useState } from "react";
3 | import { Link, useNavigate } from "react-router-dom";
4 | import { toast } from "react-toastify";
5 | import { BASE_URL } from "../../constents";
6 | import { useDispatch, useSelector } from "react-redux";
7 |
8 | const Register = () => {
9 | const [name,setName]=useState('')
10 | const [email,setEmail]=useState('')
11 | const [password,setPassword]=useState('')
12 | const [ConfirmPassword, setConfirmPassword] = useState("");
13 | const [nameError, setNameError] = useState("");
14 | const [EmailError, setEmailError] = useState("");
15 | const [PasswordError, setPasswordError] = useState("");
16 | const [ConfirmPasswordError, setConfirmPasswordError] = useState("");
17 | const { user } = useSelector((state) => state.user);
18 | const dispatch = useDispatch();
19 | const navigate=useNavigate()
20 | useEffect(()=>{
21 | if (user){
22 | navigate('/')
23 | }
24 | },[])
25 | const validateName = useCallback(
26 | (value) => {
27 | const regex = /^[a-zA-Z0-9_]{3,20}$/;
28 | setNameError(regex.test(value) ? "" : "Invalid username");
29 | },
30 | [name]
31 | );
32 | const handleName = (e) => {
33 | const value = e.target.value;
34 | setName(value);
35 | validateName(value);
36 | };
37 |
38 | const validateEmail = (value) => {
39 | const regex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
40 | setEmailError(regex.test(value) ? "" : "Invalid email");
41 | };
42 | const handleEmail = (e) => {
43 | const value = e.target.value;
44 | setEmail(value);
45 | validateEmail(value);
46 | };
47 |
48 | const validatePassword = useCallback((value) => {
49 | const regex = /^.{8,}$/;
50 | setPasswordError(
51 | regex.test(value) ? "" : "Password must be at least 8 characters"
52 | );
53 | });
54 | const handlePassword = (e) => {
55 | const value = e.target.value;
56 | setPassword(value);
57 | validatePassword(value);
58 | };
59 |
60 | const validateConfirmPassword = (value) => {
61 | setConfirmPasswordError(value === password ? "" : "Passwords do not match");
62 | };
63 | const handleConfirmPassword = (e) => {
64 | const value = e.target.value;
65 | setConfirmPassword(value);
66 | validateConfirmPassword(value);
67 | };
68 |
69 |
70 |
71 | const handleRegistration = (e) => {
72 | e.preventDefault();
73 | const data = {
74 | username: name,
75 | email: email,
76 | password: password,
77 | };
78 | validateConfirmPassword(ConfirmPassword); // Validate confirm password before checking error
79 |
80 | if (!EmailError && !nameError && !PasswordError && !ConfirmPasswordError) {
81 | axios
82 | .post(BASE_URL + "register", data)
83 | .then((response) => {
84 | if (response.status === 400) {
85 | toast.error("Give Proper Credentials");
86 | } else {
87 | toast.success("User Registered Successfully");
88 | navigate("/otp");
89 | }
90 | })
91 | .catch((error) => toast.error(error));
92 | } else {
93 | toast.error("Give Proper Credentials");
94 | }
95 | };
96 |
97 | return (
98 | <>
99 |
100 |
101 |
106 |
107 |
108 |
109 |
110 | Register
111 |
112 |
113 |
114 |
115 |
116 | Full Name
117 |
118 |
119 |
handleName(e)}
120 | placeholder="Enter your name "
121 | className="peer h-full w-full rounded-md border border-black border-opacity-20 focus:border-black focus:border-opacity-100 bg-transparent px-3 py-3 font-sans text-sm font-normal text-blue-gray-700 outline outline-0 transition-all placeholder-shown:border placeholder-shown:border-blue-gray-200 placeholder-shown:border-t-blue-gray-200 focus:outline-0 disabled:border-0 disabled:bg-blue-gray-50"
122 | />
123 |
124 | {nameError ? nameError : ''}
125 |
126 |
127 |
128 | Your Email
129 |
130 |
131 |
handleEmail(e)}
132 | placeholder="Entere your mail address"
133 | className="peer h-full w-full rounded-md border border-black border-opacity-20 focus:border-black focus:border-opacity-100 bg-transparent px-3 py-3 font-sans text-sm font-normal text-blue-gray-700 outline outline-0 transition-all placeholder-shown:border placeholder-shown:border-blue-gray-200 placeholder-shown:border-t-blue-gray-200 focus:outline-0 disabled:border-0 disabled:bg-blue-gray-50"
134 | />
135 |
136 | {EmailError ? EmailError : ''}
137 |
138 |
139 |
140 | Password
141 |
142 |
143 |
handlePassword(e)}
144 | type="password"
145 | placeholder="********"
146 | className="peer h-full w-full rounded-md border border-black border-opacity-20 focus:border-black focus:border-opacity-100 bg-transparent px-3 py-3 font-sans text-sm font-normal text-blue-gray-700 outline outline-0 transition-all placeholder-shown:border placeholder-shown:border-blue-gray-200 placeholder-shown:border-t-blue-gray-200 focus:outline-0 disabled:border-0 disabled:bg-blue-gray-50"
147 | />
148 |
149 | {PasswordError ? PasswordError : ''}
150 |
151 |
152 |
153 | Confirm Password
154 |
155 |
156 |
handleConfirmPassword(e)}
157 | type="password"
158 | placeholder="********"
159 | className="peer h-full w-full rounded-md border border-black border-opacity-20 focus:border-black focus:border-opacity-100 bg-transparent px-3 py-3 font-sans text-sm font-normal text-blue-gray-700 outline outline-0 transition-all placeholder-shown:border placeholder-shown:border-blue-gray-200 placeholder-shown:border-t-blue-gray-200 focus:outline-0 disabled:border-0 disabled:bg-blue-gray-50"
160 | />
161 |
162 | {ConfirmPasswordError ? ConfirmPasswordError : ''}
163 |
164 |
165 |
166 |
167 | handleRegistration(e)}
168 | className="mt-6 block w-full select-none rounded-lg bg-gray-900 py-3 px-6 text-center align-middle font-sans text-xs font-bold uppercase text-white shadow-md shadow-gray-900/10 transition-all hover:shadow-lg hover:shadow-gray-900/20 focus:opacity-[0.85] focus:shadow-none active:opacity-[0.85] active:shadow-none disabled:pointer-events-none disabled:opacity-50 disabled:shadow-none"
169 | type="button"
170 | >
171 | Sign in
172 |
173 |
174 | Don't have an account?
175 |
176 | Sign Up
177 |
178 |
179 |
180 |
181 |
182 |
183 | >
184 | );
185 | };
186 |
187 | export default Register;
188 |
--------------------------------------------------------------------------------
/src/pages/story/Community.jsx:
--------------------------------------------------------------------------------
1 | import Footer from "../../components/Footer/footer";
2 | import StoryPageCard from "../../components/cards/CommunityPage";
3 | import Navbar from "../../components/navbar/navbar";
4 |
5 | const Story = () => {
6 |
7 | return (
8 | <>
9 |
10 |
11 |
12 |
13 |
Welcome to our supportive community!
14 |
15 |
16 |
17 | Together, we are a beacon of hope, strength, and growth. Whether you're here to seek support, offer assistance, or simply connect with others on a journey of learning and self-discovery, you've found your place among us. Within these virtual walls, we celebrate the power of storytelling as a catalyst for motivation and learning. Your experiences, triumphs, and challenges have the potential to inspire and empower others on their own journeys.
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 | Inspirational Stories from Remarkable Women
26 |
27 |
28 |
29 |
30 |
31 |
32 | >
33 | );
34 | }
35 |
36 |
37 | export default Story
--------------------------------------------------------------------------------
/src/pages/story/Stories.jsx:
--------------------------------------------------------------------------------
1 | import Footer from "../../components/Footer/footer";
2 | import StoryPage from "../../components/cards/StoryPage";
3 | import Navbar from "../../components/navbar/navbar";
4 |
5 | const StoriesPage = () => {
6 |
7 | return (
8 | <>
9 |
10 |
11 |
12 |
15 |
16 |
17 | Welcome to our Stories page – a testament to the resilience and shared strength within our community. Here, we unveil the raw authenticity of lived experiences, turning pain into power and transforming adversity into triumph. These stories are not just narratives; they are the heartbeats of survivors who have emerged from the shadows of hardship.
18 |
19 |
20 |
21 |
22 |
23 | >
24 | );
25 | }
26 |
27 |
28 | export default StoriesPage
--------------------------------------------------------------------------------
/src/store.js:
--------------------------------------------------------------------------------
1 |
2 | import { configureStore } from "@reduxjs/toolkit";
3 | import userSlice from "./features/userSlice";
4 |
5 | const store = configureStore({
6 | reducer: {
7 | user: userSlice
8 | }
9 | });
10 |
11 | export default store;
12 |
--------------------------------------------------------------------------------
/tailwind.config.js:
--------------------------------------------------------------------------------
1 | /** @type {import('tailwindcss').Config} */
2 | export default {
3 | content: [
4 | "./index.html",
5 | "./src/**/*.{js,ts,jsx,tsx}",
6 | ],
7 | theme: {
8 | extend: {},
9 | },
10 | plugins: [],
11 | }
--------------------------------------------------------------------------------
/vite.config.js:
--------------------------------------------------------------------------------
1 | import { defineConfig } from 'vite'
2 | import react from '@vitejs/plugin-react'
3 |
4 | export default defineConfig({
5 | plugins: [react()],
6 | server:{
7 | proxy:{
8 | '/api/users/':{
9 | target:'https://hackathon-backend-hm3i.onrender.com',
10 | changeOrigin:true,
11 | // rewrite: (path) => path.replace(/^\/api/, ''),
12 | }
13 | }
14 | }
15 | })
16 |
--------------------------------------------------------------------------------