@jhits/plugin-website 0.0.11 β 0.0.13
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/api/handler.d.ts.map +1 -1
- package/dist/api/handler.js +10 -0
- package/dist/types/settings.d.ts +12 -0
- package/dist/types/settings.d.ts.map +1 -1
- package/dist/views/SettingsView.d.ts.map +1 -1
- package/dist/views/SettingsView.js +79 -14
- package/package.json +2 -2
- package/src/api/handler.ts +10 -0
- package/src/types/settings.ts +15 -0
- package/src/views/SettingsView.tsx +132 -30
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"handler.d.ts","sourceRoot":"","sources":["../../src/api/handler.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAIH,OAAO,EAAE,WAAW,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AACxD,OAAO,EAAE,gBAAgB,EAAE,MAAM,mBAAmB,CAAC;AAGrD,YAAY,EAAE,gBAAgB,EAAE,MAAM,mBAAmB,CAAC;AAE1D;;GAEG;AACH,wBAAsB,YAAY,CAC9B,GAAG,EAAE,WAAW,EAChB,MAAM,EAAE,gBAAgB,GACzB,OAAO,CAAC,YAAY,CAAC,
|
|
1
|
+
{"version":3,"file":"handler.d.ts","sourceRoot":"","sources":["../../src/api/handler.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAIH,OAAO,EAAE,WAAW,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AACxD,OAAO,EAAE,gBAAgB,EAAE,MAAM,mBAAmB,CAAC;AAGrD,YAAY,EAAE,gBAAgB,EAAE,MAAM,mBAAmB,CAAC;AAE1D;;GAEG;AACH,wBAAsB,YAAY,CAC9B,GAAG,EAAE,WAAW,EAChB,MAAM,EAAE,gBAAgB,GACzB,OAAO,CAAC,YAAY,CAAC,CAuDvB;AAED;;GAEG;AACH,wBAAsB,aAAa,CAC/B,GAAG,EAAE,WAAW,EAChB,MAAM,EAAE,gBAAgB,GACzB,OAAO,CAAC,YAAY,CAAC,CAmFvB"}
|
package/dist/api/handler.js
CHANGED
|
@@ -28,6 +28,16 @@ export async function GET_SETTINGS(req, config) {
|
|
|
28
28
|
maintenanceMode: false,
|
|
29
29
|
launch_date: '',
|
|
30
30
|
socials: [],
|
|
31
|
+
localizedContactInfo: {
|
|
32
|
+
en: { physicalAddress: '', phoneNumber: '' },
|
|
33
|
+
sv: { physicalAddress: '', phoneNumber: '' },
|
|
34
|
+
nl: { physicalAddress: '', phoneNumber: '' },
|
|
35
|
+
},
|
|
36
|
+
localizedSocials: {
|
|
37
|
+
en: [],
|
|
38
|
+
sv: [],
|
|
39
|
+
nl: [],
|
|
40
|
+
},
|
|
31
41
|
});
|
|
32
42
|
}
|
|
33
43
|
// Convert launch_date from Date to ISO string if it exists
|
package/dist/types/settings.d.ts
CHANGED
|
@@ -1,6 +1,16 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Website Settings Types
|
|
3
3
|
*/
|
|
4
|
+
export type SupportedLocale = 'en' | 'sv' | 'nl';
|
|
5
|
+
export interface LocalizedContactInfo {
|
|
6
|
+
physicalAddress?: string;
|
|
7
|
+
phoneNumber?: string;
|
|
8
|
+
}
|
|
9
|
+
export interface LocalizedSocialLink {
|
|
10
|
+
id: number;
|
|
11
|
+
platform: string;
|
|
12
|
+
url: string;
|
|
13
|
+
}
|
|
4
14
|
export interface WebsiteSettings {
|
|
5
15
|
identifier: string;
|
|
6
16
|
siteName?: string;
|
|
@@ -14,6 +24,8 @@ export interface WebsiteSettings {
|
|
|
14
24
|
maintenanceMode?: boolean;
|
|
15
25
|
launch_date?: string;
|
|
16
26
|
socials?: SocialLink[];
|
|
27
|
+
localizedContactInfo?: Partial<Record<SupportedLocale, LocalizedContactInfo>>;
|
|
28
|
+
localizedSocials?: Partial<Record<SupportedLocale, LocalizedSocialLink[]>>;
|
|
17
29
|
updatedAt?: Date;
|
|
18
30
|
createdAt?: Date;
|
|
19
31
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"settings.d.ts","sourceRoot":"","sources":["../../src/types/settings.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,MAAM,WAAW,eAAe;IAC5B,UAAU,EAAE,MAAM,CAAC;IACnB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,eAAe,CAAC,EAAE,OAAO,CAAC;IAC1B,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,OAAO,CAAC,EAAE,UAAU,EAAE,CAAC;IACvB,SAAS,CAAC,EAAE,IAAI,CAAC;IACjB,SAAS,CAAC,EAAE,IAAI,CAAC;CACpB;AAED,MAAM,WAAW,UAAU;IACvB,EAAE,EAAE,MAAM,CAAC;IACX,QAAQ,EAAE,MAAM,CAAC;IACjB,GAAG,EAAE,MAAM,CAAC;CACf;AAED,MAAM,WAAW,gBAAgB;IAC7B,KAAK,EAAE,MAAM,OAAO,CAAC;QAAE,EAAE,EAAE,MAAM,GAAG,CAAA;KAAE,CAAC,CAAC;IACxC,SAAS,CAAC,EAAE,CAAC,GAAG,EAAE,GAAG,KAAK,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAAC;IACjD,WAAW,CAAC,EAAE,OAAO,CAAC,GAAG,CAAC,CAAC;IAC3B,WAAW,CAAC,EAAE,GAAG,CAAC;IAClB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,CAAC,GAAG,EAAE,MAAM,GAAG,GAAG,CAAC;CACtB"}
|
|
1
|
+
{"version":3,"file":"settings.d.ts","sourceRoot":"","sources":["../../src/types/settings.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,MAAM,MAAM,eAAe,GAAG,IAAI,GAAG,IAAI,GAAG,IAAI,CAAC;AAEjD,MAAM,WAAW,oBAAoB;IACjC,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,WAAW,CAAC,EAAE,MAAM,CAAC;CACxB;AAED,MAAM,WAAW,mBAAmB;IAChC,EAAE,EAAE,MAAM,CAAC;IACX,QAAQ,EAAE,MAAM,CAAC;IACjB,GAAG,EAAE,MAAM,CAAC;CACf;AAED,MAAM,WAAW,eAAe;IAC5B,UAAU,EAAE,MAAM,CAAC;IACnB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,eAAe,CAAC,EAAE,OAAO,CAAC;IAC1B,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,OAAO,CAAC,EAAE,UAAU,EAAE,CAAC;IACvB,oBAAoB,CAAC,EAAE,OAAO,CAAC,MAAM,CAAC,eAAe,EAAE,oBAAoB,CAAC,CAAC,CAAC;IAC9E,gBAAgB,CAAC,EAAE,OAAO,CAAC,MAAM,CAAC,eAAe,EAAE,mBAAmB,EAAE,CAAC,CAAC,CAAC;IAC3E,SAAS,CAAC,EAAE,IAAI,CAAC;IACjB,SAAS,CAAC,EAAE,IAAI,CAAC;CACpB;AAED,MAAM,WAAW,UAAU;IACvB,EAAE,EAAE,MAAM,CAAC;IACX,QAAQ,EAAE,MAAM,CAAC;IACjB,GAAG,EAAE,MAAM,CAAC;CACf;AAED,MAAM,WAAW,gBAAgB;IAC7B,KAAK,EAAE,MAAM,OAAO,CAAC;QAAE,EAAE,EAAE,MAAM,GAAG,CAAA;KAAE,CAAC,CAAC;IACxC,SAAS,CAAC,EAAE,CAAC,GAAG,EAAE,GAAG,KAAK,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAAC;IACjD,WAAW,CAAC,EAAE,OAAO,CAAC,GAAG,CAAC,CAAC;IAC3B,WAAW,CAAC,EAAE,GAAG,CAAC;IAClB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,CAAC,GAAG,EAAE,MAAM,GAAG,GAAG,CAAC;CACtB"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"SettingsView.d.ts","sourceRoot":"","sources":["../../src/views/SettingsView.tsx"],"names":[],"mappings":"AAAA;;;GAGG;
|
|
1
|
+
{"version":3,"file":"SettingsView.d.ts","sourceRoot":"","sources":["../../src/views/SettingsView.tsx"],"names":[],"mappings":"AAAA;;;GAGG;AAyBH,MAAM,WAAW,iBAAiB;IAC9B,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,MAAM,CAAC;CAClB;AAED,wBAAgB,YAAY,CAAC,EAAE,MAAM,EAAE,MAAM,EAAE,EAAE,iBAAiB,2CA2kBjE"}
|
|
@@ -8,6 +8,11 @@ import { useState, useEffect, useRef } from 'react';
|
|
|
8
8
|
import { Save, RefreshCw, Globe, Mail, Search, Settings2, Calendar } from 'lucide-react';
|
|
9
9
|
import { FaFacebook, FaInstagram, FaLinkedin, FaPinterest, FaTiktok } from 'react-icons/fa';
|
|
10
10
|
import { FaXTwitter } from 'react-icons/fa6';
|
|
11
|
+
const AVAILABLE_LOCALES = [
|
|
12
|
+
{ code: 'en', name: 'English', flag: 'π¬π§' },
|
|
13
|
+
{ code: 'sv', name: 'Swedish', flag: 'πΈπͺ' },
|
|
14
|
+
{ code: 'nl', name: 'Dutch', flag: 'π³π±' },
|
|
15
|
+
];
|
|
11
16
|
const AVAILABLE_PLATFORMS = [
|
|
12
17
|
{ name: 'Instagram', icon: _jsx(FaInstagram, { size: 18 }) },
|
|
13
18
|
{ name: 'Facebook', icon: _jsx(FaFacebook, { size: 18 }) },
|
|
@@ -20,6 +25,7 @@ export function SettingsView({ siteId, locale }) {
|
|
|
20
25
|
const [isLoading, setIsLoading] = useState(true);
|
|
21
26
|
const [isSaving, setIsSaving] = useState(false);
|
|
22
27
|
const [showSuccess, setShowSuccess] = useState(false);
|
|
28
|
+
const [activeTab, setActiveTab] = useState('en');
|
|
23
29
|
const [settings, setSettings] = useState({
|
|
24
30
|
identifier: 'site_config',
|
|
25
31
|
siteName: '',
|
|
@@ -33,6 +39,16 @@ export function SettingsView({ siteId, locale }) {
|
|
|
33
39
|
maintenanceMode: false,
|
|
34
40
|
launch_date: '',
|
|
35
41
|
socials: [],
|
|
42
|
+
localizedContactInfo: {
|
|
43
|
+
en: { physicalAddress: '', phoneNumber: '' },
|
|
44
|
+
sv: { physicalAddress: '', phoneNumber: '' },
|
|
45
|
+
nl: { physicalAddress: '', phoneNumber: '' },
|
|
46
|
+
},
|
|
47
|
+
localizedSocials: {
|
|
48
|
+
en: [],
|
|
49
|
+
sv: [],
|
|
50
|
+
nl: [],
|
|
51
|
+
},
|
|
36
52
|
});
|
|
37
53
|
// Fetch settings on load
|
|
38
54
|
useEffect(() => {
|
|
@@ -88,6 +104,16 @@ export function SettingsView({ siteId, locale }) {
|
|
|
88
104
|
maintenanceMode: data.maintenanceMode ?? false,
|
|
89
105
|
launch_date: launchDate,
|
|
90
106
|
socials: data.socials || [],
|
|
107
|
+
localizedContactInfo: data.localizedContactInfo || {
|
|
108
|
+
en: { physicalAddress: '', phoneNumber: '' },
|
|
109
|
+
sv: { physicalAddress: '', phoneNumber: '' },
|
|
110
|
+
nl: { physicalAddress: '', phoneNumber: '' },
|
|
111
|
+
},
|
|
112
|
+
localizedSocials: data.localizedSocials || {
|
|
113
|
+
en: [],
|
|
114
|
+
sv: [],
|
|
115
|
+
nl: [],
|
|
116
|
+
},
|
|
91
117
|
});
|
|
92
118
|
}
|
|
93
119
|
}
|
|
@@ -151,26 +177,58 @@ export function SettingsView({ siteId, locale }) {
|
|
|
151
177
|
setIsSaving(false);
|
|
152
178
|
}
|
|
153
179
|
};
|
|
154
|
-
//
|
|
155
|
-
const
|
|
156
|
-
const newId = settings.socials?.length ? Math.max(...settings.socials.map(s => s.id)) + 1 : 1;
|
|
180
|
+
// Remove social link
|
|
181
|
+
const handleRemoveSocial = (id) => {
|
|
157
182
|
setSettings({
|
|
158
183
|
...settings,
|
|
159
|
-
socials:
|
|
184
|
+
socials: settings.socials?.filter(social => social.id !== id) || [],
|
|
160
185
|
});
|
|
161
186
|
};
|
|
162
|
-
// Update
|
|
163
|
-
const
|
|
187
|
+
// Update localized contact info
|
|
188
|
+
const handleUpdateLocalizedContact = (field, value) => {
|
|
164
189
|
setSettings({
|
|
165
190
|
...settings,
|
|
166
|
-
|
|
191
|
+
localizedContactInfo: {
|
|
192
|
+
...settings.localizedContactInfo,
|
|
193
|
+
[activeTab]: {
|
|
194
|
+
...settings.localizedContactInfo?.[activeTab],
|
|
195
|
+
[field]: value,
|
|
196
|
+
},
|
|
197
|
+
},
|
|
167
198
|
});
|
|
168
199
|
};
|
|
169
|
-
//
|
|
170
|
-
const
|
|
200
|
+
// Add localized social link
|
|
201
|
+
const handleAddLocalizedSocial = () => {
|
|
202
|
+
const currentSocials = settings.localizedSocials?.[activeTab] || [];
|
|
203
|
+
const newId = currentSocials.length ? Math.max(...currentSocials.map(s => s.id)) + 1 : 1;
|
|
171
204
|
setSettings({
|
|
172
205
|
...settings,
|
|
173
|
-
|
|
206
|
+
localizedSocials: {
|
|
207
|
+
...settings.localizedSocials,
|
|
208
|
+
[activeTab]: [...currentSocials, { id: newId, platform: '', url: '' }],
|
|
209
|
+
},
|
|
210
|
+
});
|
|
211
|
+
};
|
|
212
|
+
// Update localized social link
|
|
213
|
+
const handleUpdateLocalizedSocial = (id, field, value) => {
|
|
214
|
+
const currentSocials = settings.localizedSocials?.[activeTab] || [];
|
|
215
|
+
setSettings({
|
|
216
|
+
...settings,
|
|
217
|
+
localizedSocials: {
|
|
218
|
+
...settings.localizedSocials,
|
|
219
|
+
[activeTab]: currentSocials.map(social => social.id === id ? { ...social, [field]: value } : social),
|
|
220
|
+
},
|
|
221
|
+
});
|
|
222
|
+
};
|
|
223
|
+
// Remove localized social link
|
|
224
|
+
const handleRemoveLocalizedSocial = (id) => {
|
|
225
|
+
const currentSocials = settings.localizedSocials?.[activeTab] || [];
|
|
226
|
+
setSettings({
|
|
227
|
+
...settings,
|
|
228
|
+
localizedSocials: {
|
|
229
|
+
...settings.localizedSocials,
|
|
230
|
+
[activeTab]: currentSocials.filter(social => social.id !== id),
|
|
231
|
+
},
|
|
174
232
|
});
|
|
175
233
|
};
|
|
176
234
|
if (isLoading) {
|
|
@@ -180,10 +238,17 @@ export function SettingsView({ siteId, locale }) {
|
|
|
180
238
|
? 'bg-neutral-400 text-white cursor-not-allowed'
|
|
181
239
|
: showSuccess
|
|
182
240
|
? 'bg-green-600 text-white'
|
|
183
|
-
: 'bg-primary text-white hover:bg-primary/90'}`, children: isSaving ? (_jsxs(_Fragment, { children: [_jsx(RefreshCw, { className: "w-4 h-4 animate-spin" }), "Saving..."] })) : showSuccess ? (_jsxs(_Fragment, { children: [_jsx(Settings2, { className: "w-4 h-4" }), "Saved!"] })) : (_jsxs(_Fragment, { children: [_jsx(Save, { className: "w-4 h-4" }), "Save Settings"] })) })] }), _jsxs("div", { className: "grid grid-cols-1 lg:grid-cols-3 gap-8", children: [_jsxs("div", { className: "lg:col-span-2 space-y-8", children: [_jsxs("section", { className: "bg-dashboard-bg p-8 rounded-3xl border border-dashboard-border", children: [_jsxs("div", { className: "flex items-center gap-2 font-bold text-dashboard-text border-b border-dashboard-border pb-4 mb-6", children: [_jsx(Search, { size: 20, className: "text-primary" }), "Website Identity & SEO"] }), _jsxs("div", { className: "grid grid-cols-1 md:grid-cols-2 gap-6", children: [_jsxs("div", { className: "space-y-2", children: [_jsx("label", { className: "text-xs font-bold text-dashboard-text-secondary uppercase tracking-widest", children: "Website Name" }), _jsx("input", { type: "text", value: settings.siteName || '', onChange: (e) => setSettings({ ...settings, siteName: e.target.value }), placeholder: "e.g., Botanics & You", className: "w-full px-4 py-3 bg-dashboard-card border border-dashboard-border rounded-2xl outline-none focus:ring-2 focus:ring-primary transition-all text-dashboard-text" })] }), _jsxs("div", { className: "space-y-2", children: [_jsx("label", { className: "text-xs font-bold text-dashboard-text-secondary uppercase tracking-widest", children: "Website Tagline" }), _jsx("input", { type: "text", value: settings.siteTagline || '', onChange: (e) => setSettings({ ...settings, siteTagline: e.target.value }), placeholder: "e.g., Sharing my knowledge with you", className: "w-full px-4 py-3 bg-dashboard-card border border-dashboard-border rounded-2xl outline-none focus:ring-2 focus:ring-primary transition-all text-dashboard-text" })] })] }), _jsxs("div", { className: "mt-6 space-y-2", children: [_jsx("label", { className: "text-xs font-bold text-dashboard-text-secondary uppercase tracking-widest", children: "Website Description" }), _jsx("textarea", { value: settings.siteDescription || '', onChange: (e) => setSettings({ ...settings, siteDescription: e.target.value }), placeholder: "A brief description of your website", rows: 3, className: "w-full px-4 py-3 bg-dashboard-card border border-dashboard-border rounded-2xl outline-none focus:ring-2 focus:ring-primary transition-all text-dashboard-text resize-none" })] }), _jsxs("div", { className: "mt-6 space-y-2", children: [_jsx("label", { className: "text-xs font-bold text-dashboard-text-secondary uppercase tracking-widest", children: "Keywords (comma-separated)" }), _jsx("input", { type: "text", value: settings.keywords || '', onChange: (e) => setSettings({ ...settings, keywords: e.target.value }), placeholder: "keyword1, keyword2, keyword3", className: "w-full px-4 py-3 bg-dashboard-card border border-dashboard-border rounded-2xl outline-none focus:ring-2 focus:ring-primary transition-all text-dashboard-text" })] })] }), _jsxs("section", { className: "bg-dashboard-bg p-8 rounded-3xl border border-dashboard-border", children: [_jsxs("div", { className: "flex items-center gap-2 font-bold text-dashboard-text border-b border-dashboard-border pb-4 mb-6", children: [_jsx(Mail, { size: 20, className: "text-primary" }), "Contact Information"] }),
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
241
|
+
: 'bg-primary text-white hover:bg-primary/90'}`, children: isSaving ? (_jsxs(_Fragment, { children: [_jsx(RefreshCw, { className: "w-4 h-4 animate-spin" }), "Saving..."] })) : showSuccess ? (_jsxs(_Fragment, { children: [_jsx(Settings2, { className: "w-4 h-4" }), "Saved!"] })) : (_jsxs(_Fragment, { children: [_jsx(Save, { className: "w-4 h-4" }), "Save Settings"] })) })] }), _jsxs("div", { className: "grid grid-cols-1 lg:grid-cols-3 gap-8", children: [_jsxs("div", { className: "lg:col-span-2 space-y-8", children: [_jsxs("section", { className: "bg-dashboard-bg p-8 rounded-3xl border border-dashboard-border", children: [_jsxs("div", { className: "flex items-center gap-2 font-bold text-dashboard-text border-b border-dashboard-border pb-4 mb-6", children: [_jsx(Search, { size: 20, className: "text-primary" }), "Website Identity & SEO"] }), _jsxs("div", { className: "grid grid-cols-1 md:grid-cols-2 gap-6", children: [_jsxs("div", { className: "space-y-2", children: [_jsx("label", { className: "text-xs font-bold text-dashboard-text-secondary uppercase tracking-widest", children: "Website Name" }), _jsx("input", { type: "text", value: settings.siteName || '', onChange: (e) => setSettings({ ...settings, siteName: e.target.value }), placeholder: "e.g., Botanics & You", className: "w-full px-4 py-3 bg-dashboard-card border border-dashboard-border rounded-2xl outline-none focus:ring-2 focus:ring-primary transition-all text-dashboard-text" })] }), _jsxs("div", { className: "space-y-2", children: [_jsx("label", { className: "text-xs font-bold text-dashboard-text-secondary uppercase tracking-widest", children: "Website Tagline" }), _jsx("input", { type: "text", value: settings.siteTagline || '', onChange: (e) => setSettings({ ...settings, siteTagline: e.target.value }), placeholder: "e.g., Sharing my knowledge with you", className: "w-full px-4 py-3 bg-dashboard-card border border-dashboard-border rounded-2xl outline-none focus:ring-2 focus:ring-primary transition-all text-dashboard-text" })] })] }), _jsxs("div", { className: "mt-6 space-y-2", children: [_jsx("label", { className: "text-xs font-bold text-dashboard-text-secondary uppercase tracking-widest", children: "Website Description" }), _jsx("textarea", { value: settings.siteDescription || '', onChange: (e) => setSettings({ ...settings, siteDescription: e.target.value }), placeholder: "A brief description of your website", rows: 3, className: "w-full px-4 py-3 bg-dashboard-card border border-dashboard-border rounded-2xl outline-none focus:ring-2 focus:ring-primary transition-all text-dashboard-text resize-none" })] }), _jsxs("div", { className: "mt-6 space-y-2", children: [_jsx("label", { className: "text-xs font-bold text-dashboard-text-secondary uppercase tracking-widest", children: "Keywords (comma-separated)" }), _jsx("input", { type: "text", value: settings.keywords || '', onChange: (e) => setSettings({ ...settings, keywords: e.target.value }), placeholder: "keyword1, keyword2, keyword3", className: "w-full px-4 py-3 bg-dashboard-card border border-dashboard-border rounded-2xl outline-none focus:ring-2 focus:ring-primary transition-all text-dashboard-text" })] })] }), _jsxs("section", { className: "bg-dashboard-bg p-8 rounded-3xl border border-dashboard-border", children: [_jsxs("div", { className: "flex items-center gap-2 font-bold text-dashboard-text border-b border-dashboard-border pb-4 mb-6", children: [_jsx(Mail, { size: 20, className: "text-primary" }), "Contact Information"] }), _jsx("div", { className: "flex gap-2 mb-6", children: AVAILABLE_LOCALES.map((loc) => (_jsxs("button", { onClick: () => setActiveTab(loc.code), className: `px-4 py-2 rounded-full text-xs font-bold uppercase tracking-widest transition-all ${activeTab === loc.code
|
|
242
|
+
? 'bg-primary text-white'
|
|
243
|
+
: 'bg-dashboard-card text-dashboard-text-secondary hover:bg-dashboard-border'}`, children: [_jsx("span", { className: "mr-1", children: loc.flag }), loc.code.toUpperCase()] }, loc.code))) }), _jsxs("div", { className: "grid grid-cols-1 md:grid-cols-2 gap-6", children: [_jsxs("div", { className: "space-y-2", children: [_jsx("label", { className: "text-xs font-bold text-dashboard-text-secondary uppercase tracking-widest", children: "Contact Email (global)" }), _jsx("input", { type: "email", value: settings.contactEmail || '', onChange: (e) => setSettings({ ...settings, contactEmail: e.target.value }), placeholder: "contact@example.com", className: "w-full px-4 py-3 bg-dashboard-card border border-dashboard-border rounded-2xl outline-none focus:ring-2 focus:ring-primary transition-all text-dashboard-text" })] }), _jsxs("div", { className: "space-y-2", children: [_jsxs("label", { className: "text-xs font-bold text-dashboard-text-secondary uppercase tracking-widest", children: ["Phone Number (", activeTab.toUpperCase(), ")"] }), _jsx("input", { type: "tel", value: settings.localizedContactInfo?.[activeTab]?.phoneNumber || settings.phoneNumber || '', onChange: (e) => handleUpdateLocalizedContact('phoneNumber', e.target.value), placeholder: "+31 6 12345678", className: "w-full px-4 py-3 bg-dashboard-card border border-dashboard-border rounded-2xl outline-none focus:ring-2 focus:ring-primary transition-all text-dashboard-text" })] })] }), _jsxs("div", { className: "mt-6 space-y-2", children: [_jsxs("label", { className: "text-xs font-bold text-dashboard-text-secondary uppercase tracking-widest", children: ["Physical Address (", activeTab.toUpperCase(), ")"] }), _jsx("textarea", { value: settings.localizedContactInfo?.[activeTab]?.physicalAddress || settings.physicalAddress || '', onChange: (e) => handleUpdateLocalizedContact('physicalAddress', e.target.value), placeholder: "Street address, City, Country", rows: 2, className: "w-full px-4 py-3 bg-dashboard-card border border-dashboard-border rounded-2xl outline-none focus:ring-2 focus:ring-primary transition-all text-dashboard-text resize-none" })] })] }), _jsxs("section", { className: "bg-dashboard-bg p-8 rounded-3xl border border-dashboard-border", children: [_jsxs("div", { className: "flex items-center justify-between border-b border-dashboard-border pb-4 mb-6", children: [_jsxs("div", { className: "flex items-center gap-2 font-bold text-dashboard-text", children: [_jsx(Globe, { size: 20, className: "text-primary" }), "Social Links (", activeTab.toUpperCase(), ")"] }), _jsx("button", { onClick: handleAddLocalizedSocial, className: "px-4 py-2 text-xs font-bold uppercase tracking-widest bg-primary text-white rounded-full hover:bg-primary/90 transition-all", children: "Add Social" })] }), _jsx("div", { className: "flex gap-2 mb-6", children: AVAILABLE_LOCALES.map((loc) => (_jsxs("button", { onClick: () => setActiveTab(loc.code), className: `px-4 py-2 rounded-full text-xs font-bold uppercase tracking-widest transition-all ${activeTab === loc.code
|
|
244
|
+
? 'bg-primary text-white'
|
|
245
|
+
: 'bg-dashboard-card text-dashboard-text-secondary hover:bg-dashboard-border'}`, children: [_jsx("span", { className: "mr-1", children: loc.flag }), loc.code.toUpperCase()] }, loc.code))) }), _jsx("div", { className: "space-y-4", children: (() => {
|
|
246
|
+
const currentSocials = settings.localizedSocials?.[activeTab] || [];
|
|
247
|
+
return currentSocials.length > 0 ? (currentSocials.map((social) => {
|
|
248
|
+
const platform = AVAILABLE_PLATFORMS.find(p => p.name === social.platform);
|
|
249
|
+
return (_jsxs("div", { className: "flex items-center gap-4 p-4 bg-dashboard-card rounded-2xl border border-dashboard-border", children: [_jsx("div", { className: "flex-shrink-0 text-dashboard-text-secondary", children: platform?.icon || _jsx(Globe, { size: 18 }) }), _jsxs("select", { value: social.platform, onChange: (e) => handleUpdateLocalizedSocial(social.id, 'platform', e.target.value), className: "flex-1 px-4 py-2 bg-dashboard-bg border border-dashboard-border rounded-xl outline-none focus:ring-2 focus:ring-primary text-dashboard-text", children: [_jsx("option", { value: "", children: "Select Platform" }), AVAILABLE_PLATFORMS.map(p => (_jsx("option", { value: p.name, children: p.name }, p.name)))] }), _jsx("input", { type: "url", value: social.url, onChange: (e) => handleUpdateLocalizedSocial(social.id, 'url', e.target.value), placeholder: "https://...", className: "flex-1 px-4 py-2 bg-dashboard-bg border border-dashboard-border rounded-xl outline-none focus:ring-2 focus:ring-primary text-dashboard-text" }), _jsx("button", { onClick: () => handleRemoveLocalizedSocial(social.id), className: "px-4 py-2 text-xs font-bold text-red-500 hover:text-red-700 dark:hover:text-red-400 transition-colors", children: "Remove" })] }, social.id));
|
|
250
|
+
})) : (_jsxs("p", { className: "text-sm text-dashboard-text-secondary text-center py-8", children: ["No social links added for ", activeTab.toUpperCase(), ". Click \"Add Social\" to get started."] }));
|
|
251
|
+
})() })] })] }), _jsxs("div", { className: "space-y-8", children: [_jsxs("section", { className: "bg-dashboard-bg p-6 rounded-3xl border border-dashboard-border", children: [_jsxs("div", { className: "flex items-center gap-2 font-bold text-dashboard-text border-b border-dashboard-border pb-4 mb-6", children: [_jsx(Settings2, { size: 18, className: "text-primary" }), "Maintenance"] }), _jsxs("div", { className: "flex items-center justify-between", children: [_jsxs("div", { children: [_jsx("label", { className: "text-xs font-bold text-dashboard-text block mb-1", children: "Maintenance Mode" }), _jsx("p", { className: "text-[10px] text-dashboard-text-secondary", children: "Show maintenance page to visitors" })] }), _jsx("button", { onClick: () => setSettings({ ...settings, maintenanceMode: !settings.maintenanceMode }), className: `relative w-12 h-6 rounded-full transition-colors ${settings.maintenanceMode ? 'bg-primary' : 'bg-neutral-200 dark:bg-neutral-700'}`, children: _jsx("div", { className: `absolute top-1 left-1 w-4 h-4 bg-white rounded-full transition-transform duration-200 ${settings.maintenanceMode ? 'translate-x-6' : 'translate-x-0'}` }) })] })] }), _jsxs("section", { className: "bg-dashboard-bg p-6 rounded-3xl border border-dashboard-border", children: [_jsxs("div", { className: "flex items-center gap-2 font-bold text-dashboard-text border-b border-dashboard-border pb-4 mb-6", children: [_jsx(Calendar, { size: 18, className: "text-primary" }), "Launch Date"] }), _jsxs("div", { className: "space-y-4", children: [_jsxs("div", { className: "space-y-2", children: [_jsx("label", { className: "text-xs font-bold text-dashboard-text block", children: "Date" }), _jsx("input", { type: "date", value: settings.launch_date ? settings.launch_date.split('T')[0] : '', onChange: (e) => {
|
|
187
252
|
const dateValue = e.target.value;
|
|
188
253
|
const currentTime = settings.launch_date?.includes('T')
|
|
189
254
|
? settings.launch_date.split('T')[1]
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@jhits/plugin-website",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.13",
|
|
4
4
|
"description": "Website management and configuration plugin for the JHITS ecosystem",
|
|
5
5
|
"publishConfig": {
|
|
6
6
|
"access": "public"
|
|
@@ -29,7 +29,7 @@
|
|
|
29
29
|
"mongodb": "^7.1.0",
|
|
30
30
|
"next-auth": "^4.24.13",
|
|
31
31
|
"react-icons": "^5.5.0",
|
|
32
|
-
"@jhits/plugin-core": "0.0.
|
|
32
|
+
"@jhits/plugin-core": "0.0.10"
|
|
33
33
|
},
|
|
34
34
|
"peerDependencies": {
|
|
35
35
|
"next": ">=15.0.0",
|
package/src/api/handler.ts
CHANGED
|
@@ -40,6 +40,16 @@ export async function GET_SETTINGS(
|
|
|
40
40
|
maintenanceMode: false,
|
|
41
41
|
launch_date: '',
|
|
42
42
|
socials: [],
|
|
43
|
+
localizedContactInfo: {
|
|
44
|
+
en: { physicalAddress: '', phoneNumber: '' },
|
|
45
|
+
sv: { physicalAddress: '', phoneNumber: '' },
|
|
46
|
+
nl: { physicalAddress: '', phoneNumber: '' },
|
|
47
|
+
},
|
|
48
|
+
localizedSocials: {
|
|
49
|
+
en: [],
|
|
50
|
+
sv: [],
|
|
51
|
+
nl: [],
|
|
52
|
+
},
|
|
43
53
|
});
|
|
44
54
|
}
|
|
45
55
|
|
package/src/types/settings.ts
CHANGED
|
@@ -2,6 +2,19 @@
|
|
|
2
2
|
* Website Settings Types
|
|
3
3
|
*/
|
|
4
4
|
|
|
5
|
+
export type SupportedLocale = 'en' | 'sv' | 'nl';
|
|
6
|
+
|
|
7
|
+
export interface LocalizedContactInfo {
|
|
8
|
+
physicalAddress?: string;
|
|
9
|
+
phoneNumber?: string;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
export interface LocalizedSocialLink {
|
|
13
|
+
id: number;
|
|
14
|
+
platform: string;
|
|
15
|
+
url: string;
|
|
16
|
+
}
|
|
17
|
+
|
|
5
18
|
export interface WebsiteSettings {
|
|
6
19
|
identifier: string;
|
|
7
20
|
siteName?: string;
|
|
@@ -15,6 +28,8 @@ export interface WebsiteSettings {
|
|
|
15
28
|
maintenanceMode?: boolean;
|
|
16
29
|
launch_date?: string;
|
|
17
30
|
socials?: SocialLink[];
|
|
31
|
+
localizedContactInfo?: Partial<Record<SupportedLocale, LocalizedContactInfo>>;
|
|
32
|
+
localizedSocials?: Partial<Record<SupportedLocale, LocalizedSocialLink[]>>;
|
|
18
33
|
updatedAt?: Date;
|
|
19
34
|
createdAt?: Date;
|
|
20
35
|
}
|
|
@@ -7,10 +7,16 @@
|
|
|
7
7
|
|
|
8
8
|
import React, { useState, useEffect, useRef } from 'react';
|
|
9
9
|
import { Save, RefreshCw, Globe, Mail, Phone, MapPin, Search, Settings2, Calendar } from 'lucide-react';
|
|
10
|
-
import { WebsiteSettings, SocialLink } from '../types/settings';
|
|
10
|
+
import { WebsiteSettings, SocialLink, SupportedLocale, LocalizedSocialLink } from '../types/settings';
|
|
11
11
|
import { FaFacebook, FaInstagram, FaLinkedin, FaPinterest, FaTiktok } from 'react-icons/fa';
|
|
12
12
|
import { FaXTwitter } from 'react-icons/fa6';
|
|
13
13
|
|
|
14
|
+
const AVAILABLE_LOCALES: { code: SupportedLocale; name: string; flag: string }[] = [
|
|
15
|
+
{ code: 'en', name: 'English', flag: 'π¬π§' },
|
|
16
|
+
{ code: 'sv', name: 'Swedish', flag: 'πΈπͺ' },
|
|
17
|
+
{ code: 'nl', name: 'Dutch', flag: 'π³π±' },
|
|
18
|
+
];
|
|
19
|
+
|
|
14
20
|
const AVAILABLE_PLATFORMS = [
|
|
15
21
|
{ name: 'Instagram', icon: <FaInstagram size={18} /> },
|
|
16
22
|
{ name: 'Facebook', icon: <FaFacebook size={18} /> },
|
|
@@ -29,6 +35,7 @@ export function SettingsView({ siteId, locale }: SettingsViewProps) {
|
|
|
29
35
|
const [isLoading, setIsLoading] = useState(true);
|
|
30
36
|
const [isSaving, setIsSaving] = useState(false);
|
|
31
37
|
const [showSuccess, setShowSuccess] = useState(false);
|
|
38
|
+
const [activeTab, setActiveTab] = useState<SupportedLocale>('en');
|
|
32
39
|
const [settings, setSettings] = useState<WebsiteSettings>({
|
|
33
40
|
identifier: 'site_config',
|
|
34
41
|
siteName: '',
|
|
@@ -42,6 +49,16 @@ export function SettingsView({ siteId, locale }: SettingsViewProps) {
|
|
|
42
49
|
maintenanceMode: false,
|
|
43
50
|
launch_date: '',
|
|
44
51
|
socials: [],
|
|
52
|
+
localizedContactInfo: {
|
|
53
|
+
en: { physicalAddress: '', phoneNumber: '' },
|
|
54
|
+
sv: { physicalAddress: '', phoneNumber: '' },
|
|
55
|
+
nl: { physicalAddress: '', phoneNumber: '' },
|
|
56
|
+
},
|
|
57
|
+
localizedSocials: {
|
|
58
|
+
en: [],
|
|
59
|
+
sv: [],
|
|
60
|
+
nl: [],
|
|
61
|
+
},
|
|
45
62
|
});
|
|
46
63
|
|
|
47
64
|
// Fetch settings on load
|
|
@@ -96,6 +113,16 @@ export function SettingsView({ siteId, locale }: SettingsViewProps) {
|
|
|
96
113
|
maintenanceMode: data.maintenanceMode ?? false,
|
|
97
114
|
launch_date: launchDate,
|
|
98
115
|
socials: data.socials || [],
|
|
116
|
+
localizedContactInfo: data.localizedContactInfo || {
|
|
117
|
+
en: { physicalAddress: '', phoneNumber: '' },
|
|
118
|
+
sv: { physicalAddress: '', phoneNumber: '' },
|
|
119
|
+
nl: { physicalAddress: '', phoneNumber: '' },
|
|
120
|
+
},
|
|
121
|
+
localizedSocials: data.localizedSocials || {
|
|
122
|
+
en: [],
|
|
123
|
+
sv: [],
|
|
124
|
+
nl: [],
|
|
125
|
+
},
|
|
99
126
|
});
|
|
100
127
|
}
|
|
101
128
|
} catch (error) {
|
|
@@ -164,30 +191,64 @@ export function SettingsView({ siteId, locale }: SettingsViewProps) {
|
|
|
164
191
|
}
|
|
165
192
|
};
|
|
166
193
|
|
|
167
|
-
//
|
|
168
|
-
const
|
|
169
|
-
const newId = settings.socials?.length ? Math.max(...settings.socials.map(s => s.id)) + 1 : 1;
|
|
194
|
+
// Remove social link
|
|
195
|
+
const handleRemoveSocial = (id: number) => {
|
|
170
196
|
setSettings({
|
|
171
197
|
...settings,
|
|
172
|
-
socials:
|
|
198
|
+
socials: settings.socials?.filter(social => social.id !== id) || [],
|
|
173
199
|
});
|
|
174
200
|
};
|
|
175
201
|
|
|
176
|
-
// Update
|
|
177
|
-
const
|
|
202
|
+
// Update localized contact info
|
|
203
|
+
const handleUpdateLocalizedContact = (field: 'physicalAddress' | 'phoneNumber', value: string) => {
|
|
178
204
|
setSettings({
|
|
179
205
|
...settings,
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
206
|
+
localizedContactInfo: {
|
|
207
|
+
...settings.localizedContactInfo,
|
|
208
|
+
[activeTab]: {
|
|
209
|
+
...settings.localizedContactInfo?.[activeTab],
|
|
210
|
+
[field]: value,
|
|
211
|
+
},
|
|
212
|
+
},
|
|
183
213
|
});
|
|
184
214
|
};
|
|
185
215
|
|
|
186
|
-
//
|
|
187
|
-
const
|
|
216
|
+
// Add localized social link
|
|
217
|
+
const handleAddLocalizedSocial = () => {
|
|
218
|
+
const currentSocials = settings.localizedSocials?.[activeTab] || [];
|
|
219
|
+
const newId = currentSocials.length ? Math.max(...currentSocials.map(s => s.id)) + 1 : 1;
|
|
188
220
|
setSettings({
|
|
189
221
|
...settings,
|
|
190
|
-
|
|
222
|
+
localizedSocials: {
|
|
223
|
+
...settings.localizedSocials,
|
|
224
|
+
[activeTab]: [...currentSocials, { id: newId, platform: '', url: '' }],
|
|
225
|
+
},
|
|
226
|
+
});
|
|
227
|
+
};
|
|
228
|
+
|
|
229
|
+
// Update localized social link
|
|
230
|
+
const handleUpdateLocalizedSocial = (id: number, field: 'platform' | 'url', value: string) => {
|
|
231
|
+
const currentSocials = settings.localizedSocials?.[activeTab] || [];
|
|
232
|
+
setSettings({
|
|
233
|
+
...settings,
|
|
234
|
+
localizedSocials: {
|
|
235
|
+
...settings.localizedSocials,
|
|
236
|
+
[activeTab]: currentSocials.map(social =>
|
|
237
|
+
social.id === id ? { ...social, [field]: value } : social
|
|
238
|
+
),
|
|
239
|
+
},
|
|
240
|
+
});
|
|
241
|
+
};
|
|
242
|
+
|
|
243
|
+
// Remove localized social link
|
|
244
|
+
const handleRemoveLocalizedSocial = (id: number) => {
|
|
245
|
+
const currentSocials = settings.localizedSocials?.[activeTab] || [];
|
|
246
|
+
setSettings({
|
|
247
|
+
...settings,
|
|
248
|
+
localizedSocials: {
|
|
249
|
+
...settings.localizedSocials,
|
|
250
|
+
[activeTab]: currentSocials.filter(social => social.id !== id),
|
|
251
|
+
},
|
|
191
252
|
});
|
|
192
253
|
};
|
|
193
254
|
|
|
@@ -311,10 +372,29 @@ export function SettingsView({ siteId, locale }: SettingsViewProps) {
|
|
|
311
372
|
<Mail size={20} className="text-primary" />
|
|
312
373
|
Contact Information
|
|
313
374
|
</div>
|
|
375
|
+
|
|
376
|
+
{/* Language Tabs */}
|
|
377
|
+
<div className="flex gap-2 mb-6">
|
|
378
|
+
{AVAILABLE_LOCALES.map((loc) => (
|
|
379
|
+
<button
|
|
380
|
+
key={loc.code}
|
|
381
|
+
onClick={() => setActiveTab(loc.code)}
|
|
382
|
+
className={`px-4 py-2 rounded-full text-xs font-bold uppercase tracking-widest transition-all ${
|
|
383
|
+
activeTab === loc.code
|
|
384
|
+
? 'bg-primary text-white'
|
|
385
|
+
: 'bg-dashboard-card text-dashboard-text-secondary hover:bg-dashboard-border'
|
|
386
|
+
}`}
|
|
387
|
+
>
|
|
388
|
+
<span className="mr-1">{loc.flag}</span>
|
|
389
|
+
{loc.code.toUpperCase()}
|
|
390
|
+
</button>
|
|
391
|
+
))}
|
|
392
|
+
</div>
|
|
393
|
+
|
|
314
394
|
<div className="grid grid-cols-1 md:grid-cols-2 gap-6">
|
|
315
395
|
<div className="space-y-2">
|
|
316
396
|
<label className="text-xs font-bold text-dashboard-text-secondary uppercase tracking-widest">
|
|
317
|
-
Contact Email
|
|
397
|
+
Contact Email (global)
|
|
318
398
|
</label>
|
|
319
399
|
<input
|
|
320
400
|
type="email"
|
|
@@ -326,12 +406,12 @@ export function SettingsView({ siteId, locale }: SettingsViewProps) {
|
|
|
326
406
|
</div>
|
|
327
407
|
<div className="space-y-2">
|
|
328
408
|
<label className="text-xs font-bold text-dashboard-text-secondary uppercase tracking-widest">
|
|
329
|
-
Phone Number
|
|
409
|
+
Phone Number ({activeTab.toUpperCase()})
|
|
330
410
|
</label>
|
|
331
411
|
<input
|
|
332
412
|
type="tel"
|
|
333
|
-
value={settings.phoneNumber || ''}
|
|
334
|
-
onChange={(e) =>
|
|
413
|
+
value={settings.localizedContactInfo?.[activeTab]?.phoneNumber || settings.phoneNumber || ''}
|
|
414
|
+
onChange={(e) => handleUpdateLocalizedContact('phoneNumber', e.target.value)}
|
|
335
415
|
placeholder="+31 6 12345678"
|
|
336
416
|
className="w-full px-4 py-3 bg-dashboard-card border border-dashboard-border rounded-2xl outline-none focus:ring-2 focus:ring-primary transition-all text-dashboard-text"
|
|
337
417
|
/>
|
|
@@ -339,11 +419,11 @@ export function SettingsView({ siteId, locale }: SettingsViewProps) {
|
|
|
339
419
|
</div>
|
|
340
420
|
<div className="mt-6 space-y-2">
|
|
341
421
|
<label className="text-xs font-bold text-dashboard-text-secondary uppercase tracking-widest">
|
|
342
|
-
Physical Address
|
|
422
|
+
Physical Address ({activeTab.toUpperCase()})
|
|
343
423
|
</label>
|
|
344
424
|
<textarea
|
|
345
|
-
value={settings.physicalAddress || ''}
|
|
346
|
-
onChange={(e) =>
|
|
425
|
+
value={settings.localizedContactInfo?.[activeTab]?.physicalAddress || settings.physicalAddress || ''}
|
|
426
|
+
onChange={(e) => handleUpdateLocalizedContact('physicalAddress', e.target.value)}
|
|
347
427
|
placeholder="Street address, City, Country"
|
|
348
428
|
rows={2}
|
|
349
429
|
className="w-full px-4 py-3 bg-dashboard-card border border-dashboard-border rounded-2xl outline-none focus:ring-2 focus:ring-primary transition-all text-dashboard-text resize-none"
|
|
@@ -351,23 +431,44 @@ export function SettingsView({ siteId, locale }: SettingsViewProps) {
|
|
|
351
431
|
</div>
|
|
352
432
|
</section>
|
|
353
433
|
|
|
354
|
-
{/* Social Links */}
|
|
434
|
+
{/* Social Links (Localized) */}
|
|
355
435
|
<section className="bg-dashboard-bg p-8 rounded-3xl border border-dashboard-border">
|
|
356
436
|
<div className="flex items-center justify-between border-b border-dashboard-border pb-4 mb-6">
|
|
357
437
|
<div className="flex items-center gap-2 font-bold text-dashboard-text">
|
|
358
438
|
<Globe size={20} className="text-primary" />
|
|
359
|
-
Social Links
|
|
439
|
+
Social Links ({activeTab.toUpperCase()})
|
|
360
440
|
</div>
|
|
361
441
|
<button
|
|
362
|
-
onClick={
|
|
442
|
+
onClick={handleAddLocalizedSocial}
|
|
363
443
|
className="px-4 py-2 text-xs font-bold uppercase tracking-widest bg-primary text-white rounded-full hover:bg-primary/90 transition-all"
|
|
364
444
|
>
|
|
365
445
|
Add Social
|
|
366
446
|
</button>
|
|
367
447
|
</div>
|
|
448
|
+
|
|
449
|
+
{/* Language Tabs for Socials */}
|
|
450
|
+
<div className="flex gap-2 mb-6">
|
|
451
|
+
{AVAILABLE_LOCALES.map((loc) => (
|
|
452
|
+
<button
|
|
453
|
+
key={loc.code}
|
|
454
|
+
onClick={() => setActiveTab(loc.code)}
|
|
455
|
+
className={`px-4 py-2 rounded-full text-xs font-bold uppercase tracking-widest transition-all ${
|
|
456
|
+
activeTab === loc.code
|
|
457
|
+
? 'bg-primary text-white'
|
|
458
|
+
: 'bg-dashboard-card text-dashboard-text-secondary hover:bg-dashboard-border'
|
|
459
|
+
}`}
|
|
460
|
+
>
|
|
461
|
+
<span className="mr-1">{loc.flag}</span>
|
|
462
|
+
{loc.code.toUpperCase()}
|
|
463
|
+
</button>
|
|
464
|
+
))}
|
|
465
|
+
</div>
|
|
466
|
+
|
|
368
467
|
<div className="space-y-4">
|
|
369
|
-
{
|
|
370
|
-
settings.
|
|
468
|
+
{(() => {
|
|
469
|
+
const currentSocials = settings.localizedSocials?.[activeTab] || [];
|
|
470
|
+
return currentSocials.length > 0 ? (
|
|
471
|
+
currentSocials.map((social) => {
|
|
371
472
|
const platform = AVAILABLE_PLATFORMS.find(p => p.name === social.platform);
|
|
372
473
|
return (
|
|
373
474
|
<div key={social.id} className="flex items-center gap-4 p-4 bg-dashboard-card rounded-2xl border border-dashboard-border">
|
|
@@ -376,7 +477,7 @@ export function SettingsView({ siteId, locale }: SettingsViewProps) {
|
|
|
376
477
|
</div>
|
|
377
478
|
<select
|
|
378
479
|
value={social.platform}
|
|
379
|
-
onChange={(e) =>
|
|
480
|
+
onChange={(e) => handleUpdateLocalizedSocial(social.id, 'platform', e.target.value)}
|
|
380
481
|
className="flex-1 px-4 py-2 bg-dashboard-bg border border-dashboard-border rounded-xl outline-none focus:ring-2 focus:ring-primary text-dashboard-text"
|
|
381
482
|
>
|
|
382
483
|
<option value="">Select Platform</option>
|
|
@@ -387,12 +488,12 @@ export function SettingsView({ siteId, locale }: SettingsViewProps) {
|
|
|
387
488
|
<input
|
|
388
489
|
type="url"
|
|
389
490
|
value={social.url}
|
|
390
|
-
onChange={(e) =>
|
|
491
|
+
onChange={(e) => handleUpdateLocalizedSocial(social.id, 'url', e.target.value)}
|
|
391
492
|
placeholder="https://..."
|
|
392
493
|
className="flex-1 px-4 py-2 bg-dashboard-bg border border-dashboard-border rounded-xl outline-none focus:ring-2 focus:ring-primary text-dashboard-text"
|
|
393
494
|
/>
|
|
394
495
|
<button
|
|
395
|
-
onClick={() =>
|
|
496
|
+
onClick={() => handleRemoveLocalizedSocial(social.id)}
|
|
396
497
|
className="px-4 py-2 text-xs font-bold text-red-500 hover:text-red-700 dark:hover:text-red-400 transition-colors"
|
|
397
498
|
>
|
|
398
499
|
Remove
|
|
@@ -402,9 +503,10 @@ export function SettingsView({ siteId, locale }: SettingsViewProps) {
|
|
|
402
503
|
})
|
|
403
504
|
) : (
|
|
404
505
|
<p className="text-sm text-dashboard-text-secondary text-center py-8">
|
|
405
|
-
No social links added
|
|
506
|
+
No social links added for {activeTab.toUpperCase()}. Click "Add Social" to get started.
|
|
406
507
|
</p>
|
|
407
|
-
)
|
|
508
|
+
);
|
|
509
|
+
})()}
|
|
408
510
|
</div>
|
|
409
511
|
</section>
|
|
410
512
|
</div>
|