@jhits/plugin-website 0.0.14 → 0.0.16

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.
@@ -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,CAuDvB;AAED;;GAEG;AACH,wBAAsB,aAAa,CAC/B,GAAG,EAAE,WAAW,EAChB,MAAM,EAAE,gBAAgB,GACzB,OAAO,CAAC,YAAY,CAAC,CAmFvB"}
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,CAuDvB"}
@@ -69,12 +69,6 @@ export async function POST_SETTINGS(req, config) {
69
69
  return NextResponse.json({ error: 'Unauthorized' }, { status: 401 });
70
70
  }
71
71
  const body = await req.json();
72
- console.log('[WebsiteAPI] POST_SETTINGS received body:', {
73
- launch_date: body.launch_date,
74
- launch_date_type: typeof body.launch_date,
75
- has_launch_date: 'launch_date' in body,
76
- body_keys: Object.keys(body),
77
- });
78
72
  const dbConnection = await config.getDb();
79
73
  const db = dbConnection.db();
80
74
  const settings = db.collection('settings');
@@ -92,39 +86,19 @@ export async function POST_SETTINGS(req, config) {
92
86
  if (launch_date !== undefined && launch_date !== null && launch_date !== '') {
93
87
  // Convert launch_date from datetime-local string to Date if provided
94
88
  const date = new Date(launch_date);
95
- console.log('[WebsiteAPI] Date conversion:', {
96
- input: launch_date,
97
- parsed: date,
98
- isValid: !isNaN(date.getTime()),
99
- iso: !isNaN(date.getTime()) ? date.toISOString() : 'invalid',
100
- });
101
89
  if (!isNaN(date.getTime())) {
102
90
  updateOps.$set.launch_date = date;
103
- console.log('[WebsiteAPI] Setting launch_date to:', date.toISOString());
104
91
  }
105
92
  else {
106
- console.warn('[WebsiteAPI] Invalid date, removing launch_date field');
107
93
  updateOps.$unset = { launch_date: '' };
108
94
  }
109
95
  }
110
96
  else {
111
97
  // Remove launch_date field if it's empty, undefined, or null
112
- console.log('[WebsiteAPI] launch_date is empty/undefined, removing field');
113
98
  updateOps.$unset = { launch_date: '' };
114
99
  }
115
- console.log('[WebsiteAPI] Update operations:', JSON.stringify(updateOps, (key, value) => {
116
- if (value instanceof Date) {
117
- return value.toISOString();
118
- }
119
- return value;
120
- }, 2));
121
100
  // Upsert settings
122
- const result = await settings.updateOne({ identifier: 'site_config' }, updateOps, { upsert: true });
123
- console.log('[WebsiteAPI] Update result:', {
124
- matchedCount: result.matchedCount,
125
- modifiedCount: result.modifiedCount,
126
- upsertedCount: result.upsertedCount,
127
- });
101
+ await settings.updateOne({ identifier: 'site_config' }, updateOps, { upsert: true });
128
102
  return NextResponse.json({ success: true, message: 'Settings updated successfully' });
129
103
  }
