Skip to content

Commit c34de99

Browse files
authored
Merge pull request #10 from Solstice-Hosting/alexx-partners-260424-2133
Partners system finished. /partners.js moved to /partners/index.js
2 parents 317a6bc + 5dad374 commit c34de99

File tree

3 files changed

+270
-28
lines changed

3 files changed

+270
-28
lines changed

pages/partners.js

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

pages/partners/dashboard.js

Lines changed: 178 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,178 @@
1+
import Header from "@/components/main/Header";
2+
import { useState, useEffect, Suspense } from "react";
3+
import { useRouter } from "next/router";
4+
import PocketBase from "pocketbase";
5+
import { Button } from "@/components/ui/button";
6+
import { Input } from "@/components/ui/input";
7+
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
8+
import { faCheck, faPlus } from "@fortawesome/free-solid-svg-icons";
9+
import Image from "next/image";
10+
11+
export default function PartnerDashboard() {
12+
const pb = new PocketBase('https://pb.solsticehosting.co.uk');
13+
const router = useRouter();
14+
const [authenticated, setAuthenticated] = useState(false);
15+
const [adminAccount, setAdminAccount] = useState(false);
16+
const [partnerInfo, setPartnerInfo] = useState([]);
17+
18+
useEffect(() => {
19+
if (pb.authStore.isValid) {
20+
21+
if (pb.authStore.isAdmin) {
22+
setAdminAccount(true);
23+
}
24+
setAuthenticated(true);
25+
}
26+
else {
27+
router.push('/login');
28+
}
29+
}, [authenticated, pb, router]);
30+
31+
useEffect(() => {
32+
if (authenticated === true) {
33+
if (!adminAccount) {
34+
const getPartnerInfo = async () => {
35+
const authData = await pb.collection('users').authRefresh();
36+
console.log(authData.record.id);
37+
const gettingPartnerInfo = await pb.collection('partners').getFullList({
38+
filter: `account ~ "${pb.authStore.model.id}"`
39+
});
40+
if (gettingPartnerInfo.length > 0) {
41+
setPartnerInfo(gettingPartnerInfo);
42+
}
43+
else {
44+
router.push('/partners');
45+
}
46+
};
47+
getPartnerInfo();
48+
}
49+
50+
}
51+
}, [authenticated]);
52+
53+
54+
return (
55+
<>
56+
<Header />
57+
<main className="min-h-screen w-screen bg-gray-950 flex gap-8 flex-col p-24">
58+
<Suspense fallback="Loading...">
59+
{partnerInfo.length > 0 && (
60+
<>
61+
<div className="w-10/12 flex flex-col gap-6">
62+
<h1 className="text-white font-extrabold text-4xl">Edit your Partnership Information</h1>
63+
</div>
64+
<div className="flex flex-col gap-8 text-white">
65+
{partnerInfo.map((partner) => (
66+
<PartnerComp key={partner.id} partner={partner} />
67+
))}
68+
</div >
69+
</>)}
70+
</Suspense>
71+
</main>
72+
</>
73+
)
74+
}
75+
76+
77+
function PartnerComp({ key, partner }) {
78+
const pb = new PocketBase("https://pb.solsticehosting.co.uk");
79+
const [partnerName, setPartnerName] = useState('');
80+
const [memoInfo, setMemoInfo] = useState('');
81+
const [site, setSite] = useState('');
82+
const [discord, setDiscord] = useState('');
83+
const [status, setStatus] = useState(null);
84+
85+
useEffect(() => {
86+
console.log(partner);
87+
setPartnerName(partner.title);
88+
setMemoInfo(partner.memo);
89+
setSite(partner.site);
90+
setDiscord(partner.discord);
91+
}, [partner]);
92+
93+
const saveChanges = async () => {
94+
const tryToUpdate = await pb.collection('partners').update(partner.id, {
95+
"title": partnerName,
96+
"memo": memoInfo,
97+
"site": site,
98+
"discord": discord,
99+
"logo": partner.logo,
100+
});
101+
102+
if (!tryToUpdate.code) {
103+
setStatus('success');
104+
setTimeout(() => {setStatus('')}, 1500);
105+
}
106+
else {
107+
setStatus(tryToUpdate.message);
108+
}
109+
};
110+
111+
return (
112+
<>
113+
<div className="w-full bg-gray-800 min-h-content rounded-lg border-2 border-gray-700 p-4 flex flex-col gap-8">
114+
<div className="flex w-full justify-between items-center">
115+
<input
116+
className="bg-gray-700 rounded-lg text-white outline-none p-4 text-2xl font-extrabold w-1/2 border-2 border-gray-600"
117+
value={partnerName}
118+
onChange={(e) => setPartnerName(e.target.value)}
119+
/>
120+
<span className="text-gray-400 font-semibold">
121+
<span className="font-normal">Partner Id:</span> {partner.id}
122+
</span>
123+
</div>
124+
<div className="flex flex-col gap-2">
125+
<span className="font-bold">Memo</span>
126+
<textarea
127+
value={memoInfo}
128+
onChange={(e) => { setMemoInfo(e.target.value) }}
129+
className="bg-gray-700 rounded-lg text-white outline-none p-4 min-h-[16rem] border-2 border-gray-600"
130+
>
131+
132+
</textarea>
133+
</div>
134+
<div className="flex gap-4">
135+
<div className="flex flex-col gap-2 w-full">
136+
<span className="font-bold flex gap-4 items-center">Website <span className="font-normal text-gray-400">(optional)</span></span>
137+
<input
138+
className="bg-gray-700 rounded-lg p-4 text-white w-full outline-none border-2 border-gray-600"
139+
value={site}
140+
onChange={(e) => setSite(e.target.value)}
141+
/>
142+
</div>
143+
<div className="flex flex-col gap-2 w-full">
144+
<span className="font-bold flex gap-4 items-center">Discord Invite <span className="font-normal text-gray-400">(optional)</span></span>
145+
<input
146+
className="bg-gray-700 rounded-lg p-4 text-white w-full outline-none border-2 border-gray-600"
147+
value={discord}
148+
onChange={(e) => setDiscord(e.target.value)}
149+
/>
150+
</div>
151+
</div>
152+
<div className="w-full justify-between">
153+
<div></div>
154+
<Button onClick={saveChanges} className={`${!status ? 'bg-gray-900' : (status === 'success' ? 'bg-green-600' : 'bg-red-400')} transition-all duration-200`}>
155+
{!status ?
156+
'Save Changes'
157+
: ( status === 'success' ?
158+
'Success!'
159+
: `${success}`
160+
)}
161+
</Button>
162+
</div>
163+
</div>
164+
</>
165+
);
166+
}
167+
168+
169+
async function fetchImageBlob(url) {
170+
try {
171+
const response = await fetch(url);
172+
const blob = await response.blob();
173+
return blob;
174+
} catch (error) {
175+
console.error('Error fetching image blob:', error);
176+
throw error;
177+
}
178+
}

