New resposne wall coding started.

This commit is contained in:
2025-10-10 22:11:20 -06:00
parent 8976a143ed
commit ac54d998c8
21 changed files with 7172 additions and 36 deletions

View File

@@ -26,7 +26,9 @@ class NocoDBService {
campaigns: process.env.NOCODB_TABLE_CAMPAIGNS,
campaignEmails: process.env.NOCODB_TABLE_CAMPAIGN_EMAILS,
users: process.env.NOCODB_TABLE_USERS,
calls: process.env.NOCODB_TABLE_CALLS
calls: process.env.NOCODB_TABLE_CALLS,
representativeResponses: process.env.NOCODB_TABLE_REPRESENTATIVE_RESPONSES,
responseUpvotes: process.env.NOCODB_TABLE_RESPONSE_UPVOTES
};
// Validate that all table IDs are set
@@ -688,6 +690,191 @@ class NocoDBService {
return await this.getAll(this.tableIds.users, params);
}
// Representative Responses methods
async getRepresentativeResponses(params = {}) {
if (!this.tableIds.representativeResponses) {
throw new Error('Representative responses table not configured');
}
console.log('getRepresentativeResponses params:', JSON.stringify(params, null, 2));
const result = await this.getAll(this.tableIds.representativeResponses, params);
// Log without the where clause to see ALL responses
if (params.where) {
const allResult = await this.getAll(this.tableIds.representativeResponses, {});
console.log(`Total responses in DB (no filter): ${allResult.list?.length || 0}`);
if (allResult.list && allResult.list.length > 0) {
console.log('Sample raw response from DB:', JSON.stringify(allResult.list[0], null, 2));
}
}
console.log('getRepresentativeResponses raw result:', JSON.stringify(result, null, 2));
// NocoDB returns {list: [...]} or {pageInfo: {...}, list: [...]}
const list = result.list || [];
console.log(`getRepresentativeResponses: Found ${list.length} responses`);
return list.map(item => this.normalizeResponse(item));
}
async getRepresentativeResponseById(responseId) {
if (!this.tableIds.representativeResponses) {
throw new Error('Representative responses table not configured');
}
try {
const url = `${this.getTableUrl(this.tableIds.representativeResponses)}/${responseId}`;
const response = await this.client.get(url);
return this.normalizeResponse(response.data);
} catch (error) {
console.error('Error getting representative response by ID:', error);
throw error;
}
}
async createRepresentativeResponse(responseData) {
if (!this.tableIds.representativeResponses) {
throw new Error('Representative responses table not configured');
}
// Ensure campaign_id is not null/undefined
if (!responseData.campaign_id) {
throw new Error('Campaign ID is required for creating a response');
}
const data = {
'Campaign ID': responseData.campaign_id,
'Campaign Slug': responseData.campaign_slug,
'Representative Name': responseData.representative_name,
'Representative Title': responseData.representative_title,
'Representative Level': responseData.representative_level,
'Response Type': responseData.response_type,
'Response Text': responseData.response_text,
'User Comment': responseData.user_comment,
'Screenshot URL': responseData.screenshot_url,
'Submitted By Name': responseData.submitted_by_name,
'Submitted By Email': responseData.submitted_by_email,
'Submitted By User ID': responseData.submitted_by_user_id,
'Is Anonymous': responseData.is_anonymous,
'Status': responseData.status,
'Is Verified': responseData.is_verified,
'Upvote Count': responseData.upvote_count,
'Submitted IP': responseData.submitted_ip
};
console.log('Creating response with data:', JSON.stringify(data, null, 2));
const url = this.getTableUrl(this.tableIds.representativeResponses);
const response = await this.client.post(url, data);
return this.normalizeResponse(response.data);
}
async updateRepresentativeResponse(responseId, updates) {
if (!this.tableIds.representativeResponses) {
throw new Error('Representative responses table not configured');
}
const data = {};
if (updates.status !== undefined) data['Status'] = updates.status;
if (updates.is_verified !== undefined) data['Is Verified'] = updates.is_verified;
if (updates.upvote_count !== undefined) data['Upvote Count'] = updates.upvote_count;
if (updates.response_text !== undefined) data['Response Text'] = updates.response_text;
if (updates.user_comment !== undefined) data['User Comment'] = updates.user_comment;
console.log(`Updating response ${responseId} with data:`, JSON.stringify(data, null, 2));
const url = `${this.getTableUrl(this.tableIds.representativeResponses)}/${responseId}`;
const response = await this.client.patch(url, data);
console.log('NocoDB update response:', JSON.stringify(response.data, null, 2));
return this.normalizeResponse(response.data);
}
async deleteRepresentativeResponse(responseId) {
if (!this.tableIds.representativeResponses) {
throw new Error('Representative responses table not configured');
}
const url = `${this.getTableUrl(this.tableIds.representativeResponses)}/${responseId}`;
const response = await this.client.delete(url);
return response.data;
}
// Response Upvotes methods
async getResponseUpvotes(params = {}) {
if (!this.tableIds.responseUpvotes) {
throw new Error('Response upvotes table not configured');
}
const result = await this.getAll(this.tableIds.responseUpvotes, params);
// NocoDB returns {list: [...]} or {pageInfo: {...}, list: [...]}
const list = result.list || [];
return list.map(item => this.normalizeUpvote(item));
}
async createResponseUpvote(upvoteData) {
if (!this.tableIds.responseUpvotes) {
throw new Error('Response upvotes table not configured');
}
const data = {
'Response ID': upvoteData.response_id,
'User ID': upvoteData.user_id,
'User Email': upvoteData.user_email,
'Upvoted IP': upvoteData.upvoted_ip
};
const url = this.getTableUrl(this.tableIds.responseUpvotes);
const response = await this.client.post(url, data);
return this.normalizeUpvote(response.data);
}
async deleteResponseUpvote(upvoteId) {
if (!this.tableIds.responseUpvotes) {
throw new Error('Response upvotes table not configured');
}
const url = `${this.getTableUrl(this.tableIds.responseUpvotes)}/${upvoteId}`;
const response = await this.client.delete(url);
return response.data;
}
// Normalize response data from NocoDB format to application format
normalizeResponse(data) {
if (!data) return null;
return {
id: data.ID || data.Id || data.id,
campaign_id: data['Campaign ID'] || data.campaign_id,
campaign_slug: data['Campaign Slug'] || data.campaign_slug,
representative_name: data['Representative Name'] || data.representative_name,
representative_title: data['Representative Title'] || data.representative_title,
representative_level: data['Representative Level'] || data.representative_level,
response_type: data['Response Type'] || data.response_type,
response_text: data['Response Text'] || data.response_text,
user_comment: data['User Comment'] || data.user_comment,
screenshot_url: data['Screenshot URL'] || data.screenshot_url,
submitted_by_name: data['Submitted By Name'] || data.submitted_by_name,
submitted_by_email: data['Submitted By Email'] || data.submitted_by_email,
submitted_by_user_id: data['Submitted By User ID'] || data.submitted_by_user_id,
is_anonymous: data['Is Anonymous'] || data.is_anonymous || false,
status: data['Status'] || data.status,
is_verified: data['Is Verified'] || data.is_verified || false,
upvote_count: data['Upvote Count'] || data.upvote_count || 0,
submitted_ip: data['Submitted IP'] || data.submitted_ip,
created_at: data.CreatedAt || data.created_at,
updated_at: data.UpdatedAt || data.updated_at
};
}
// Normalize upvote data from NocoDB format to application format
normalizeUpvote(data) {
if (!data) return null;
return {
id: data.ID || data.Id || data.id,
response_id: data['Response ID'] || data.response_id,
user_id: data['User ID'] || data.user_id,
user_email: data['User Email'] || data.user_email,
upvoted_ip: data['Upvoted IP'] || data.upvoted_ip,
created_at: data.CreatedAt || data.created_at
};
}
}
module.exports = new NocoDBService();
module.exports = new NocoDBService();