Diff -- /var/www/vhosts/3dshawn.com/crm.3dshawn.com/preferences.cgi
Diff

/var/www/vhosts/3dshawn.com/crm.3dshawn.com/preferences.cgi

added on local at 2026-07-01 15:03:00

Added
+158
lines
Removed
-0
lines
Context
0
unchanged
Blobs
from
to a307a26d6ecb
Restore this content →
Unified diff
Naive LCS-based line diff. Additions in emerald, deletions in rose. Both sides decompressed live from BLOB_STORE.
1#!/usr/bin/perl
2#======================================================================
3# ContactForge - Preferences (notifications + UI prefs)
4#
5# URL: /preferences.cgi
6#
7# Owns the "how I want the app to behave" half of what used to live
8# under /settings.cgi:
9# - email notification toggles (sale alerts, platform health,
10# review digest, A/B winners, weekly summary, marketing)
11#
12# Account identity (name/email/timezone/currency, 2FA, sessions,
13# entitlements, team) lives in /profile.cgi.
14#======================================================================
15use strict;
16use warnings;
17
18use lib '/var/www/vhosts/3dshawn.com/crm.3dshawn.com';
19use CGI;
20use MODS::Template;
21use MODS::DBConnect;
22use MODS::Login;
23use MODS::ContactForge::Config;
24use MODS::ContactForge::Wrapper;
25
26my $q = CGI->new;
27my $form = $q->Vars;
28my $auth = MODS::Login->new;
29my $wrap = MODS::ContactForge::Wrapper->new;
30my $tfile = MODS::Template->new;
31my $db = MODS::DBConnect->new;
32my $cfg = MODS::ContactForge::Config->new;
33my $DB = $cfg->settings('database_name');
34
35$|=1;
36my $userinfo = $auth->login_verify();
37if (!$userinfo) {
38 print "Status: 302 Found\nLocation: /login.cgi\n\n";
39 exit;
40}
41my $uid = $userinfo->{user_id};
42$uid =~ s/[^0-9]//g;
43
44my $dbh = $db->db_connect();
45
46# Notification preference schema (mirrored to JSON in
47# user_settings.notification_prefs). Adding a new key here costs nothing
48# since the column is LONGTEXT JSON.
49my @NOTIF_KEYS = qw(
50 sale_alerts
51 platform_health
52 review_digest
53 ab_winners
54 weekly_summary
55 marketing
56);
57my %NOTIF_DEFAULT = (
58 sale_alerts => 1,
59 platform_health => 1,
60 review_digest => 1,
61 ab_winners => 1,
62 weekly_summary => 1,
63 marketing => 0,
64);
65
66sub _esc {
67 my $s = shift;
68 $s //= '';
69 $s =~ s/\\/\\\\/g;
70 $s =~ s/'/''/g;
71 return $s;
72}
73
74sub _parse_notif_json {
75 my ($raw) = @_;
76 my %out = %NOTIF_DEFAULT;
77 return \%out unless $raw && $raw =~ /\S/;
78 foreach my $k (@NOTIF_KEYS) {
79 if ($raw =~ /"\Q$k\E"\s*:\s*(true|false|0|1)/i) {
80 my $v = lc $1;
81 $out{$k} = ($v eq 'true' || $v eq '1') ? 1 : 0;
82 }
83 }
84 return \%out;
85}
86
87sub _build_notif_json {
88 my ($prefs) = @_;
89 my @parts;
90 foreach my $k (@NOTIF_KEYS) {
91 my $v = $prefs->{$k} ? 1 : 0;
92 push @parts, qq{"$k":$v};
93 }
94 return '{' . join(',', @parts) . '}';
95}
96
97# ---- POST handler ---------------------------------------------------
98my $saved_msg = '';
99if (($form->{action} || '') eq 'save_notifications') {
100 my %prefs;
101 foreach my $k (@NOTIF_KEYS) {
102 $prefs{$k} = ($form->{"notif_$k"} ? 1 : 0);
103 }
104 my $json = _build_notif_json(\%prefs);
105
106 $db->db_readwrite($dbh, qq~
107 INSERT INTO `${DB}`.user_settings
108 SET user_id='$uid',
109 notification_prefs='~ . _esc($json) . qq~',
110 marketing_opt_in='~ . ($prefs{marketing} ? 1 : 0) . qq~'
111 ON DUPLICATE KEY UPDATE
112 notification_prefs=VALUES(notification_prefs),
113 marketing_opt_in=VALUES(marketing_opt_in)
114 ~, $ENV{SCRIPT_NAME}, __LINE__);
115 $saved_msg = 'Notification preferences saved.';
116}
117
118# ---- Load current state ---------------------------------------------
119my $s = $db->db_readwrite($dbh, qq~
120 SELECT notification_prefs, marketing_opt_in
121 FROM `${DB}`.user_settings
122 WHERE user_id='$uid'
123~, $ENV{SCRIPT_NAME}, __LINE__) || {};
124my $prefs = _parse_notif_json($s->{notification_prefs});
125$prefs->{marketing} = $s->{marketing_opt_in} ? 1 : 0 if exists $s->{marketing_opt_in};
126
127$db->db_disconnect($dbh);
128
129my $tvars = {
130 user_id => $uid,
131 saved_msg => $saved_msg,
132 has_saved_msg => $saved_msg ? 1 : 0,
133
134 notif_sale_alerts_on => $prefs->{sale_alerts} ? 'on' : '',
135 notif_platform_health_on => $prefs->{platform_health} ? 'on' : '',
136 notif_review_digest_on => $prefs->{review_digest} ? 'on' : '',
137 notif_ab_winners_on => $prefs->{ab_winners} ? 'on' : '',
138 notif_weekly_summary_on => $prefs->{weekly_summary} ? 'on' : '',
139 notif_marketing_on => $prefs->{marketing} ? 'on' : '',
140
141 notif_sale_alerts_checked => $prefs->{sale_alerts} ? 'checked' : '',
142 notif_platform_health_checked => $prefs->{platform_health} ? 'checked' : '',
143 notif_review_digest_checked => $prefs->{review_digest} ? 'checked' : '',
144 notif_ab_winners_checked => $prefs->{ab_winners} ? 'checked' : '',
145 notif_weekly_summary_checked => $prefs->{weekly_summary} ? 'checked' : '',
146 notif_marketing_checked => $prefs->{marketing} ? 'checked' : '',
147};
148
149print "Content-Type: text/html; charset=utf-8\nCache-Control: no-store, no-cache, must-revalidate, max-age=0\nPragma: no-cache\nExpires: 0\n\n";
150
151my $body = join('', $tfile->template('cf_preferences.html', $tvars, $userinfo));
152
153$wrap->render({
154 userinfo => $userinfo,
155 page_key => 'preferences',
156 title => 'Preferences',
157 body => $body,
158});
Keyboard: j next diff k previous diff g top G bottom r restore c compile-check ? help