PHP 7.4.33
Preview: gravity-form.ts Size: 7.24 KB
/var/www/nea-dev-frontend.wpress.dk/httpdocs/src/utils/gravity-form.ts

export const getGravityAuthHeader = () => {
  const consumerKey = process.env.GF_ACCESS_KEY;
  const consumerSecret = process.env.GF_ACCESS_SECRET;
  if (!consumerKey || !consumerSecret) {
    throw new Error(
      'GF_ACCESS_KEY and GF_ACCESS_SECRET must be set in .env.local for Gravity Forms API authentication.'
    );
  }
  const auth = Buffer.from(`${consumerKey}:${consumerSecret}`).toString('base64');
  return auth;
};

export const getGravityBaseUrl = () => {
  const baseUrl = process.env.GRAVITY_FORMS_BASE_URL;
  if (!baseUrl) {
    throw new Error(
      'GRAVITY_FORMS_BASE_URL is not set. Add it to your .env.local (e.g. GRAVITY_FORMS_BASE_URL=https://your-wordpress-site.com) and restart the dev server.'
    );
  }
  return `${baseUrl}/wp-json/gf/v2`;
};

export type GravityFormData = {
  fields: any[];
  button?: {
    text?: string;
    layoutGridColumnSpan?: string;
  };
  [key: string]: unknown;
};

export async function fetchFormFields(
  formId: string,
): Promise<{ data: GravityFormData | null; error: string | null }> {
  try {
    if (!formId) {
      throw new Error('Form ID is required');
    }
    const url = getGravityBaseUrl();
    const form_url = `${url}/forms/${formId}`;
    const auth = getGravityAuthHeader();
    const revalidateTime = process.env.NODE_ENV === 'development' ? 0 : 36000;

    const response = await fetch(form_url, {
      method: 'GET',
      headers: {
        Authorization: `Basic ${auth}`,
        'Content-Type': 'application/json',
      },
      next: {
        revalidate: revalidateTime,
        tags: ['global', 'form', `form-${formId}`],
      },
    });

    if (!response.ok) {
      const error = await response.json().catch(() => ({}));
      throw new Error(error.message || `Failed to fetch fields: ${response.status}`);
    }

    const data = await response.json();

    if (!data.fields) {
      throw new Error('No fields found in response');
    }

    return {
      data: {
        fields: data.fields || [],
        button: data.button || null,
        ...data,
      },
      error: null,
    };
  } catch (error) {
    console.error('Error fetching form fields:', error);
    return {
      data: null,
      error: error instanceof Error ? error.message : 'Failed to fetch form fields',
    };
  }
}

type ConditionalRule = {
  fieldId: string;
  operator: string;
  value: string;
}
export const evaluateConditionalLogic = (field: any, fieldValues: any): boolean => {
  if (!field.conditionalLogic || !field.conditionalLogic.enabled) {
    return true;
  }

  const { actionType, logicType, rules } = field.conditionalLogic;

  const ruleResults = rules.map((rule: ConditionalRule) => {
    const fieldValue = fieldValues[rule.fieldId];
    // console.log("fieldValue", fieldValue);
    // console.log("rule", rule);
    const isEmpty =
      fieldValue === undefined ||
      fieldValue === null ||
      fieldValue === '' ||
      (Array.isArray(fieldValue) && fieldValue.length === 0);

    if (rule.value === '') {
      if (rule.operator === 'is') {
        return isEmpty;
      }
      if (rule.operator === 'isnot') {
        return !isEmpty;
      }
    }

    // Skip further evaluation if the field is empty and we're not explicitly checking for emptiness
    if (isEmpty && rule.value !== '') {
      // When field is empty, only "is empty" should be true, all other conditions are false
      return false;
    }

    switch (rule.operator) {
      case 'is':
        if (Array.isArray(fieldValue)) {
          return fieldValue.includes(rule.value);
        }

        if (fieldValue == "true") {
          return "1" === rule.value
        };
        return fieldValue === rule.value;
      case 'isnot':
        if (Array.isArray(fieldValue)) {
          return !fieldValue.includes(rule.value);
        }
        if (fieldValue == "false") {
          return "1" !== rule.value
        };
        return fieldValue !== rule.value;

      case 'contains':
        return typeof fieldValue === 'string' && fieldValue.includes(rule.value);
      case 'greater_than':
        return Number(fieldValue) > Number(rule.value);
      case 'less_than':
        return Number(fieldValue) < Number(rule.value);
      case 'starts_with':
        return typeof fieldValue === 'string' && fieldValue.startsWith(rule.value);
      case 'ends_with':
        return typeof fieldValue === 'string' && fieldValue.endsWith(rule.value);
      default:
        return false;
    }
  });

  let shouldShow: boolean;

  if (logicType === 'all') {
    shouldShow = ruleResults.every((result: any) => result);
  } else {
    shouldShow = ruleResults.some((result: any) => result);
  }

  // Invert the result if the action type is 'hide'
  return actionType === 'show' ? shouldShow : !shouldShow;
};


