feat:更换反馈服务提供商
This commit is contained in:
57
app/page.jsx
57
app/page.jsx
@@ -2,7 +2,6 @@
|
|||||||
|
|
||||||
import { useEffect, useRef, useState } from 'react';
|
import { useEffect, useRef, useState } from 'react';
|
||||||
import { motion, AnimatePresence, Reorder } from 'framer-motion';
|
import { motion, AnimatePresence, Reorder } from 'framer-motion';
|
||||||
import { useForm, ValidationError } from '@formspree/react';
|
|
||||||
import Announcement from "./components/Announcement";
|
import Announcement from "./components/Announcement";
|
||||||
|
|
||||||
function PlusIcon(props) {
|
function PlusIcon(props) {
|
||||||
@@ -130,16 +129,42 @@ function Stat({ label, value, delta }) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function FeedbackModal({ onClose }) {
|
function FeedbackModal({ onClose }) {
|
||||||
const [state, handleSubmit] = useForm("xdadgvjd");
|
const [submitting, setSubmitting] = useState(false);
|
||||||
|
const [succeeded, setSucceeded] = useState(false);
|
||||||
|
const [error, setError] = useState("");
|
||||||
|
|
||||||
const onSubmit = (e) => {
|
const onSubmit = async (e) => {
|
||||||
const form = e?.target;
|
e.preventDefault();
|
||||||
const nicknameInput = form?.elements?.namedItem?.('nickname');
|
setSubmitting(true);
|
||||||
if (nicknameInput && typeof nicknameInput.value === 'string') {
|
setError("");
|
||||||
const v = nicknameInput.value.trim();
|
|
||||||
if (!v) nicknameInput.value = '匿名';
|
const formData = new FormData(e.target);
|
||||||
|
const nickname = formData.get("nickname")?.trim();
|
||||||
|
if (!nickname) {
|
||||||
|
formData.set("nickname", "匿名");
|
||||||
|
}
|
||||||
|
|
||||||
|
// Web3Forms Access Key
|
||||||
|
formData.append("access_key", "c390fbb1-77e0-4aab-a939-caa75edc7319");
|
||||||
|
formData.append("subject", "基估宝 - 用户反馈");
|
||||||
|
|
||||||
|
try {
|
||||||
|
const response = await fetch("https://api.web3forms.com/submit", {
|
||||||
|
method: "POST",
|
||||||
|
body: formData
|
||||||
|
});
|
||||||
|
|
||||||
|
const data = await response.json();
|
||||||
|
if (data.success) {
|
||||||
|
setSucceeded(true);
|
||||||
|
} else {
|
||||||
|
setError(data.message || "提交失败,请稍后再试");
|
||||||
|
}
|
||||||
|
} catch (err) {
|
||||||
|
setError("网络错误,请检查您的连接");
|
||||||
|
} finally {
|
||||||
|
setSubmitting(false);
|
||||||
}
|
}
|
||||||
return handleSubmit(e);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
@@ -170,7 +195,7 @@ function FeedbackModal({ onClose }) {
|
|||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{state.succeeded ? (
|
{succeeded ? (
|
||||||
<div className="success-message" style={{ textAlign: 'center', padding: '20px 0' }}>
|
<div className="success-message" style={{ textAlign: 'center', padding: '20px 0' }}>
|
||||||
<div style={{ fontSize: '48px', marginBottom: 16 }}>🎉</div>
|
<div style={{ fontSize: '48px', marginBottom: 16 }}>🎉</div>
|
||||||
<h3 style={{ marginBottom: 8 }}>感谢您的反馈!</h3>
|
<h3 style={{ marginBottom: 8 }}>感谢您的反馈!</h3>
|
||||||
@@ -193,7 +218,6 @@ function FeedbackModal({ onClose }) {
|
|||||||
placeholder="匿名"
|
placeholder="匿名"
|
||||||
style={{ width: '100%' }}
|
style={{ width: '100%' }}
|
||||||
/>
|
/>
|
||||||
<ValidationError prefix="Nickname" field="nickname" errors={state.errors} className="error-text" />
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="form-group" style={{ marginBottom: 20 }}>
|
<div className="form-group" style={{ marginBottom: 20 }}>
|
||||||
@@ -208,11 +232,16 @@ function FeedbackModal({ onClose }) {
|
|||||||
placeholder="请描述您遇到的问题或建议..."
|
placeholder="请描述您遇到的问题或建议..."
|
||||||
style={{ width: '100%', minHeight: '120px', padding: '12px', resize: 'vertical' }}
|
style={{ width: '100%', minHeight: '120px', padding: '12px', resize: 'vertical' }}
|
||||||
/>
|
/>
|
||||||
<ValidationError prefix="Message" field="message" errors={state.errors} className="error-text" />
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<button className="button" type="submit" disabled={state.submitting} style={{ width: '100%' }}>
|
{error && (
|
||||||
{state.submitting ? '发送中...' : '提交反馈'}
|
<div className="error-text" style={{ marginBottom: 16, textAlign: 'center' }}>
|
||||||
|
{error}
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
|
||||||
|
<button className="button" type="submit" disabled={submitting} style={{ width: '100%' }}>
|
||||||
|
{submitting ? '发送中...' : '提交反馈'}
|
||||||
</button>
|
</button>
|
||||||
</form>
|
</form>
|
||||||
)}
|
)}
|
||||||
|
|||||||
74
package-lock.json
generated
74
package-lock.json
generated
@@ -8,37 +8,12 @@
|
|||||||
"name": "real-time-fund",
|
"name": "real-time-fund",
|
||||||
"version": "0.1.0",
|
"version": "0.1.0",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@formspree/react": "^3.0.0",
|
|
||||||
"framer-motion": "^12.29.2",
|
"framer-motion": "^12.29.2",
|
||||||
"next": "14.2.5",
|
"next": "14.2.5",
|
||||||
"react": "18.3.1",
|
"react": "18.3.1",
|
||||||
"react-dom": "18.3.1"
|
"react-dom": "18.3.1"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@formspree/core": {
|
|
||||||
"version": "4.0.0",
|
|
||||||
"resolved": "https://registry.npmjs.org/@formspree/core/-/core-4.0.0.tgz",
|
|
||||||
"integrity": "sha512-geNlUut5nME1Ztej5Pzx1BrlQ1fFIcJYIqmF+Vm0jaUbpZxjXvt7SDOGeQVkuxn80QJiIHlwBGGjSBFjPX/KDw==",
|
|
||||||
"license": "MIT",
|
|
||||||
"dependencies": {
|
|
||||||
"@stripe/stripe-js": "^5.7.0"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/@formspree/react": {
|
|
||||||
"version": "3.0.0",
|
|
||||||
"resolved": "https://registry.npmjs.org/@formspree/react/-/react-3.0.0.tgz",
|
|
||||||
"integrity": "sha512-8PufBZ4l13VmCp9xTGQXwyF6mZtYSecqgTlFuMo5Fbe4Q6zUk7PMU2uKOwIaytZyTyJgFVCvdbpQElPPBKYNLw==",
|
|
||||||
"license": "MIT",
|
|
||||||
"dependencies": {
|
|
||||||
"@formspree/core": "^4.0.0",
|
|
||||||
"@stripe/react-stripe-js": "^3.1.1",
|
|
||||||
"@stripe/stripe-js": "^5.7.0"
|
|
||||||
},
|
|
||||||
"peerDependencies": {
|
|
||||||
"react": "^16.8 || ^17.0 || ^18.0 || ^19.0",
|
|
||||||
"react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/@next/env": {
|
"node_modules/@next/env": {
|
||||||
"version": "14.2.5",
|
"version": "14.2.5",
|
||||||
"resolved": "https://registry.npmjs.org/@next/env/-/env-14.2.5.tgz",
|
"resolved": "https://registry.npmjs.org/@next/env/-/env-14.2.5.tgz",
|
||||||
@@ -189,29 +164,6 @@
|
|||||||
"node": ">= 10"
|
"node": ">= 10"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@stripe/react-stripe-js": {
|
|
||||||
"version": "3.10.0",
|
|
||||||
"resolved": "https://registry.npmjs.org/@stripe/react-stripe-js/-/react-stripe-js-3.10.0.tgz",
|
|
||||||
"integrity": "sha512-UPqHZwMwDzGSax0ZI7XlxR3tZSpgIiZdk3CiwjbTK978phwR/fFXeAXQcN/h8wTAjR4ZIAzdlI9DbOqJhuJdeg==",
|
|
||||||
"license": "MIT",
|
|
||||||
"dependencies": {
|
|
||||||
"prop-types": "^15.7.2"
|
|
||||||
},
|
|
||||||
"peerDependencies": {
|
|
||||||
"@stripe/stripe-js": ">=1.44.1 <8.0.0",
|
|
||||||
"react": ">=16.8.0 <20.0.0",
|
|
||||||
"react-dom": ">=16.8.0 <20.0.0"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/@stripe/stripe-js": {
|
|
||||||
"version": "5.10.0",
|
|
||||||
"resolved": "https://registry.npmjs.org/@stripe/stripe-js/-/stripe-js-5.10.0.tgz",
|
|
||||||
"integrity": "sha512-PTigkxMdMUP6B5ISS7jMqJAKhgrhZwjprDqR1eATtFfh0OpKVNp110xiH+goeVdrJ29/4LeZJR4FaHHWstsu0A==",
|
|
||||||
"license": "MIT",
|
|
||||||
"engines": {
|
|
||||||
"node": ">=12.16"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/@swc/counter": {
|
"node_modules/@swc/counter": {
|
||||||
"version": "0.1.3",
|
"version": "0.1.3",
|
||||||
"resolved": "https://registry.npmjs.org/@swc/counter/-/counter-0.1.3.tgz",
|
"resolved": "https://registry.npmjs.org/@swc/counter/-/counter-0.1.3.tgz",
|
||||||
@@ -400,15 +352,6 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/object-assign": {
|
|
||||||
"version": "4.1.1",
|
|
||||||
"resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz",
|
|
||||||
"integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==",
|
|
||||||
"license": "MIT",
|
|
||||||
"engines": {
|
|
||||||
"node": ">=0.10.0"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/picocolors": {
|
"node_modules/picocolors": {
|
||||||
"version": "1.1.1",
|
"version": "1.1.1",
|
||||||
"resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz",
|
"resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz",
|
||||||
@@ -443,17 +386,6 @@
|
|||||||
"node": "^10 || ^12 || >=14"
|
"node": "^10 || ^12 || >=14"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/prop-types": {
|
|
||||||
"version": "15.8.1",
|
|
||||||
"resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.8.1.tgz",
|
|
||||||
"integrity": "sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg==",
|
|
||||||
"license": "MIT",
|
|
||||||
"dependencies": {
|
|
||||||
"loose-envify": "^1.4.0",
|
|
||||||
"object-assign": "^4.1.1",
|
|
||||||
"react-is": "^16.13.1"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/react": {
|
"node_modules/react": {
|
||||||
"version": "18.3.1",
|
"version": "18.3.1",
|
||||||
"resolved": "https://registry.npmjs.org/react/-/react-18.3.1.tgz",
|
"resolved": "https://registry.npmjs.org/react/-/react-18.3.1.tgz",
|
||||||
@@ -479,12 +411,6 @@
|
|||||||
"react": "^18.3.1"
|
"react": "^18.3.1"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/react-is": {
|
|
||||||
"version": "16.13.1",
|
|
||||||
"resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz",
|
|
||||||
"integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==",
|
|
||||||
"license": "MIT"
|
|
||||||
},
|
|
||||||
"node_modules/scheduler": {
|
"node_modules/scheduler": {
|
||||||
"version": "0.23.2",
|
"version": "0.23.2",
|
||||||
"resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.23.2.tgz",
|
"resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.23.2.tgz",
|
||||||
|
|||||||
@@ -8,7 +8,6 @@
|
|||||||
"start": "next start"
|
"start": "next start"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@formspree/react": "^3.0.0",
|
|
||||||
"framer-motion": "^12.29.2",
|
"framer-motion": "^12.29.2",
|
||||||
"next": "14.2.5",
|
"next": "14.2.5",
|
||||||
"react": "18.3.1",
|
"react": "18.3.1",
|
||||||
|
|||||||
Reference in New Issue
Block a user