pages/partners/index.js

Lines changed: 92 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,92 @@
1+
import Footer from "@/components/main/Footer";
2+
import Header from "@/components/main/Header";
3+
import { Button } from "@/components/ui/button";
4+
import { faDiscord } from "@fortawesome/free-brands-svg-icons";
5+
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
6+
import Head from "next/head";
7+
import Image from "next/image";
8+
import Link from "next/link";
9+
import PocketBase from "pocketbase";
10+
import { Suspense, useEffect, useState } from "react";
11+
12+
export default function PartnerPage() {
13+
const [partners, setPartners] = useState([]);
14+
const [userId, setUserId] = useState('');
15+
16+
useEffect(() => {
17+
const pb = new PocketBase("https://pb.solsticehosting.co.uk");
18+
const getPartners = async () => {
19+
const authData = await pb.collection('users').authRefresh();
20+
setUserId(authData?.record?.id);
21+
const partners = await pb.collection('partners').getFullList({
22+
filter: 'display = 1'
23+
});
24+
console.log(partners);
25+
setPartners(partners);
26+
}
27+
getPartners()
28+
}, []);
29+
30+
return (
31+
<>
32+
<Head>
33+
<title>Partners - SolsticeHosting</title>
34+
<meta name="description" content="Our wonderful partners; quite literally the friends we've made along the way." />
35+
<meta name="keywords" content="partners, minecraft hosting, hosting, hosting partners, solstice hosting, solstice partner, partner with solstice" />
36+
</Head>
37+
<Header />
38+
<main className="min-h-[80vh] w-full bg-gray-950">
39+
<div className="flex flex-col gap-2 items-center p-4 lg:p-10 text-center">
40+
<h1 className="font-extrabold text-5xl text-gray-100 whitespace-nowrap">
41+
<span className="hidden lg:block">Our</span>
42+
<span className="bg-gradient-to-r from-orange-400 transition-all duration-200 to-purple-500 bg-clip-text text-transparent hover:saturate-150 hover:to-orange-400 hover:from-purple-500">
43+
Partners
44+
</span>
45+
</h1>
46+
<span className="text-2xl text-gray-50">All of the friends we&apos;ve made along the way.</span>
47+
</div>
48+
<div
49+
className="flex flex-col gap-10 px-10"
50+
>
51+
<Suspense placeholder="Loading..">{partners.length > 0 && partners.map((partner) => (
52+
<div key={partner.id} className="flex flex-col lg:flex-row gap-4 lg:gap-12 items-center justify-start bg-gray-900 rounded-lg p-8 my-2">
53+
<Image
54+
src={`https://pb.solsticehosting.co.uk/api/files/partners/${partner.id}/${partner.logo}?thumb=250x250`}
55+
width="250"
56+
height="250"
57+
className="object-contain object-left drop-shadow-xl"
58+
alt={partner.title}
59+
/>
60+
<div className="w-full flex flex-col justify-between h-full items-start gap-4">
61+
<h3 className="text-3xl font-extrabold text-white w-full flex gap-12 items-end">
62+
{partner.title} {(partner.account).includes(userId) && (<span className="font-semibold text-gray-400 text-lg italic"> Pssst... this is you!</span>)}
63+
</h3>
64+
<p className="w-full whitespace-pre-wrap text-white">
65+
{partner.memo}
66+
</p>
67+
<div className="flex gap-4">
68+
{partner.site &&
69+
(<Link href={`${partner.site ? partner.site : ''}`} target="_blank">
70+
<Button className="bg-gray-800 hover:bg-gray-700 h-full w-40">
71+
View Site
72+
</Button>
73+
</Link>)}
74+
{partner.discord &&
75+
(<Link href={`${partner.discord ? partner.discord : ''}`} target="_blank">
76+
<Button className="h-12 w-12 bg-gray-800 hover:bg-gray-700">
77+
<FontAwesomeIcon icon={faDiscord} />
78+
</Button>
79+
</Link>)}
80+
</div>
81+
</div>
82+
</div>
83+
))}</Suspense>
84+
85+
<span className="w-full text-white font-semibold text-center text-2xl py-4 mb-8">Want to become a partner? Reach out on <Link href={'https://discord.gg/tgMFqC9EzY'} target="_blank" className="font-extrabold italic">our discord</Link></span>
86+
</div>
87+
</main>
88+
<Footer />
89+
90+
</>
91+
)
92+
}

0 commit comments

Comments
 (0)