// Helper function to determine file type based on extension
// utils/fileUtils.ts

// Core MIME type mapper
function getMimeTypeByExtension(ext: string): string {
  ext = ext.trim().toLowerCase();
  if (!ext.startsWith('.')) ext = '.' + ext;

  switch (ext) {
    case '.pdf': return 'application/pdf';
    case '.doc': return 'application/msword';
    case '.docx': return 'application/vnd.openxmlformats-officedocument.wordprocessingml.document';
    case '.odt': return 'application/vnd.oasis.opendocument.text';
    case '.rtf': return 'application/rtf';
    case '.txt': return 'text/plain';
    case '.csv': return 'text/csv';
    case '.tsv': return 'text/tab-separated-values';
    case '.xls': return 'application/vnd.ms-excel';
    case '.xlsx': return 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet';
    case '.ods': return 'application/vnd.oasis.opendocument.spreadsheet';
    case '.ppt': return 'application/vnd.ms-powerpoint';
    case '.pptx': return 'application/vnd.openxmlformats-officedocument.presentationml.presentation';
    case '.odp': return 'application/vnd.oasis.opendocument.presentation';
    case '.jpg': return 'image/jpg';
    case '.jpeg': return 'image/jpeg';
    case '.png': return 'image/png';
    case '.gif': return 'image/gif';
    case '.bmp': return 'image/bmp';
    case '.tiff':
    case '.tif': return 'image/tiff';
    case '.svg': return 'image/svg+xml';
    case '.webp': return 'image/webp';
    case '.ico': return 'image/x-icon';
    case '.mp3': return 'audio/mpeg';
    case '.wav': return 'audio/wav';
    case '.ogg': return 'audio/ogg';
    case '.mp4': return 'video/mp4';
    case '.mov': return 'video/quicktime';
    case '.avi': return 'video/x-msvideo';
    case '.wmv': return 'video/x-ms-wmv';
    case '.mkv': return 'video/x-matroska';
    case '.zip': return 'application/zip';
    case '.rar': return 'application/vnd.rar';
    case '.7z': return 'application/x-7z-compressed';
    case '.tar': return 'application/x-tar';
    case '.gz': return 'application/gzip';
    case '.json': return 'application/json';
    case '.xml': return 'application/xml';
    case '.html':
    case '.htm': return 'text/html';
    case '.md': return 'text/markdown';
    default: return ext; // fallback: return original ext as `.ext` string
  }
}


// Exposed function: accepts filename or extension (your original version)
export function getFileType(filename: string = "", extension: string = ""): string {
  let ext = extension ? extension : (filename.includes('.') ? filename.split('.').pop() || '' : '');
  return getMimeTypeByExtension(ext);
}

Directory Contents

Dirs: 0 × Files: 2
Name Size Perms Modified Actions
7.24 KB lrw-r--r-- 2026-02-04 15:35:15
Edit Download
3.85 KB lrw-r--r-- 2025-08-12 08:52:38
Edit Download
If ZipArchive is unavailable, a .tar will be created (no compression).