Add MinIO storage + replace Supabase Storage with S3 SDK

- New: src/lib/storage.ts — S3-compatible client, uploadFile/deleteFile/listFiles/publicUrl helpers, bucket constants
- New: docker-compose adds minio + minio_init services
- Replaced Supabase fetch PUTs in:
  - src/actions/brand-settings.ts (3 uploaders)
  - src/actions/products/upload-image.ts
  - src/actions/communications/import-contacts.ts
  - src/app/api/water-photo-upload/route.ts
- Replaced hardcoded Supabase URLs in:
  - src/components/storefront/TuxedoVideoHero.tsx
  - src/components/time-tracking/TimeTrackingFieldClient.tsx
  - src/app/tuxedo/about/page.tsx
  - src/lib/email-service.ts (4 occurrences)
- Added @aws-sdk/client-s3 + @aws-sdk/s3-request-presigner
- .env.example adds MinIO + storage vars
- Migration cleanup: deleted BUNDLE_018_042, 4 XXX drafts, 087/145/099-contact storage migrations
- Migration patches: 006 STATIC→STABLE, 135 param reordering
- Preflight: added pgcrypto extension, removed storage stub
- Verified: MinIO upload/list/delete round-trip works against local instance
This commit is contained in:
2026-06-05 02:33:05 +00:00
parent 66d8cdf9b2
commit c20538ef9f
42 changed files with 973 additions and 5608 deletions
+12 -11
View File
@@ -2,9 +2,10 @@
import { useState } from "react";
import Link from "next/link";
import { supabase } from "@/lib/supabase";
import { authClient } from "@/lib/auth-client";
import { AdminUserRow } from "@/actions/admin/users";
import { logUserActivity } from "@/actions/admin/audit";
import { updateAdminProfileAction } from "@/actions/admin/profile";
type ProfilePageProps = {
currentUser: AdminUserRow;
@@ -26,13 +27,13 @@ export default function AdminMeClient({ currentUser }: ProfilePageProps) {
setSaving(true);
setError(null);
try {
const { error: rpcError } = await supabase.rpc("update_admin_user", {
p_id: currentUser.id,
p_display_name: displayName || null,
p_phone_number: phoneNumber || null,
});
if (rpcError) {
setError(rpcError.message);
const result = await updateAdminProfileAction(
currentUser.id,
displayName || null,
phoneNumber || null
);
if (!result.success) {
setError(result.error);
return;
}
await logUserActivity({
@@ -51,11 +52,11 @@ export default function AdminMeClient({ currentUser }: ProfilePageProps) {
setChangingEmail(true);
setEmailError(null);
try {
const { error: updateError } = await supabase.auth.updateUser({
email: newEmail,
const { error: updateError } = await authClient.changeEmail({
newEmail: newEmail,
});
if (updateError) {
setEmailError(updateError.message);
setEmailError(updateError.message ?? "Failed to change email");
return;
}
await logUserActivity({