130
104
  catch (error) {
@@ -1 +1 @@
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;AAyMD,wBAAgB,YAAY,CAAC,EAAE,MAAM,EAAE,MAAM,EAAE,EAAE,iBAAiB,2CAmdjE"}
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;AA+MD,wBAAgB,YAAY,CAAC,EAAE,MAAM,EAAE,MAAM,EAAE,EAAE,iBAAiB,2CAyejE"}
@@ -24,7 +24,7 @@ const AVAILABLE_PLATFORMS = [
24
24
  function DomainLanguagesCard({ config, onEdit }) {
25
25
  return (_jsxs("section", { className: "bg-dashboard-bg p-6 rounded-3xl border border-dashboard-border", children: [_jsx("div", { className: "flex items-center justify-between border-b border-dashboard-border pb-4 mb-4", children: _jsxs("div", { className: "flex items-center gap-2 font-bold text-dashboard-text", children: [_jsx(Globe2, { size: 18, className: "text-primary" }), "Domain Languages"] }) }), _jsx("div", { className: "space-y-2", children: config && config.length > 0 ? (_jsx("div", { className: "flex flex-wrap gap-2", children: config.map((entry, index) => (_jsxs("div", { className: "inline-flex items-center gap-2 px-3 py-1.5 bg-dashboard-card rounded-full border border-dashboard-border text-xs", children: [_jsx("span", { className: "font-medium text-dashboard-text", children: entry.domain }), _jsx("span", { className: "text-dashboard-text-secondary", children: "\u2192" }), _jsx("span", { children: AVAILABLE_LOCALES.find(l => l.code === entry.locale)?.flag }), _jsx("span", { className: "text-dashboard-text-secondary", children: entry.allowUserOverride ? '' : '🔒' })] }, index))) })) : (_jsx("p", { className: "text-xs text-dashboard-text-secondary", children: "No domain languages configured." })) }), _jsxs("button", { onClick: onEdit, className: "mt-4 w-full flex items-center justify-center gap-2 px-4 py-2 bg-primary text-white rounded-xl text-xs font-bold uppercase tracking-wider hover:bg-primary/90 transition-colors", children: [_jsx(Edit3, { size: 14 }), config?.length ? 'Edit Domains' : 'Add Domains'] })] }));
26
26
  }
27
- function DomainLanguagesModal({ isOpen, config, onSave, onClose }) {
27
+ function DomainLanguagesModal({ isOpen, config, onSave, onClose, onSaveAndClose, isSaving = false }) {
28
28
  const [tempConfig, setTempConfig] = useState(config);
29
29
  const [expandedIndex, setExpandedIndex] = useState(null);
30
30
  useEffect(() => {
@@ -50,7 +50,7 @@ function DomainLanguagesModal({ isOpen, config, onSave, onClose }) {
50
50
  const toggleExpand = (index) => {
51
51
  setExpandedIndex(expandedIndex === index ? null : index);
52
52
  };
53
- return (_jsx("div", { className: "fixed inset-0 bg-black/50 flex items-center justify-center z-50 p-4", children: _jsxs("div", { className: "bg-dashboard-bg rounded-3xl border border-dashboard-border w-full max-w-lg max-h-[80vh] overflow-hidden flex flex-col", children: [_jsxs("div", { className: "flex items-center justify-between p-6 border-b border-dashboard-border", children: [_jsx("h2", { className: "text-xl font-bold text-dashboard-text", children: "Domain Languages" }), _jsx("button", { onClick: onClose, className: "p-2 text-dashboard-text-secondary hover:text-dashboard-text transition-colors", children: _jsx(X, { size: 20 }) })] }), _jsxs("div", { className: "flex-1 overflow-y-auto p-6 space-y-4", children: [tempConfig.length > 0 && (_jsxs("div", { className: "space-y-2", children: [_jsx("p", { className: "text-xs font-bold text-dashboard-text-secondary uppercase tracking-wider", children: "Current Config" }), tempConfig.map((entry, index) => (_jsxs("div", { className: "bg-dashboard-card rounded-xl border border-dashboard-border overflow-hidden", children: [_jsxs("div", { onClick: () => toggleExpand(index), className: "w-full flex items-center justify-between p-3 text-left hover:bg-dashboard-border/50 transition-colors cursor-pointer", children: [_jsxs("div", { className: "flex items-center gap-2", children: [_jsx("span", { className: "font-medium text-dashboard-text", children: entry.domain || '(no domain)' }), _jsx("span", { className: "text-dashboard-text-secondary", children: "\u2192" }), _jsx("span", { children: AVAILABLE_LOCALES.find(l => l.code === entry.locale)?.flag }), entry.allowUserOverride === false && _jsx("span", { className: "text-dashboard-text-secondary", children: "\uD83D\uDD12" })] }), _jsxs("div", { className: "flex items-center gap-2", children: [_jsx("button", { onClick: (e) => { e.stopPropagation(); handleRemove(index); }, className: "p-1 text-red-500 hover:bg-red-500/10 rounded transition-colors", title: "Remove", children: _jsx(Trash2, { size: 14 }) }), _jsx("span", { className: "text-dashboard-text-secondary text-xs", children: expandedIndex === index ? '▲' : '▼' })] })] }), expandedIndex === index && (_jsxs("div", { className: "p-3 pt-0 space-y-3 border-t border-dashboard-border", children: [_jsxs("div", { className: "space-y-1", children: [_jsx("label", { className: "text-[10px] font-bold text-dashboard-text-secondary uppercase tracking-wider", children: "Domain" }), _jsx("input", { type: "text", value: entry.domain, onChange: (e) => handleUpdate(index, 'domain', e.target.value), placeholder: "example.com", className: "w-full px-3 py-2 bg-dashboard-bg border border-dashboard-border rounded-lg outline-none focus:ring-2 focus:ring-primary text-dashboard-text text-sm" })] }), _jsx("div", { className: "flex items-center gap-2", children: _jsxs("div", { className: "flex-1 space-y-1", children: [_jsx("label", { className: "text-[10px] font-bold text-dashboard-text-secondary uppercase tracking-wider", children: "Language" }), _jsx("select", { value: entry.locale, onChange: (e) => handleUpdate(index, 'locale', e.target.value), className: "w-full px-3 py-2 bg-dashboard-bg border border-dashboard-border rounded-lg outline-none focus:ring-2 focus:ring-primary text-dashboard-text text-sm", children: AVAILABLE_LOCALES.map(loc => (_jsxs("option", { value: loc.code, children: [loc.flag, " ", loc.name] }, loc.code))) })] }) }), _jsxs("div", { className: "flex items-center justify-between", children: [_jsx("label", { className: "text-[10px] text-dashboard-text-secondary", children: "Allow user to change" }), _jsx("button", { onClick: () => handleUpdate(index, 'allowUserOverride', !entry.allowUserOverride), className: `relative w-10 h-5 rounded-full transition-colors ${entry.allowUserOverride ? 'bg-primary' : 'bg-neutral-300 dark:bg-neutral-600'}`, children: _jsx("div", { className: `absolute top-0.5 left-0.5 w-4 h-4 bg-white rounded-full transition-transform duration-200 ${entry.allowUserOverride ? 'translate-x-5' : 'translate-x-0'}` }) })] })] }))] }, index)))] })), _jsxs("div", { className: "border-t border-dashboard-border pt-4", children: [_jsx("p", { className: "text-xs font-bold text-dashboard-text-secondary uppercase tracking-wider mb-3", children: "Add New Domain" }), _jsxs("button", { onClick: handleAdd, className: "w-full flex items-center justify-center gap-2 px-4 py-3 border-2 border-dashed border-dashboard-border text-dashboard-text-secondary hover:border-primary hover:text-primary rounded-xl transition-colors", children: [_jsx(Plus, { size: 16 }), "Add Domain"] })] }), _jsx("p", { className: "text-[10px] text-dashboard-text-secondary text-center pt-2", children: "Configure which language to use per domain. E.g., botanicsandyou.nl \u2192 Dutch, botanicsandyou.se \u2192 Swedish." })] }), _jsxs("div", { className: "flex gap-3 p-6 border-t border-dashboard-border", children: [_jsx("button", { onClick: onClose, className: "flex-1 px-4 py-2 bg-dashboard-card text-dashboard-text rounded-xl text-sm font-bold hover:bg-dashboard-border transition-colors", children: "Cancel" }), _jsx("button", { onClick: () => onSave(tempConfig), className: "flex-1 px-4 py-2 bg-primary text-white rounded-xl text-sm font-bold hover:bg-primary/90 transition-colors", children: "Save" })] })] }) }));
53
+ return (_jsx("div", { className: "fixed inset-0 bg-black/50 flex items-center justify-center z-50 p-4", children: _jsxs("div", { className: "bg-dashboard-bg rounded-3xl border border-dashboard-border w-full max-w-lg max-h-[80vh] overflow-hidden flex flex-col", children: [_jsxs("div", { className: "flex items-center justify-between p-6 border-b border-dashboard-border", children: [_jsx("h2", { className: "text-xl font-bold text-dashboard-text", children: "Domain Languages" }), _jsx("button", { onClick: onClose, className: "p-2 text-dashboard-text-secondary hover:text-dashboard-text transition-colors", children: _jsx(X, { size: 20 }) })] }), _jsxs("div", { className: "flex-1 overflow-y-auto p-6 space-y-4", children: [tempConfig.length > 0 && (_jsxs("div", { className: "space-y-2", children: [_jsx("p", { className: "text-xs font-bold text-dashboard-text-secondary uppercase tracking-wider", children: "Current Config" }), tempConfig.map((entry, index) => (_jsxs("div", { className: "bg-dashboard-card rounded-xl border border-dashboard-border overflow-hidden", children: [_jsxs("div", { onClick: () => toggleExpand(index), className: "w-full flex items-center justify-between p-3 text-left hover:bg-dashboard-border/50 transition-colors cursor-pointer", children: [_jsxs("div", { className: "flex items-center gap-2", children: [_jsx("span", { className: "font-medium text-dashboard-text", children: entry.domain || '(no domain)' }), _jsx("span", { className: "text-dashboard-text-secondary", children: "\u2192" }), _jsx("span", { children: AVAILABLE_LOCALES.find(l => l.code === entry.locale)?.flag }), entry.allowUserOverride === false && _jsx("span", { className: "text-dashboard-text-secondary", children: "\uD83D\uDD12" })] }), _jsxs("div", { className: "flex items-center gap-2", children: [_jsx("button", { onClick: (e) => { e.stopPropagation(); handleRemove(index); }, className: "p-1 text-red-500 hover:bg-red-500/10 rounded transition-colors", title: "Remove", children: _jsx(Trash2, { size: 14 }) }), _jsx("span", { className: "text-dashboard-text-secondary text-xs", children: expandedIndex === index ? '▲' : '▼' })] })] }), expandedIndex === index && (_jsxs("div", { className: "p-3 pt-0 space-y-3 border-t border-dashboard-border", children: [_jsxs("div", { className: "space-y-1", children: [_jsx("label", { className: "text-[10px] font-bold text-dashboard-text-secondary uppercase tracking-wider", children: "Domain" }), _jsx("input", { type: "text", value: entry.domain, onChange: (e) => handleUpdate(index, 'domain', e.target.value), placeholder: "example.com", className: "w-full px-3 py-2 bg-dashboard-bg border border-dashboard-border rounded-lg outline-none focus:ring-2 focus:ring-primary text-dashboard-text text-sm" })] }), _jsx("div", { className: "flex items-center gap-2", children: _jsxs("div", { className: "flex-1 space-y-1", children: [_jsx("label", { className: "text-[10px] font-bold text-dashboard-text-secondary uppercase tracking-wider", children: "Language" }), _jsx("select", { value: entry.locale, onChange: (e) => handleUpdate(index, 'locale', e.target.value), className: "w-full px-3 py-2 bg-dashboard-bg border border-dashboard-border rounded-lg outline-none focus:ring-2 focus:ring-primary text-dashboard-text text-sm", children: AVAILABLE_LOCALES.map(loc => (_jsxs("option", { value: loc.code, children: [loc.flag, " ", loc.name] }, loc.code))) })] }) }), _jsxs("div", { className: "flex items-center justify-between", children: [_jsx("label", { className: "text-[10px] text-dashboard-text-secondary", children: "Allow user to change" }), _jsx("button", { onClick: () => handleUpdate(index, 'allowUserOverride', !entry.allowUserOverride), className: `relative w-10 h-5 rounded-full transition-colors ${entry.allowUserOverride ? 'bg-primary' : 'bg-neutral-300 dark:bg-neutral-600'}`, children: _jsx("div", { className: `absolute top-0.5 left-0.5 w-4 h-4 bg-white rounded-full transition-transform duration-200 ${entry.allowUserOverride ? 'translate-x-5' : 'translate-x-0'}` }) })] })] }))] }, index)))] })), _jsxs("div", { className: "border-t border-dashboard-border pt-4", children: [_jsx("p", { className: "text-xs font-bold text-dashboard-text-secondary uppercase tracking-wider mb-3", children: "Add New Domain" }), _jsxs("button", { onClick: handleAdd, className: "w-full flex items-center justify-center gap-2 px-4 py-3 border-2 border-dashed border-dashboard-border text-dashboard-text-secondary hover:border-primary hover:text-primary rounded-xl transition-colors", children: [_jsx(Plus, { size: 16 }), "Add Domain"] })] }), _jsx("p", { className: "text-[10px] text-dashboard-text-secondary text-center pt-2", children: "Configure which language to use per domain. E.g., botanicsandyou.nl \u2192 Dutch, botanicsandyou.se \u2192 Swedish." })] }), _jsxs("div", { className: "flex gap-3 p-6 border-t border-dashboard-border", children: [_jsx("button", { onClick: onClose, className: "flex-1 px-4 py-2 bg-dashboard-card text-dashboard-text rounded-xl text-sm font-bold hover:bg-dashboard-border transition-colors", children: "Cancel" }), _jsx("button", { onClick: () => onSaveAndClose(tempConfig), disabled: isSaving, className: "flex-1 px-4 py-2 bg-primary text-white rounded-xl text-sm font-bold hover:bg-primary/90 transition-colors disabled:opacity-50", children: isSaving ? 'Saving...' : 'Save' })] })] }) }));
54
54
  }
55
55
  // =============================================================================
56
56
  // Main Component
@@ -225,6 +225,26 @@ export function SettingsView({ siteId, locale }) {
225
225
  setSettings({ ...settings, domainLocaleConfig: config });
226
226
  setShowDomainModal(false);
227
227
  };
228
+ const saveDomainConfigAndClose = async (config) => {
229
+ setSettings({ ...settings, domainLocaleConfig: config });
230
+ setShowDomainModal(false);
231
+ // Immediately save to API
232
+ try {
233
+ const response = await fetch('/api/plugin-website/settings', {
234
+ method: 'POST',
235
+ headers: { 'Content-Type': 'application/json' },
236
+ credentials: 'include',
237
+ body: JSON.stringify({ ...settings, domainLocaleConfig: config }),
238
+ });
239
+ if (response.ok) {
240
+ setShowSuccess(true);
241
+ setTimeout(() => setShowSuccess(false), 3000);
242
+ }
243
+ }
244
+ catch (error) {
245
+ console.error('Failed to save domain config:', error);
246
+ }
247
+ };
228
248
  if (isLoading) {
229
249
  return (_jsx("div", { className: "h-full w-full bg-dashboard-card text-dashboard-text flex items-center justify-center", children: _jsxs("div", { className: "text-center", children: [_jsx(RefreshCw, { className: "w-8 h-8 animate-spin text-primary mx-auto mb-4" }), _jsx("p", { className: "text-sm text-dashboard-text-secondary", children: "Loading settings..." })] }) }));
230
250
  }
@@ -246,5 +266,5 @@ export function SettingsView({ siteId, locale }) {
246
266
  const timeValue = e.target.value;
247
267
  const currentDate = settings.launch_date?.includes('T') ? settings.launch_date.split('T')[0] : new Date().toISOString().split('T')[0];
248
268
  setSettings(prev => ({ ...prev, launch_date: timeValue ? `${currentDate}T${timeValue}` : '' }));
249
- }, className: "w-full px-4 py-2 bg-dashboard-card border border-dashboard-border rounded-xl outline-none focus:ring-2 focus:ring-primary text-dashboard-text" })] }), _jsx("p", { className: "text-[10px] text-dashboard-text-secondary", children: "Used for countdown timers." })] })] }), _jsx(DomainLanguagesCard, { config: settings.domainLocaleConfig || [], onEdit: openDomainModal })] })] })] }), _jsx(DomainLanguagesModal, { isOpen: showDomainModal, config: settings.domainLocaleConfig || [], onSave: saveDomainConfig, onClose: closeDomainModal })] }));
269
+ }, className: "w-full px-4 py-2 bg-dashboard-card border border-dashboard-border rounded-xl outline-none focus:ring-2 focus:ring-primary text-dashboard-text" })] }), _jsx("p", { className: "text-[10px] text-dashboard-text-secondary", children: "Used for countdown timers." })] })] }), _jsx(DomainLanguagesCard, { config: settings.domainLocaleConfig || [], onEdit: openDomainModal })] })] })] }), _jsx(DomainLanguagesModal, { isOpen: showDomainModal, config: settings.domainLocaleConfig || [], onSave: saveDomainConfig, onSaveAndClose: saveDomainConfigAndClose, onClose: closeDomainModal, isSaving: isSaving })] }));
250
270
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@jhits/plugin-website",
3
- "version": "0.0.14",
3
+ "version": "0.0.16",
4
4
  "description": "Website management and configuration plugin for the JHITS ecosystem",
