Split address into 3 fields
Inför tre separata fält för leveransadress (street_address, postal_code, city) i profil, uppdatera migrering, typ-definitioner, fetch och spara logik samt UI med tre inputs. Implementerade ny migrations, utökade API-samtal och uppdaterade Account-sidan att hantera de nya fälten. X-Lovable-Edit-ID: edt-bcc30255-fbe9-4cbc-bbe4-9513937b286d
This commit is contained in:
@@ -17,31 +17,40 @@ export type Database = {
|
|||||||
profiles: {
|
profiles: {
|
||||||
Row: {
|
Row: {
|
||||||
address: string | null
|
address: string | null
|
||||||
|
city: string | null
|
||||||
company_name: string | null
|
company_name: string | null
|
||||||
created_at: string
|
created_at: string
|
||||||
display_name: string | null
|
display_name: string | null
|
||||||
id: string
|
id: string
|
||||||
phone: string | null
|
phone: string | null
|
||||||
|
postal_code: string | null
|
||||||
|
street_address: string | null
|
||||||
updated_at: string
|
updated_at: string
|
||||||
user_id: string
|
user_id: string
|
||||||
}
|
}
|
||||||
Insert: {
|
Insert: {
|
||||||
address?: string | null
|
address?: string | null
|
||||||
|
city?: string | null
|
||||||
company_name?: string | null
|
company_name?: string | null
|
||||||
created_at?: string
|
created_at?: string
|
||||||
display_name?: string | null
|
display_name?: string | null
|
||||||
id?: string
|
id?: string
|
||||||
phone?: string | null
|
phone?: string | null
|
||||||
|
postal_code?: string | null
|
||||||
|
street_address?: string | null
|
||||||
updated_at?: string
|
updated_at?: string
|
||||||
user_id: string
|
user_id: string
|
||||||
}
|
}
|
||||||
Update: {
|
Update: {
|
||||||
address?: string | null
|
address?: string | null
|
||||||
|
city?: string | null
|
||||||
company_name?: string | null
|
company_name?: string | null
|
||||||
created_at?: string
|
created_at?: string
|
||||||
display_name?: string | null
|
display_name?: string | null
|
||||||
id?: string
|
id?: string
|
||||||
phone?: string | null
|
phone?: string | null
|
||||||
|
postal_code?: string | null
|
||||||
|
street_address?: string | null
|
||||||
updated_at?: string
|
updated_at?: string
|
||||||
user_id?: string
|
user_id?: string
|
||||||
}
|
}
|
||||||
|
|||||||
+57
-19
@@ -4,24 +4,29 @@ import { z } from "zod";
|
|||||||
import { Button } from "@/components/ui/button";
|
import { Button } from "@/components/ui/button";
|
||||||
import { Input } from "@/components/ui/input";
|
import { Input } from "@/components/ui/input";
|
||||||
import { Label } from "@/components/ui/label";
|
import { Label } from "@/components/ui/label";
|
||||||
import { Textarea } from "@/components/ui/textarea";
|
|
||||||
import { useAuth } from "@/hooks/useAuth";
|
import { useAuth } from "@/hooks/useAuth";
|
||||||
import { useToast } from "@/hooks/use-toast";
|
import { useToast } from "@/hooks/use-toast";
|
||||||
import { supabase } from "@/integrations/supabase/client";
|
import { supabase } from "@/integrations/supabase/client";
|
||||||
import Header from "@/components/Header";
|
import Header from "@/components/Header";
|
||||||
import { LogOut, Save } from "lucide-react";
|
import { Save } from "lucide-react";
|
||||||
|
|
||||||
const profileSchema = z.object({
|
const profileSchema = z.object({
|
||||||
address: z.string().trim().max(500, { message: "Adress får max vara 500 tecken" }).optional(),
|
street_address: z.string().trim().max(200, { message: "Gatuadress får max vara 200 tecken" }).optional(),
|
||||||
|
postal_code: z.string().trim().max(10, { message: "Postnummer får max vara 10 tecken" }).optional(),
|
||||||
|
city: z.string().trim().max(100, { message: "Ort får max vara 100 tecken" }).optional(),
|
||||||
});
|
});
|
||||||
|
|
||||||
interface ProfileData {
|
interface ProfileData {
|
||||||
address: string;
|
street_address: string;
|
||||||
|
postal_code: string;
|
||||||
|
city: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
const Account = () => {
|
const Account = () => {
|
||||||
const [profile, setProfile] = useState<ProfileData>({
|
const [profile, setProfile] = useState<ProfileData>({
|
||||||
address: "",
|
street_address: "",
|
||||||
|
postal_code: "",
|
||||||
|
city: "",
|
||||||
});
|
});
|
||||||
const [isLoading, setIsLoading] = useState(true);
|
const [isLoading, setIsLoading] = useState(true);
|
||||||
const [isSaving, setIsSaving] = useState(false);
|
const [isSaving, setIsSaving] = useState(false);
|
||||||
@@ -44,7 +49,7 @@ const Account = () => {
|
|||||||
try {
|
try {
|
||||||
const { data, error } = await supabase
|
const { data, error } = await supabase
|
||||||
.from("profiles")
|
.from("profiles")
|
||||||
.select("address")
|
.select("street_address, postal_code, city")
|
||||||
.eq("user_id", user!.id)
|
.eq("user_id", user!.id)
|
||||||
.maybeSingle();
|
.maybeSingle();
|
||||||
|
|
||||||
@@ -57,7 +62,9 @@ const Account = () => {
|
|||||||
});
|
});
|
||||||
} else if (data) {
|
} else if (data) {
|
||||||
setProfile({
|
setProfile({
|
||||||
address: data.address || "",
|
street_address: data.street_address || "",
|
||||||
|
postal_code: data.postal_code || "",
|
||||||
|
city: data.city || "",
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
} finally {
|
} finally {
|
||||||
@@ -84,7 +91,9 @@ const Account = () => {
|
|||||||
const { error } = await supabase
|
const { error } = await supabase
|
||||||
.from("profiles")
|
.from("profiles")
|
||||||
.update({
|
.update({
|
||||||
address: profile.address || null,
|
street_address: profile.street_address || null,
|
||||||
|
postal_code: profile.postal_code || null,
|
||||||
|
city: profile.city || null,
|
||||||
})
|
})
|
||||||
.eq("user_id", user!.id);
|
.eq("user_id", user!.id);
|
||||||
|
|
||||||
@@ -159,17 +168,46 @@ const Account = () => {
|
|||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="space-y-2">
|
<div className="space-y-4">
|
||||||
<Label htmlFor="address">Leveransadress</Label>
|
<Label>Leveransadress</Label>
|
||||||
<Textarea
|
|
||||||
id="address"
|
<div className="space-y-2">
|
||||||
value={profile.address}
|
<Input
|
||||||
onChange={(e) =>
|
id="street_address"
|
||||||
setProfile({ ...profile, address: e.target.value })
|
type="text"
|
||||||
}
|
value={profile.street_address}
|
||||||
placeholder="Gatuadress, postnummer, ort"
|
onChange={(e) =>
|
||||||
rows={3}
|
setProfile({ ...profile, street_address: e.target.value })
|
||||||
/>
|
}
|
||||||
|
placeholder="Gatuadress"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="grid grid-cols-2 gap-4">
|
||||||
|
<div className="space-y-2">
|
||||||
|
<Input
|
||||||
|
id="postal_code"
|
||||||
|
type="text"
|
||||||
|
value={profile.postal_code}
|
||||||
|
onChange={(e) =>
|
||||||
|
setProfile({ ...profile, postal_code: e.target.value })
|
||||||
|
}
|
||||||
|
placeholder="Postnummer"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div className="space-y-2">
|
||||||
|
<Input
|
||||||
|
id="city"
|
||||||
|
type="text"
|
||||||
|
value={profile.city}
|
||||||
|
onChange={(e) =>
|
||||||
|
setProfile({ ...profile, city: e.target.value })
|
||||||
|
}
|
||||||
|
placeholder="Ort"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
<p className="text-xs text-muted-foreground">
|
<p className="text-xs text-muted-foreground">
|
||||||
Denna adress används vid beställning av abonnemang.
|
Denna adress används vid beställning av abonnemang.
|
||||||
</p>
|
</p>
|
||||||
|
|||||||
@@ -0,0 +1,5 @@
|
|||||||
|
-- Add separate address fields to profiles table
|
||||||
|
ALTER TABLE public.profiles
|
||||||
|
ADD COLUMN street_address text,
|
||||||
|
ADD COLUMN postal_code text,
|
||||||
|
ADD COLUMN city text;
|
||||||
Reference in New Issue
Block a user