Skip to content

Commit f4acca2

Browse files
committed
use new rules-widget component to show the last modifeid rules
1 parent ee60702 commit f4acca2

File tree

2 files changed

+109
-1
lines changed

2 files changed

+109
-1
lines changed
Lines changed: 108 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,108 @@
1+
import React, { useEffect, useState } from "react";
2+
import { FaClock } from "react-icons/fa";
3+
import { formatDistanceStrict } from "date-fns";
4+
5+
function getLastUpdatedTime(isoDate) {
6+
return formatDistanceStrict(new Date(isoDate), new Date())
7+
.replace("minute", "min")
8+
.replace("second", "sec");
9+
}
10+
11+
export default function RulesWidget({
12+
numberOfRules = 5,
13+
author,
14+
rulesUrl = "https://www.ssw.com.au/rules",
15+
seeMoreUrl,
16+
title = "Latest Rules",
17+
}) {
18+
const [items, setItems] = useState([]);
19+
const [status, setStatus] = useState("idle"); // idle | loading | error | success
20+
21+
useEffect(() => {
22+
if (!author) return;
23+
24+
let cancelled = false;
25+
26+
(async () => {
27+
try {
28+
setStatus("loading");
29+
const res = await fetch(
30+
`${rulesUrl}/api/rules/last-modified?username=${encodeURIComponent(author)}&limit=${numberOfRules}`,
31+
{ cache: "no-store" }
32+
);
33+
if (!res.ok) throw new Error("Failed to fetch last modified rules");
34+
const data = await res.json();
35+
if (!cancelled) {
36+
setItems(Array.isArray(data?.items) ? data.items : []);
37+
setStatus("success");
38+
}
39+
} catch (e) {
40+
if (!cancelled) {
41+
setItems([]);
42+
setStatus("error");
43+
}
44+
}
45+
})();
46+
47+
return () => {
48+
cancelled = true;
49+
};
50+
}, [author, numberOfRules]);
51+
52+
const enabled = !!author;
53+
const moreHref = seeMoreUrl || `${rulesUrl}/user-rules?author=${encodeURIComponent(author || "")}`;
54+
55+
const content = (() => {
56+
if (!enabled) return <p className="text-center text-sm text-gray-600">No Rules Found</p>;
57+
if (status === "loading") return <p className="text-center text-sm text-gray-600">Loading...</p>;
58+
if (status === "error") return <p className="text-center text-sm text-gray-600">No Rules Found</p>;
59+
if (!items.length) return <p className="text-center text-sm text-gray-600">No Rules Found</p>;
60+
61+
return (
62+
<>
63+
{items.map((item, idx) => (
64+
<a
65+
key={`${item.uri}-${idx}`}
66+
href={`${rulesUrl}/${item.uri}`}
67+
target="_blank"
68+
rel="noreferrer"
69+
className="block no-underline text-gray-800 hover:text-[#cc4141]"
70+
>
71+
<div className="my-2.5 p-3 bg-[#f5f5f5] border-l-2 border-l-[#cc4141] text-left transition-shadow hover:shadow-md">
72+
<p className="text-base text-gray-800 leading-[1.2] break-words mb-1">
73+
{item.title}
74+
</p>
75+
76+
<p className="text-[#aaa] flex items-center gap-1 text-sm">
77+
<span className="inline-flex items-start">
78+
<FaClock size={14} />
79+
</span>
80+
{item.lastModifiedAt ? `${getLastUpdatedTime(item.lastModifiedAt)} ago` : "—"}
81+
</p>
82+
</div>
83+
</a>
84+
))}
85+
86+
<div className="text-center leading-[0.8] p-3">
87+
<a className="text-base text-[#cc4141] underline" target="_blank" rel="noreferrer" href={moreHref}>
88+
See more
89+
</a>
90+
</div>
91+
</>
92+
);
93+
})();
94+
95+
return (
96+
<div className="text-base">
97+
<div className="flex flex-col items-center">
98+
<h4 className="m-0">
99+
<a className="no-underline text-gray-800 hover:text-[#cc4141]" target="_blank" rel="noreferrer" href={rulesUrl}>
100+
{title}
101+
</a>
102+
</h4>
103+
</div>
104+
105+
<div className="border-none text-gray-800 rounded">{content}</div>
106+
</div>
107+
);
108+
}

src/templates/person.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ import PropTypes from 'prop-types';
1111
import Quote from '../components/quote/quote';
1212
import SkillsList from '../components/skills-list/skills-list';
1313
import SocialLinks from '../components/social-links/social-links';
14-
import { RulesWidget } from 'ssw.rules.widget';
14+
import RulesWidget from '../components/rules-widget/rules-widget';
1515
import YoutubePlaylist from '../components/youtube-playlist/youtube-playlist';
1616
import { config } from '@fortawesome/fontawesome-svg-core';
1717
import { isChinaBuild } from '../helpers/chinaHelper';

0 commit comments

Comments
 (0)