5
5
  "publishConfig": {
6
6
  "access": "public"
@@ -88,12 +88,6 @@ export async function POST_SETTINGS(
88
88
  }
89
89
 
90
90
  const body = await req.json();
91
- console.log('[WebsiteAPI] POST_SETTINGS received body:', {
92
- launch_date: body.launch_date,
93
- launch_date_type: typeof body.launch_date,
94
- has_launch_date: 'launch_date' in body,
95
- body_keys: Object.keys(body),
96
- });
97
91
 
98
92
  const dbConnection = await config.getDb();
99
93
  const db = dbConnection.db();
@@ -115,46 +109,24 @@ export async function POST_SETTINGS(
115
109
  if (launch_date !== undefined && launch_date !== null && launch_date !== '') {
116
110
  // Convert launch_date from datetime-local string to Date if provided
117
111
  const date = new Date(launch_date);
118
- console.log('[WebsiteAPI] Date conversion:', {
119
- input: launch_date,
120
- parsed: date,
121
- isValid: !isNaN(date.getTime()),
122
- iso: !isNaN(date.getTime()) ? date.toISOString() : 'invalid',
123
- });
124
112
 
125
113
  if (!isNaN(date.getTime())) {
126
114
  updateOps.$set.launch_date = date;
127
- console.log('[WebsiteAPI] Setting launch_date to:', date.toISOString());
128
115
  } else {
129
- console.warn('[WebsiteAPI] Invalid date, removing launch_date field');
130
116
  updateOps.$unset = { launch_date: '' };
131
117
  }
132
118
  } else {
133
119
  // Remove launch_date field if it's empty, undefined, or null
134
- console.log('[WebsiteAPI] launch_date is empty/undefined, removing field');
135
120
  updateOps.$unset = { launch_date: '' };
136
121
  }
137
122
 
138
- console.log('[WebsiteAPI] Update operations:', JSON.stringify(updateOps, (key, value) => {
139
- if (value instanceof Date) {
140
- return value.toISOString();
141
- }
142
- return value;
143
- }, 2));
144
-
145
123
  // Upsert settings
146
- const result = await settings.updateOne(
124
+ await settings.updateOne(
147
125
  { identifier: 'site_config' },
148
126
  updateOps,
149
127
  { upsert: true }
150
128
  );
151
129
 
152
- console.log('[WebsiteAPI] Update result:', {
153
- matchedCount: result.matchedCount,
154
- modifiedCount: result.modifiedCount,
155
- upsertedCount: result.upsertedCount,
156
- });
157
-
158
130
  return NextResponse.json({ success: true, message: 'Settings updated successfully' });
159
131
  } catch (error: any) {
160
132
  console.error('[WebsiteAPI] POST_SETTINGS error:', error);
@@ -164,4 +136,3 @@ export async function POST_SETTINGS(
164
136
  );
165
137
  }
166
138
  }
167
-
@@ -85,9 +85,11 @@ interface DomainLanguagesModalProps {
85
85
  config: DomainLocaleConfig[];
86
86
  onSave: (config: DomainLocaleConfig[]) => void;
87
87
  onClose: () => void;
88
+ onSaveAndClose: (config: DomainLocaleConfig[]) => void;
89
+ isSaving?: boolean;
88
90
  }
89
91
 
90
- function DomainLanguagesModal({ isOpen, config, onSave, onClose }: DomainLanguagesModalProps) {
92
+ function DomainLanguagesModal({ isOpen, config, onSave, onClose, onSaveAndClose, isSaving = false }: DomainLanguagesModalProps) {
91
93
  const [tempConfig, setTempConfig] = useState<DomainLocaleConfig[]>(config);
92
94
  const [expandedIndex, setExpandedIndex] = useState<number | null>(null);
93
95
 
@@ -217,8 +219,12 @@ function DomainLanguagesModal({ isOpen, config, onSave, onClose }: DomainLanguag
217
219
  <button onClick={onClose} className="flex-1 px-4 py-2 bg-dashboard-card text-dashboard-text rounded-xl text-sm font-bold hover:bg-dashboard-border transition-colors">
218
220
  Cancel
219
221
  </button>
220
- <button onClick={() => onSave(tempConfig)} className="flex-1 px-4 py-2 bg-primary text-white rounded-xl text-sm font-bold hover:bg-primary/90 transition-colors">
221
- Save
222
+ <button
223
+ onClick={() => onSaveAndClose(tempConfig)}
224
+ disabled={isSaving}
225
+ className="flex-1 px-4 py-2 bg-primary text-white rounded-xl text-sm font-bold hover:bg-primary/90 transition-colors disabled:opacity-50"
226
+ >
227
+ {isSaving ? 'Saving...' : 'Save'}
222
228
  </button>
223
229
  </div>
224
230
  </div>
@@ -408,6 +414,26 @@ export function SettingsView({ siteId, locale }: SettingsViewProps) {
408
414
  setSettings({ ...settings, domainLocaleConfig: config });
409
415
  setShowDomainModal(false);
410
416
  };
417
+ const saveDomainConfigAndClose = async (config: DomainLocaleConfig[]) => {
418
+ setSettings({ ...settings, domainLocaleConfig: config });
419
+ setShowDomainModal(false);
420
+
421
+ // Immediately save to API
422
+ try {
423
+ const response = await fetch('/api/plugin-website/settings', {
424
+ method: 'POST',
425
+ headers: { 'Content-Type': 'application/json' },
426
+ credentials: 'include',
427
+ body: JSON.stringify({ ...settings, domainLocaleConfig: config }),
428
+ });
429
+ if (response.ok) {
430
+ setShowSuccess(true);
431
+ setTimeout(() => setShowSuccess(false), 3000);
432
+ }
433
+ } catch (error) {
434
+ console.error('Failed to save domain config:', error);
435
+ }
436
+ };
411
437
 
412
438
  if (isLoading) {
413
439
  return (
@@ -693,7 +719,9 @@ export function SettingsView({ siteId, locale }: SettingsViewProps) {
693
719
  isOpen={showDomainModal}
694
720
  config={settings.domainLocaleConfig || []}
695
721
  onSave={saveDomainConfig}
722
+ onSaveAndClose={saveDomainConfigAndClose}
696
723
  onClose={closeDomainModal}
724
+ isSaving={isSaving}
697
725
  />
698
726
  </div>
699
727
  );