Skip to content

Commit 3c15476

Browse files
authored
Merge pull request #11 from RizkyRajitha/dev
Dev
2 parents 11fdae7 + db0135f commit 3c15476

File tree

17 files changed

+412
-101
lines changed

17 files changed

+412
-101
lines changed

Procfile

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
web: npm run herokustart

README.md

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,10 @@
2424

2525
[![Deploy with Vercel](https://vercel.com/button)](https://vercel.com/new/git/external?repository-url=https%3A%2F%2Fgithub.com%2FRizkyRajitha%2Flinkin&env=DBURL&envDescription=PostgreSQL%20database%20URL&demo-title=Linkin%20&demo-description=Linkin%20is%20a%20customizable%20self%20hosted%20link%20in%20the%20bio%20platform%20.%20And%20it's%20ready%20for%20you)
2626

27+
## Deploy with Heroku
28+
29+
[![Deploy](https://www.herokucdn.com/deploy/button.svg)](https://heroku.com/deploy?template=https://github.com/RizkyRajitha/linkin&env[DBURL]=postgresdburl&env[KEY]=123)
30+
2731
![Screenshot_2021-05-22 LinkIn's Link In The Bio Page](https://user-images.githubusercontent.com/38534289/119221911-4ca94f80-bb0f-11eb-94ff-31f1c3a51d06.png)
2832

2933
![Screenshot_2021-05-22 Linkin Dashboard](https://user-images.githubusercontent.com/38534289/119221942-7d898480-bb0f-11eb-9175-5e139fa57f0a.png)
@@ -35,7 +39,7 @@
3539
- host in vercel
3640
- set vercel environment variables
3741
- `DBURL` - **Postgres** database url
38-
- `SECRETKEY` - random secret key
42+
- `KEY` - random secret key
3943
- after successfully deploying visit `youdomain/admin` to view admin login
4044
- use default login credentials
4145
- username = `admin`

app.json

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
{
2+
"name": "Linkin",
3+
"repository": "https://github.com/RizkyRajitha/linkin",
4+
"description": "Linkin is a customizable self hosted link in the bio platform",
5+
"logo": "https://res.cloudinary.com/dijjqfsto/image/upload/v1621666671/linkin_logo_1_jcuvr3.png",
6+
"keywords": [
7+
"next",
8+
"serverless",
9+
"linkinthebio",
10+
"javascript",
11+
"js",
12+
"react",
13+
"node",
14+
"postgres"
15+
]
16+
}

components/alert.js

Lines changed: 5 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,13 @@
1-
import { useEffect, useState } from "react";
1+
// import { useEffect, useState } from "react";
22

33
export default function Alert({ msg, type = "danger" }) {
4-
const [msgstate, setmsg] = useState(msg);
4+
// const [msgstate, setmsg] = useState(msg);
55

6-
useEffect(() => {
7-
// return;
8-
}, [msg]);
9-
console.log("alert ", msg, type);
6+
// console.log("alert ", msg, type);
107
return (
118
<div className="mt-4">
12-
<div hidden={!msgstate} className={`text-center alert alert-${type}`}>
13-
{msgstate}
9+
<div hidden={!msg} className={`text-center alert alert-${type}`}>
10+
{msg}
1411
</div>
1512
</div>
1613
);

components/formwrapper.js

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import ColorForm from "./colorform";
77
import LinksForm from "./linksform";
88
import GenaralForm from "./genaralform";
99
import FontForm from "./fontform";
10+
import PasswordChangeForm from "./passwordchangeform";
1011

1112
import { ToastContainer, toast } from "react-toastify";
1213

@@ -107,8 +108,18 @@ function Formwrapper({ pageData, updatedPageData }) {
107108
return (
108109
<>
109110
<div className={styles.dashform}>
110-
<div className="d-flex justify-content-end mb-2">
111+
<div className="d-flex justify-content-end mb-4">
111112
{" "}
113+
<button
114+
className={`btn btn-outline-primary logout-btn ${
115+
styles.logoutbtn
116+
} ${activeForm === "passwordchangeform" ? "active" : ""} `}
117+
onClick={() => {
118+
setactiveForm("passwordchangeform");
119+
}}
120+
>
121+
Change Password
122+
</button>
112123
<a
113124
className={`btn btn-outline-primary logout-btn ${styles.logoutbtn}`}
114125
href={`${PUBLICURL}`}
@@ -207,6 +218,7 @@ function Formwrapper({ pageData, updatedPageData }) {
207218
<FontForm data={pageData} update={savePageData} loading={loading} />
208219
)}
209220
{activeForm === "linksForm" && <LinksForm pagedataid={pageData.id} />}
221+
{activeForm === "passwordchangeform" && <PasswordChangeForm />}
210222
</div>
211223
<ToastContainer
212224
position="bottom-left"

components/passwordchangeform.js

Lines changed: 208 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,208 @@
1+
import { useRouter } from "next/router";
2+
import { useRef, useState } from "react";
3+
import { useForm } from "react-hook-form";
4+
import { toast, ToastContainer } from "react-toastify";
5+
6+
import styles from "../styles/form.module.css";
7+
8+
const endpoint =
9+
process.env.NODE_ENV === "production" ? `` : "http://localhost:3000";
10+
11+
const PasswordChangeForm = () => {
12+
const {
13+
register,
14+
handleSubmit,
15+
watch,
16+
formState: { errors },
17+
} = useForm();
18+
const router = useRouter();
19+
20+
const [loading, setloading] = useState(false);
21+
22+
const password = useRef({});
23+
password.current = watch("newPassword", "");
24+
25+
const updatePassword = async (data) => {
26+
console.log(data);
27+
setloading(true);
28+
29+
// let payload = {};
30+
// currentpassword: "123"
31+
// ​
32+
// newpassword: "D6taSRDazH9giCG"
33+
// return;
34+
35+
try {
36+
let res = await fetch(`${endpoint}/api/changepassword`, {
37+
method: "POST",
38+
body: JSON.stringify(data),
39+
headers: { "Content-Type": "application/json" },
40+
}).then((res) => res.json());
41+
42+
if (!res.success) {
43+
toast.error(`Error : ${res.msg}`, {
44+
position: "bottom-left",
45+
autoClose: 5000,
46+
hideProgressBar: false,
47+
closeOnClick: true,
48+
pauseOnHover: true,
49+
draggable: true,
50+
progress: undefined,
51+
});
52+
setloading(false);
53+
return;
54+
}
55+
56+
toast.success(`successfully updated password`, {
57+
position: "bottom-left",
58+
autoClose: 5000,
59+
hideProgressBar: false,
60+
closeOnClick: true,
61+
pauseOnHover: true,
62+
draggable: true,
63+
progress: undefined,
64+
});
65+
await logout();
66+
} catch (error) {
67+
console.log(error);
68+
toast.error(`Error : ${error.message}`, {
69+
position: "bottom-left",
70+
autoClose: 5000,
71+
hideProgressBar: false,
72+
closeOnClick: true,
73+
pauseOnHover: true,
74+
draggable: true,
75+
progress: undefined,
76+
});
77+
}
78+
setloading(false);
79+
};
80+
81+
const logout = async () => {
82+
try {
83+
let res = await fetch(`${endpoint}/api/logout`).then((res) => res.json());
84+
console.log(res);
85+
86+
if (res.success) {
87+
router.push("/admin");
88+
}
89+
} catch (error) {
90+
toast.error(`Logout Error : ${error.message}`, {
91+
position: "bottom-left",
92+
autoClose: 5000,
93+
hideProgressBar: false,
94+
closeOnClick: true,
95+
pauseOnHover: true,
96+
draggable: true,
97+
progress: undefined,
98+
});
99+
}
100+
};
101+
102+
return (
103+
<>
104+
<div className={styles.Wrapper}>
105+
<div
106+
className={`${styles.Inner} col-10 col-sm-10 col-md-10 col-lg-10 col-xl-8 col-xxl-8 `}
107+
>
108+
<form onSubmit={(e) => e.preventDefault()}>
109+
<h3>Updated Password</h3>
110+
<div className="mb-3 ">
111+
<label className="form-label">Current Password</label>
112+
<input
113+
type="password"
114+
className={
115+
errors.currentPassword
116+
? "form-control is-invalid"
117+
: "form-control"
118+
}
119+
placeholder="Enter Current Password"
120+
{...register("currentPassword")}
121+
/>
122+
{errors.currentPassword && (
123+
<div className="invalid-feedback">
124+
{errors.currentPassword.message}
125+
</div>
126+
)}
127+
</div>
128+
<div className="mb-3 ">
129+
<label className="form-label">New Password</label>
130+
<input
131+
type="password"
132+
className={
133+
errors.newPassword
134+
? "form-control is-invalid"
135+
: "form-control"
136+
}
137+
placeholder="Enter New Password"
138+
{...register("newPassword", {
139+
required: "You must specify a password",
140+
minLength: {
141+
value: 6,
142+
message: "Password must have at least 6 characters",
143+
},
144+
})}
145+
/>
146+
{errors.newPassword && (
147+
<div className="invalid-feedback">
148+
{errors.newPassword.message}
149+
</div>
150+
)}
151+
</div>
152+
<div className="mb-3 ">
153+
<label className="form-label">Confirm Password</label>
154+
<input
155+
type="password"
156+
className={
157+
errors.confirm_password
158+
? "form-control is-invalid"
159+
: "form-control"
160+
}
161+
placeholder="Enter New Password"
162+
{...register("confirm_password", {
163+
validate: (value) => {
164+
return (
165+
value === password.current || "The passwords do not match"
166+
);
167+
},
168+
})}
169+
/>{" "}
170+
{errors.confirm_password && (
171+
<div className="invalid-feedback">
172+
{errors.confirm_password.message}
173+
</div>
174+
)}
175+
</div>
176+
<button
177+
type="submit"
178+
className="btn btn-primary btn-block"
179+
onClick={handleSubmit(updatePassword)}
180+
disabled={loading}
181+
>
182+
{loading && (
183+
<span
184+
className="spinner-border spinner-border-sm me-1"
185+
role="status"
186+
aria-hidden="true"
187+
></span>
188+
)}
189+
Change Password
190+
</button>
191+
</form>
192+
<ToastContainer
193+
position="bottom-left"
194+
autoClose={5000}
195+
hideProgressBar={true}
196+
newestOnTop={false}
197+
closeOnClick
198+
rtl={false}
199+
pauseOnFocusLoss
200+
draggable
201+
pauseOnHover
202+
/>
203+
</div>
204+
</div>
205+
</>
206+
);
207+
};
208+
export default PasswordChangeForm;

db/con.js

Lines changed: 0 additions & 77 deletions
This file was deleted.

0 commit comments

Comments
 (0)