Skip to content

feat: ui: adding tenant meta management#147

Merged
schwannden merged 1 commit intomainfrom
feat/adding-tenant-meta-ui
Aug 5, 2025
Merged

feat: ui: adding tenant meta management#147
schwannden merged 1 commit intomainfrom
feat/adding-tenant-meta-ui

Conversation

@schwannden
Copy link
Copy Markdown
Owner

Purpose

Frontend implementation of tenant metadata UI components with comprehensive form handling, tooltip displays, verification badges, and testing for the multi-tenant chabod church management system.

Core Principles

  1. UX First: Clean, intuitive interface for church administrative information
  2. Form-Driven: React Hook Form + Zod validation following established patterns
  3. Accessible: Tooltips, badges, and proper ARIA labels
  4. Test-Driven: Comprehensive UI test coverage following existing patterns
  5. I18n Ready: Full internationalization support for English/Chinese

Goal

Add tenant metadata UI components to display and edit church administrative information with proper tooltips, verification badges, form validation, and comprehensive testing.

Why

  • User Experience: Churches need to view and edit administrative information (tax ID, contact details, verification status)
  • Information Architecture: Metadata contains many fields - need tooltip to avoid cluttering the card
  • Trust Indicators: Verification badge provides credibility signal
  • Data Integrity: Form validation ensures quality administrative data
  • Maintainability: Following established patterns ensures consistency

What

Frontend implementation of tenant metadata UI with:

  • Enhanced TenantCard with church info tooltip and verification badge
  • Extended TenantForm with all metadata fields (tax_id, contact_email, address, website, phone_number)
  • Proper form validation with meaningful error messages
  • Verification badge display with appropriate styling
  • Comprehensive UI testing coverage
  • Complete internationalization support

Copilot AI review requested due to automatic review settings August 5, 2025 04:47
Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull Request Overview

This PR implements a comprehensive frontend tenant metadata management system, enhancing church administrative information handling with verification badges, tooltips, and extended form fields. The implementation follows established patterns with React Hook Form, Zod validation, and comprehensive UI testing.

  • Enhanced TenantCard with church info tooltip and verification badge display
  • Extended TenantForm with metadata fields (tax_id, contact_email, address, website, phone_number) and validation
  • Added service layer functions for tenant metadata management

Reviewed Changes

Copilot reviewed 12 out of 12 changed files in this pull request and generated 4 comments.

Show a summary per file
File Description
src/components/Tenants/TenantCard.tsx Added verification badge and church info dialog integration
src/components/Tenants/TenantForm.tsx Complete rewrite with React Hook Form, Zod validation, and metadata fields
src/components/Tenants/TenantUpdateDialog.tsx Extended to handle metadata fields with proper service integration
src/components/Tenants/TenantCreateDialog.tsx Enhanced to create metadata alongside tenant creation
src/components/Tenants/ChurchInfoDialog.tsx New dialog component for displaying church metadata
src/lib/tenant-service.ts Added functions for metadata management
src/lib/types.ts Added TenantWithUsageAndMeta type definition
Translation files Added comprehensive metadata-related translations
Test files Extended UI tests for metadata display functionality
Comments suppressed due to low confidence (2)

tests/rls/tenant-meta.rls.test.ts:122

  • The variable '_error' suggests the error is intentionally unused, but the test doesn't verify the error state. Consider either removing the variable assignment or adding assertions about the expected error behavior.
        const { data, error: _error } = await member.client

src/components/Tenants/TenantUpdateDialog.tsx:102

  • [nitpick] The submitText uses t('updated') which translates to 'Tenant updated', but this should be an action verb like 'Update' or 'Save Changes' for a submit button.
          submitText={t("updated")}

/**
* Creates tenant metadata for new tenant
*/
export async function createTenantMetadata(
Copy link

Copilot AI Aug 5, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The function name is 'createTenantMetadata' but it uses 'update' operation instead of 'insert'. This will fail if no metadata record exists for the tenant. Either rename to 'updateTenantMetadata' or change to use 'upsert' operation.

Copilot uses AI. Check for mistakes.
Comment on lines +542 to +556
const infoButtons = screen.getAllByRole("button");
const churchInfoButton = infoButtons.find(
(button) =>
button.classList.contains("text-muted-foreground") && button.querySelector("svg"),
);

expect(churchInfoButton).toBeInTheDocument();

if (churchInfoButton) {
await user.click(churchInfoButton);

// After clicking, the dialog should be opened
// We can test this by checking if the dialog content appears
// Since the ChurchInfoDialog component will render its content
}
Copy link

Copilot AI Aug 5, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Using getAllByRole('button') and then filtering by CSS classes is fragile. Consider using more specific test selectors like data-testid or getByLabelText for better test reliability.

Suggested change
const infoButtons = screen.getAllByRole("button");
const churchInfoButton = infoButtons.find(
(button) =>
button.classList.contains("text-muted-foreground") && button.querySelector("svg"),
);
expect(churchInfoButton).toBeInTheDocument();
if (churchInfoButton) {
await user.click(churchInfoButton);
// After clicking, the dialog should be opened
// We can test this by checking if the dialog content appears
// Since the ChurchInfoDialog component will render its content
}
const churchInfoButton = screen.getByTestId("church-info-button");
expect(churchInfoButton).toBeInTheDocument();
await user.click(churchInfoButton);
// After clicking, the dialog should be opened
// We can test this by checking if the dialog content appears
// Since the ChurchInfoDialog component will render its content

Copilot uses AI. Check for mistakes.
</FormControl>
<FormMessage />
<p className="text-xs text-muted-foreground">
{t("name")}: /tenant/{field.value || "example"}
Copy link

Copilot AI Aug 5, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The help text shows '{t("name")}:' but should show 'URL:' or similar to indicate this is showing the URL format, not just repeating the field name.

Suggested change
{t("name")}: /tenant/{field.value || "example"}
URL: /tenant/{field.value || "example"}

Copilot uses AI. Check for mistakes.
Comment on lines +75 to +88
const watchName = form.watch("name");

// Auto-generate slug from name if enabled
if (autoGenerateSlug) {
const slugValue = watchName
.trim()
.toLowerCase()
.replace(/\s+/g, "-")
.replace(/[^a-z0-9-]/g, "");

if (slugValue !== form.getValues("slug")) {
form.setValue("slug", slugValue);
}
}
Copy link

Copilot AI Aug 5, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Using form.watch() inside the component body will cause re-renders on every keystroke. Consider moving the auto-slug generation logic inside useEffect or using a more efficient pattern.

Copilot uses AI. Check for mistakes.
@schwannden schwannden merged commit 3eba597 into main Aug 5, 2025
4 checks passed
@schwannden schwannden mentioned this pull request Aug 7, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants