fix markdown editor css and change mobile bottom nav menu

tst2
suvodip ghosh 2025-06-16 15:42:05 +00:00
parent 22fade091d
commit f6857712a8
9 changed files with 1632 additions and 187 deletions

File diff suppressed because it is too large Load Diff

View File

@ -14,21 +14,24 @@ export default function NewKubernetesService() {
const [isFetchingData, setIsFetchingData] = useState(true); const [isFetchingData, setIsFetchingData] = useState(true);
const [plans, setPlans] = useState([]); const [plans, setPlans] = useState([]);
const [vpcs, setVpcs] = useState([]); const [vpcs, setVpcs] = useState([]);
const [subnets, setSubnets] = useState([]);
const UTHO_API_KEY = "Bearer IoNXhkRJsQPyOEqFMceSfzuKaDLrpxUCATgZjiVdvYlBHbwWmGtn"; const UTHO_API_KEY = "Bearer IoNXhkRJsQPyOEqFMceSfzuKaDLrpxUCATgZjiVdvYlBHbwWmGtn";
const [formData, setFormData] = useState({ const [formData, setFormData] = useState({
datacenter: "mumbai", dcslug: "innoida",
plan: "", cluster_version: "1.24",
name: "", cluster_label: "",
k8s_version: "1.27", nodepools: [{
nodes: 1, label: "default-pool",
storage: "50", size: "",
public_ip: true, count: 1,
auto_scaling: false, maxCount: 1
min_nodes: 1, }],
max_nodes: 3, firewall: "",
vpc: "", vpc: "",
subnet: "" subnet: "",
network_type: "public",
cpumodel: "intel"
}); });
useEffect(() => { useEffect(() => {
@ -52,19 +55,19 @@ export default function NewKubernetesService() {
const plansData = await plansResponse.json(); const plansData = await plansResponse.json();
const vpcsData = await vpcsResponse.json(); const vpcsData = await vpcsResponse.json();
console.log('vpcsData.vpc', vpcsData.vpc)
setPlans(plansData.plans || []); setPlans(plansData.plans || []);
setVpcs(vpcsData.vpc || []); setVpcs(vpcsData.vpc || []);
// Set default VPC and subnet if available // Set default VPC if available
if (vpcsData.vpc?.length > 0) { if (vpcsData.vpc?.length > 0) {
const firstVpc = vpcsData.vpc[0]; const firstVpc = vpcsData.vpc[0];
const firstSubnet = firstVpc.subnets?.[0]?.id || "";
setFormData(prev => ({ setFormData(prev => ({
...prev, ...prev,
vpc: firstVpc.id, vpc: firstVpc.id
subnet: firstSubnet
})); }));
// Fetch subnets for the default VPC
await fetchSubnets(firstVpc.id);
} }
} catch (error) { } catch (error) {
console.error("Initial data fetch error:", error); console.error("Initial data fetch error:", error);
@ -81,19 +84,49 @@ console.log('vpcsData.vpc', vpcsData.vpc)
fetchInitialData(); fetchInitialData();
}, []); }, []);
const handleVpcChange = (vpcId) => { const fetchSubnets = async (vpcId) => {
try {
// First try to get subnets from the VPC data
const selectedVpc = vpcs.find(vpc => vpc.id === vpcId); const selectedVpc = vpcs.find(vpc => vpc.id === vpcId);
const firstSubnet = selectedVpc?.subnet?.[0]?.id || ""; if (selectedVpc?.subnet?.length > 0) {
setSubnets(selectedVpc.subnet);
setFormData(prev => ({
...prev,
subnet: selectedVpc.subnet[0].id
}));
return;
}
// If no subnets in VPC data, try the subnets endpoint
const response = await fetch(`https://api.utho.com/v2/vpc/${vpcId}/subnets`, {
headers: {
"Authorization": UTHO_API_KEY,
"Content-Type": "application/json"
}
});
if (response.ok) {
const data = await response.json();
setSubnets(data.subnets || []);
if (data.subnets?.length > 0) {
setFormData(prev => ({
...prev,
subnet: data.subnets[0].id
}));
}
}
} catch (error) {
console.error("Error fetching subnets:", error);
}
};
const handleVpcChange = async (vpcId) => {
setFormData(prev => ({ setFormData(prev => ({
...prev, ...prev,
vpc: vpcId, vpc: vpcId,
subnet: firstSubnet subnet: ""
})); }));
}; await fetchSubnets(vpcId);
const getCurrentSubnets = () => {
const selectedVpc = vpcs.find(vpc => vpc.id === formData.vpc);
return selectedVpc?.subnets || [];
}; };
const handleSubmit = async (e) => { const handleSubmit = async (e) => {
@ -101,27 +134,29 @@ console.log('vpcsData.vpc', vpcsData.vpc)
setIsLoading(true); setIsLoading(true);
try { try {
if (!formData.vpc || !formData.subnet) { // Validate required fields including subnet
throw new Error("Please select both VPC and Subnet to proceed"); if (!formData.cluster_label || !formData.nodepools[0].size || !formData.vpc || !formData.subnet) {
throw new Error("Please fill all required fields including VPC and Subnet");
} }
const payload = { const payload = {
datacenter: formData.datacenter, dcslug: formData.dcslug,
plan: formData.plan, cluster_version: formData.cluster_version,
name: formData.name, cluster_label: formData.cluster_label,
k8s_version: formData.k8s_version, nodepools: formData.nodepools.map(pool => ({
nodes: formData.nodes, label: pool.label,
storage: formData.storage, size: pool.size,
public_ip: formData.public_ip, count: pool.count.toString(),
maxCount: pool.maxCount.toString()
})),
firewall: formData.firewall || undefined,
vpc: formData.vpc, vpc: formData.vpc,
subnet: formData.subnet subnet: formData.subnet, // Now required based on API behavior
network_type: formData.network_type,
cpumodel: formData.cpumodel
}; };
if (formData.auto_scaling) { console.log("Deployment payload:", payload);
payload.auto_scaling = true;
payload.min_nodes = formData.min_nodes;
payload.max_nodes = formData.max_nodes;
}
const response = await fetch("https://api.utho.com/v2/kubernetes/deploy", { const response = await fetch("https://api.utho.com/v2/kubernetes/deploy", {
method: "POST", method: "POST",
@ -144,11 +179,18 @@ console.log('vpcsData.vpc', vpcsData.vpc)
description: `Cluster ${data.cluster_id || data.id} is being deployed`, description: `Cluster ${data.cluster_id || data.id} is being deployed`,
variant: "success" variant: "success"
}); });
// Reset form
setFormData(prev => ({ setFormData(prev => ({
...prev, ...prev,
name: "", cluster_label: "",
plan: "", nodepools: [{
nodes: 1 label: "default-pool",
size: "",
count: 1,
maxCount: 1
}],
vpc: vpcs[0]?.id || "",
subnet: subnets[0]?.id || ""
})); }));
} else { } else {
throw new Error(data.message || "Failed to deploy Kubernetes cluster"); throw new Error(data.message || "Failed to deploy Kubernetes cluster");
@ -173,6 +215,15 @@ console.log('vpcsData.vpc', vpcsData.vpc)
})); }));
}; };
const handleNodePoolChange = (index, field, value) => {
const updatedNodePools = [...formData.nodepools];
updatedNodePools[index][field] = value;
setFormData(prev => ({
...prev,
nodepools: updatedNodePools
}));
};
if (isFetchingData) { if (isFetchingData) {
return ( return (
<div className="flex items-center justify-center h-64"> <div className="flex items-center justify-center h-64">
@ -182,8 +233,6 @@ console.log('vpcsData.vpc', vpcsData.vpc)
); );
} }
const currentSubnets = getCurrentSubnets();
return ( return (
<Card className="w-full max-w-2xl mx-auto my-4"> <Card className="w-full max-w-2xl mx-auto my-4">
<CardHeader> <CardHeader>
@ -194,75 +243,130 @@ console.log('vpcsData.vpc', vpcsData.vpc)
</CardHeader> </CardHeader>
<CardContent> <CardContent>
<form onSubmit={handleSubmit} className="space-y-4"> <form onSubmit={handleSubmit} className="space-y-4">
{/* Name, Datacenter, and Kubernetes Version fields */} {/* Cluster Label */}
<div className="space-y-2"> <div className="space-y-2">
<Label htmlFor="name">Cluster Name *</Label> <Label htmlFor="cluster_label">Cluster Label *</Label>
<Input <Input
id="name" id="cluster_label"
name="name" name="cluster_label"
value={formData.name} value={formData.cluster_label}
onChange={handleChange} onChange={handleChange}
placeholder="my-cluster" placeholder="my-cluster"
required required
/> />
</div> </div>
{/* Data Center and Version */}
<div className="grid grid-cols-1 md:grid-cols-2 gap-4"> <div className="grid grid-cols-1 md:grid-cols-2 gap-4">
<div className="space-y-2"> <div className="space-y-2">
<Label htmlFor="datacenter">Data Center *</Label> <Label htmlFor="dcslug">Data Center *</Label>
<Select <Select
name="datacenter" name="dcslug"
value={formData.datacenter} value={formData.dcslug}
onValueChange={(value) => setFormData({...formData, datacenter: value})} onValueChange={(value) => setFormData({...formData, dcslug: value})}
required
> >
<SelectTrigger> <SelectTrigger>
<SelectValue placeholder="Select location" /> <SelectValue placeholder="Select location" />
</SelectTrigger> </SelectTrigger>
<SelectContent> <SelectContent>
<SelectItem value="mumbai">Mumbai</SelectItem> <SelectItem value="innoida">Noida</SelectItem>
<SelectItem value="noida">Noida</SelectItem> <SelectItem value="inmumbaizone2">Mumbai Zone 2</SelectItem>
<SelectItem value="delhi">Delhi</SelectItem> <SelectItem value="indelhi">Delhi</SelectItem>
</SelectContent> </SelectContent>
</Select> </Select>
</div> </div>
<div className="space-y-2"> <div className="space-y-2">
<Label htmlFor="k8s_version">Kubernetes Version *</Label> <Label htmlFor="cluster_version">Kubernetes Version *</Label>
<Select <Select
name="k8s_version" name="cluster_version"
value={formData.k8s_version} value={formData.cluster_version}
onValueChange={(value) => setFormData({...formData, k8s_version: value})} onValueChange={(value) => setFormData({...formData, cluster_version: value})}
required required
> >
<SelectTrigger> <SelectTrigger>
<SelectValue placeholder="Select version" /> <SelectValue placeholder="Select version" />
</SelectTrigger> </SelectTrigger>
<SelectContent> <SelectContent>
<SelectItem value="1.27">1.27 (Latest)</SelectItem> <SelectItem value="1.24">1.24</SelectItem>
<SelectItem value="1.26">1.26</SelectItem>
<SelectItem value="1.25">1.25</SelectItem> <SelectItem value="1.25">1.25</SelectItem>
<SelectItem value="1.26">1.26</SelectItem>
<SelectItem value="1.27">1.27</SelectItem>
</SelectContent> </SelectContent>
</Select> </Select>
</div> </div>
</div> </div>
{/* Node Plan and Count */} {/* Network Type and CPU Model */}
<div className="grid grid-cols-1 md:grid-cols-2 gap-4"> <div className="grid grid-cols-1 md:grid-cols-2 gap-4">
<div className="space-y-2"> <div className="space-y-2">
<Label htmlFor="plan">Node Plan *</Label> <Label htmlFor="network_type">Network Type *</Label>
<Select <Select
name="plan" name="network_type"
value={formData.plan} value={formData.network_type}
onValueChange={(value) => setFormData({...formData, plan: value})} onValueChange={(value) => setFormData({...formData, network_type: value})}
required required
> >
<SelectTrigger> <SelectTrigger>
<SelectValue placeholder="Select a plan" /> <SelectValue placeholder="Select network type" />
</SelectTrigger>
<SelectContent>
<SelectItem value="public">Public</SelectItem>
<SelectItem value="private">Private</SelectItem>
</SelectContent>
</Select>
</div>
<div className="space-y-2">
<Label htmlFor="cpumodel">CPU Model *</Label>
<Select
name="cpumodel"
value={formData.cpumodel}
onValueChange={(value) => setFormData({...formData, cpumodel: value})}
required
>
<SelectTrigger>
<SelectValue placeholder="Select CPU model" />
</SelectTrigger>
<SelectContent>
<SelectItem value="intel">Intel</SelectItem>
<SelectItem value="amd">AMD</SelectItem>
</SelectContent>
</Select>
</div>
</div>
{/* Node Pool Configuration */}
<div className="space-y-4">
<h3 className="text-lg font-medium">Node Pool Configuration</h3>
{formData.nodepools.map((pool, index) => (
<div key={index} className="p-4 border rounded-lg space-y-4">
<div className="space-y-2">
<Label htmlFor={`pool-label-${index}`}>Pool Label *</Label>
<Input
id={`pool-label-${index}`}
value={pool.label}
onChange={(e) => handleNodePoolChange(index, 'label', e.target.value)}
required
/>
</div>
<div className="grid grid-cols-1 md:grid-cols-3 gap-4">
<div className="space-y-2">
<Label htmlFor={`pool-size-${index}`}>Node Size *</Label>
<Select
value={pool.size}
onValueChange={(value) => handleNodePoolChange(index, 'size', value)}
required
>
<SelectTrigger>
<SelectValue placeholder="Select node size" />
</SelectTrigger> </SelectTrigger>
<SelectContent> <SelectContent>
{plans.map(plan => ( {plans.map(plan => (
<SelectItem key={plan.id} value={plan.id}> <SelectItem key={plan.id} value={plan.id}>
{`${plan.cpu} vCPU, ${Math.floor(parseInt(plan.ram)/1024)}GB RAM, ${plan.disk}GB Disk`} {`${plan.cpu} vCPU, ${Math.floor(parseInt(plan.ram)/1024)}GB RAM`}
</SelectItem> </SelectItem>
))} ))}
</SelectContent> </SelectContent>
@ -270,21 +374,33 @@ console.log('vpcsData.vpc', vpcsData.vpc)
</div> </div>
<div className="space-y-2"> <div className="space-y-2">
<Label htmlFor="nodes">Initial Node Count *</Label> <Label htmlFor={`pool-count-${index}`}>Node Count *</Label>
<Input <Input
id="nodes" id={`pool-count-${index}`}
name="nodes"
type="number" type="number"
min="1" min="1"
max="10" value={pool.count}
value={formData.nodes} onChange={(e) => handleNodePoolChange(index, 'count', parseInt(e.target.value))}
onChange={handleChange}
required required
/> />
</div> </div>
<div className="space-y-2">
<Label htmlFor={`pool-maxCount-${index}`}>Max Nodes</Label>
<Input
id={`pool-maxCount-${index}`}
type="number"
min={pool.count}
value={pool.maxCount}
onChange={(e) => handleNodePoolChange(index, 'maxCount', parseInt(e.target.value))}
/>
</div>
</div>
</div>
))}
</div> </div>
{/* VPC and Subnet Selection */} {/* VPC and Subnet */}
<div className="grid grid-cols-1 md:grid-cols-2 gap-4"> <div className="grid grid-cols-1 md:grid-cols-2 gap-4">
<div className="space-y-2"> <div className="space-y-2">
<Label htmlFor="vpc">VPC *</Label> <Label htmlFor="vpc">VPC *</Label>
@ -314,22 +430,22 @@ console.log('vpcsData.vpc', vpcsData.vpc)
value={formData.subnet} value={formData.subnet}
onValueChange={(value) => setFormData({...formData, subnet: value})} onValueChange={(value) => setFormData({...formData, subnet: value})}
required required
disabled={!formData.vpc || currentSubnets.length === 0} disabled={!formData.vpc || subnets.length === 0}
> >
<SelectTrigger> <SelectTrigger>
<SelectValue placeholder={currentSubnets.length === 0 ? "No subnets available" : "Select subnet"}> <SelectValue placeholder={subnets.length === 0 ? "No subnets available" : "Select subnet"}>
{formData.subnet || (currentSubnets.length === 0 ? "No subnets available" : "Select subnet")} {formData.subnet || (subnets.length === 0 ? "No subnets available" : "Select subnet")}
</SelectValue> </SelectValue>
</SelectTrigger> </SelectTrigger>
<SelectContent> <SelectContent>
{currentSubnets.map(subnet => ( {subnets.map(subnet => (
<SelectItem key={subnet.id} value={subnet.id}> <SelectItem key={subnet.id} value={subnet.id}>
{subnet.name || subnet.id} ({subnet.network}/{subnet.size}) {subnet.name || subnet.id} ({subnet.network}/{subnet.size})
</SelectItem> </SelectItem>
))} ))}
</SelectContent> </SelectContent>
</Select> </Select>
{currentSubnets.length === 0 && formData.vpc && ( {subnets.length === 0 && formData.vpc && (
<p className="text-sm text-muted-foreground mt-1"> <p className="text-sm text-muted-foreground mt-1">
No subnets found in this VPC. Please create a subnet first. No subnets found in this VPC. Please create a subnet first.
</p> </p>
@ -337,85 +453,22 @@ console.log('vpcsData.vpc', vpcsData.vpc)
</div> </div>
</div> </div>
{/* Storage and Advanced Options */} {/* Firewall (Optional) */}
<div className="space-y-2"> <div className="space-y-2">
<Label htmlFor="storage">Storage per Node (GB) *</Label> <Label htmlFor="firewall">Firewall ID (Optional)</Label>
<Select
name="storage"
value={formData.storage}
onValueChange={(value) => setFormData({...formData, storage: value})}
required
>
<SelectTrigger>
<SelectValue placeholder="Select storage" />
</SelectTrigger>
<SelectContent>
<SelectItem value="50">50 GB</SelectItem>
<SelectItem value="100">100 GB</SelectItem>
<SelectItem value="200">200 GB</SelectItem>
<SelectItem value="500">500 GB</SelectItem>
</SelectContent>
</Select>
</div>
<div className="space-y-4">
<h3 className="text-lg font-medium">Advanced Options</h3>
<div className="flex flex-col gap-4">
<div className="flex items-center space-x-2">
<Switch
id="public_ip"
checked={formData.public_ip}
onCheckedChange={(checked) => setFormData({...formData, public_ip: checked})}
/>
<Label htmlFor="public_ip">Enable Public IP for Nodes</Label>
</div>
<div className="flex items-center space-x-2">
<Switch
id="auto_scaling"
checked={formData.auto_scaling}
onCheckedChange={(checked) => setFormData({...formData, auto_scaling: checked})}
/>
<Label htmlFor="auto_scaling">Enable Auto Scaling</Label>
</div>
{formData.auto_scaling && (
<div className="grid grid-cols-1 md:grid-cols-2 gap-4 p-4 border rounded-lg">
<div className="space-y-2">
<Label htmlFor="min_nodes">Minimum Nodes</Label>
<Input <Input
id="min_nodes" id="firewall"
name="min_nodes" name="firewall"
type="number" value={formData.firewall}
min="1"
max="10"
value={formData.min_nodes}
onChange={handleChange} onChange={handleChange}
required placeholder="Firewall ID"
/> />
</div> </div>
<div className="space-y-2">
<Label htmlFor="max_nodes">Maximum Nodes</Label>
<Input
id="max_nodes"
name="max_nodes"
type="number"
min={formData.min_nodes}
max="20"
value={formData.max_nodes}
onChange={handleChange}
required
/>
</div>
</div>
)}
</div>
</div>
<div className="flex justify-end pt-4"> <div className="flex justify-end pt-4">
<Button <Button
type="submit" type="submit"
disabled={isLoading || !formData.vpc || !formData.subnet} disabled={isLoading || !formData.cluster_label || !formData.nodepools[0].size || !formData.vpc || !formData.subnet}
className="w-full md:w-auto" className="w-full md:w-auto"
> >
{isLoading ? ( {isLoading ? (

View File

@ -14,7 +14,7 @@ export default function LoginOrProfile({ deviceType }) {
} }
{ {
deviceType === 'mobile' && ( deviceType === 'mobile' && (
<svg className="animate-spin flex flex-col items-center justify-center w-full h-full text-[#6d9e37] hover:text-white transition-colors" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="64px" height="64px" viewBox="0 0 100 100" enable-background="new 0 0 100 100" xml:space="preserve" fill="#6d9e37"><g id="SVGRepo_bgCarrier" stroke-width="0"></g><g id="SVGRepo_tracerCarrier" stroke-linecap="round" stroke-linejoin="round"></g><g id="SVGRepo_iconCarrier"> <g id="Download_x5F_25_x25_"> </g> <g id="Download_x5F_50_x25_"> </g> <g id="Download_x5F_75_x25_"> </g> <g id="Download_x5F_100_x25_"> </g> <g id="Upload"> </g> <g id="Next"> </g> <g id="Last"> </g> <g id="OK"> </g> <g id="Fail"> </g> <g id="Add"> </g> <g id="Spinner_x5F_0_x25_"> </g> <g id="Spinner_x5F_25_x25_"> <g> <path fill="none" stroke="#6d9e37" stroke-width="4" stroke-linejoin="round" stroke-miterlimit="10" d="M50.188,26.812 c12.806,0,23.188,10.381,23.188,23.188"></path> <g> <circle cx="73.375" cy="50" r="1.959"></circle> <circle cx="72.029" cy="57.704" r="1.959"></circle> <circle cx="68.237" cy="64.579" r="1.959"></circle> <circle cx="62.324" cy="69.759" r="1.959"></circle> <circle cx="55.013" cy="72.699" r="1.959"></circle> </g> <g> <ellipse transform="matrix(0.9968 -0.0794 0.0794 0.9968 -4.0326 2.3121)" cx="27.045" cy="51.843" rx="1.959" ry="1.959"></ellipse> <ellipse transform="matrix(0.9968 -0.0794 0.0794 0.9968 -4.628 2.4912)" cx="28.998" cy="59.416" rx="1.959" ry="1.959"></ellipse> <ellipse transform="matrix(0.9968 -0.0794 0.0794 0.9968 -5.1348 2.8556)" cx="33.325" cy="65.967" rx="1.959" ry="1.959"></ellipse> <ellipse transform="matrix(0.9968 -0.0794 0.0794 0.9968 -5.4877 3.3713)" cx="39.63" cy="70.661" rx="1.959" ry="1.959"></ellipse> <ellipse transform="matrix(0.9968 -0.0794 0.0794 0.9968 -5.6506 3.9762)" cx="47.152" cy="73.012" rx="1.959" ry="1.959"></ellipse> </g> <g> <ellipse transform="matrix(0.9962 -0.0867 0.0867 0.9962 -3.713 2.567)" cx="27.71" cy="44.049" rx="1.959" ry="1.959"></ellipse> <ellipse transform="matrix(0.9962 -0.0867 0.0867 0.9962 -3.079 2.8158)" cx="30.892" cy="36.872" rx="1.959" ry="1.959"></ellipse> <ellipse transform="matrix(0.9962 -0.0867 0.0867 0.9962 -2.567 3.266)" cx="36.334" cy="31.199" rx="1.959" ry="1.959"></ellipse> <ellipse transform="matrix(0.9962 -0.0867 0.0867 0.9962 -2.2318 3.8617)" cx="43.363" cy="27.636" rx="1.959" ry="1.959"></ellipse> </g> </g> </g> <g id="Spinner_x5F_50_x25_"> </g> <g id="Spinner_x5F_75_x25_"> </g> <g id="Brightest_x5F_25_x25_"> </g> <g id="Brightest_x5F_50_x25_"> </g> <g id="Brightest_x5F_75_x25_"> </g> <g id="Brightest_x5F_100_x25_"> </g> <g id="Reload"> </g> <g id="Forbidden"> </g> <g id="Clock"> </g> <g id="Compass"> </g> <g id="World"> </g> <g id="Speed"> </g> <g id="Microphone"> </g> <g id="Options"> </g> <g id="Chronometer"> </g> <g id="Lock"> </g> <g id="User"> </g> <g id="Position"> </g> <g id="No_x5F_Signal"> </g> <g id="Low_x5F_Signal"> </g> <g id="Mid_x5F_Signal"> </g> <g id="High_x5F_Signal"> </g> <g id="Options_1_"> </g> <g id="Flash"> </g> <g id="No_x5F_Signal_x5F_02"> </g> <g id="Low_x5F_Signal_x5F_02"> </g> <g id="Mid_x5F_Signal_x5F_02"> </g> <g id="High_x5F_Signal_x5F_02"> </g> <g id="Favorite"> </g> <g id="Search"> </g> <g id="Stats_x5F_01"> </g> <g id="Stats_x5F_02"> </g> <g id="Turn_x5F_On_x5F_Off"> </g> <g id="Full_x5F_Height"> </g> <g id="Full_x5F_Width"> </g> <g id="Full_x5F_Screen"> </g> <g id="Compress_x5F_Screen"> </g> <g id="Chat"> </g> <g id="Bluetooth"> </g> <g id="Share_x5F_iOS"> </g> <g id="Share_x5F_Android"> </g> <g id="Love__x2F__Favorite"> </g> <g id="Hamburguer"> </g> <g id="Flying"> </g> <g id="Take_x5F_Off"> </g> <g id="Land"> </g> <g id="City"> </g> <g id="Nature"> </g> <g id="Pointer"> </g> <g id="Prize"> </g> <g id="Extract"> </g> <g id="Play"> </g> <g id="Pause"> </g> <g id="Stop"> </g> <g id="Forward"> </g> <g id="Reverse"> </g> <g id="Next_1_"> </g> <g id="Last_1_"> </g> <g id="Empty_x5F_Basket"> </g> <g id="Add_x5F_Basket"> </g> <g id="Delete_x5F_Basket"> </g> <g id="Error_x5F_Basket"> </g> <g id="OK_x5F_Basket"> </g> </g></svg> <svg className="animate-spin flex flex-col items-center justify-center w-[45px] h-[45px] text-[#6d9e37] hover:text-white transition-colors" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="64px" height="64px" viewBox="0 0 100 100" enable-background="new 0 0 100 100" xml:space="preserve" fill="#6d9e37"><g id="SVGRepo_bgCarrier" stroke-width="0"></g><g id="SVGRepo_tracerCarrier" stroke-linecap="round" stroke-linejoin="round"></g><g id="SVGRepo_iconCarrier"> <g id="Download_x5F_25_x25_"> </g> <g id="Download_x5F_50_x25_"> </g> <g id="Download_x5F_75_x25_"> </g> <g id="Download_x5F_100_x25_"> </g> <g id="Upload"> </g> <g id="Next"> </g> <g id="Last"> </g> <g id="OK"> </g> <g id="Fail"> </g> <g id="Add"> </g> <g id="Spinner_x5F_0_x25_"> </g> <g id="Spinner_x5F_25_x25_"> <g> <path fill="none" stroke="#6d9e37" stroke-width="4" stroke-linejoin="round" stroke-miterlimit="10" d="M50.188,26.812 c12.806,0,23.188,10.381,23.188,23.188"></path> <g> <circle cx="73.375" cy="50" r="1.959"></circle> <circle cx="72.029" cy="57.704" r="1.959"></circle> <circle cx="68.237" cy="64.579" r="1.959"></circle> <circle cx="62.324" cy="69.759" r="1.959"></circle> <circle cx="55.013" cy="72.699" r="1.959"></circle> </g> <g> <ellipse transform="matrix(0.9968 -0.0794 0.0794 0.9968 -4.0326 2.3121)" cx="27.045" cy="51.843" rx="1.959" ry="1.959"></ellipse> <ellipse transform="matrix(0.9968 -0.0794 0.0794 0.9968 -4.628 2.4912)" cx="28.998" cy="59.416" rx="1.959" ry="1.959"></ellipse> <ellipse transform="matrix(0.9968 -0.0794 0.0794 0.9968 -5.1348 2.8556)" cx="33.325" cy="65.967" rx="1.959" ry="1.959"></ellipse> <ellipse transform="matrix(0.9968 -0.0794 0.0794 0.9968 -5.4877 3.3713)" cx="39.63" cy="70.661" rx="1.959" ry="1.959"></ellipse> <ellipse transform="matrix(0.9968 -0.0794 0.0794 0.9968 -5.6506 3.9762)" cx="47.152" cy="73.012" rx="1.959" ry="1.959"></ellipse> </g> <g> <ellipse transform="matrix(0.9962 -0.0867 0.0867 0.9962 -3.713 2.567)" cx="27.71" cy="44.049" rx="1.959" ry="1.959"></ellipse> <ellipse transform="matrix(0.9962 -0.0867 0.0867 0.9962 -3.079 2.8158)" cx="30.892" cy="36.872" rx="1.959" ry="1.959"></ellipse> <ellipse transform="matrix(0.9962 -0.0867 0.0867 0.9962 -2.567 3.266)" cx="36.334" cy="31.199" rx="1.959" ry="1.959"></ellipse> <ellipse transform="matrix(0.9962 -0.0867 0.0867 0.9962 -2.2318 3.8617)" cx="43.363" cy="27.636" rx="1.959" ry="1.959"></ellipse> </g> </g> </g> <g id="Spinner_x5F_50_x25_"> </g> <g id="Spinner_x5F_75_x25_"> </g> <g id="Brightest_x5F_25_x25_"> </g> <g id="Brightest_x5F_50_x25_"> </g> <g id="Brightest_x5F_75_x25_"> </g> <g id="Brightest_x5F_100_x25_"> </g> <g id="Reload"> </g> <g id="Forbidden"> </g> <g id="Clock"> </g> <g id="Compass"> </g> <g id="World"> </g> <g id="Speed"> </g> <g id="Microphone"> </g> <g id="Options"> </g> <g id="Chronometer"> </g> <g id="Lock"> </g> <g id="User"> </g> <g id="Position"> </g> <g id="No_x5F_Signal"> </g> <g id="Low_x5F_Signal"> </g> <g id="Mid_x5F_Signal"> </g> <g id="High_x5F_Signal"> </g> <g id="Options_1_"> </g> <g id="Flash"> </g> <g id="No_x5F_Signal_x5F_02"> </g> <g id="Low_x5F_Signal_x5F_02"> </g> <g id="Mid_x5F_Signal_x5F_02"> </g> <g id="High_x5F_Signal_x5F_02"> </g> <g id="Favorite"> </g> <g id="Search"> </g> <g id="Stats_x5F_01"> </g> <g id="Stats_x5F_02"> </g> <g id="Turn_x5F_On_x5F_Off"> </g> <g id="Full_x5F_Height"> </g> <g id="Full_x5F_Width"> </g> <g id="Full_x5F_Screen"> </g> <g id="Compress_x5F_Screen"> </g> <g id="Chat"> </g> <g id="Bluetooth"> </g> <g id="Share_x5F_iOS"> </g> <g id="Share_x5F_Android"> </g> <g id="Love__x2F__Favorite"> </g> <g id="Hamburguer"> </g> <g id="Flying"> </g> <g id="Take_x5F_Off"> </g> <g id="Land"> </g> <g id="City"> </g> <g id="Nature"> </g> <g id="Pointer"> </g> <g id="Prize"> </g> <g id="Extract"> </g> <g id="Play"> </g> <g id="Pause"> </g> <g id="Stop"> </g> <g id="Forward"> </g> <g id="Reverse"> </g> <g id="Next_1_"> </g> <g id="Last_1_"> </g> <g id="Empty_x5F_Basket"> </g> <g id="Add_x5F_Basket"> </g> <g id="Delete_x5F_Basket"> </g> <g id="Error_x5F_Basket"> </g> <g id="OK_x5F_Basket"> </g> </g></svg>
) )
} }

View File

@ -7,7 +7,6 @@ import { Button } from './ui/button';
import { Separator } from './ui/separator'; import { Separator } from './ui/separator';
import { Dialog, DialogContent, DialogHeader, DialogTitle, DialogTrigger } from './ui/dialog'; import { Dialog, DialogContent, DialogHeader, DialogTitle, DialogTrigger } from './ui/dialog';
import { CustomTabs } from './ui/tabs'; import { CustomTabs } from './ui/tabs';
const TOPIC_API_URL = 'https://host-api.cs1.hz.siliconpin.com/v1/topics/'; const TOPIC_API_URL = 'https://host-api.cs1.hz.siliconpin.com/v1/topics/';
const MINIO_UPLOAD_URL = 'https://hostapi2.cs1.hz.siliconpin.com/api/storage/upload'; const MINIO_UPLOAD_URL = 'https://hostapi2.cs1.hz.siliconpin.com/api/storage/upload';

View File

@ -112,10 +112,18 @@ export default function TopicCreation() {
return ( return (
<> <>
{isLoggedIn && ( {isLoggedIn && (
<>
<div className="container mx-auto flex justify-end gap-x-4 my-4"> <div className="container mx-auto flex justify-end gap-x-4 my-4">
<Button onClick={() => window.location.href = '/topic/new'} variant="outline">Create New</Button> <Button className="hidden lg:block" onClick={() => window.location.href = '/topic/new'} variant="outline">Create New</Button>
<Button onClick={() => window.location.href = '/topic/my-topic'} variant="outline">My Creation</Button> <Button onClick={() => window.location.href = '/topic/my-topic'} variant="outline">My Creation</Button>
</div> </div>
<button onClick={() => window.location.href = '/topic/new'} className="fixed z-10 bottom-20 lg:bottom-10 right-0 lg:right-10 rounded-full w-16 h-16 bg-[#6d9e37]">
<span class="absolute inline-flex h-full w-full animate-ping rounded-full bg-[#6d9e37] opacity-75 duration-[1s,15s]"></span>
<span class="relative inline-flex w-16 h-16 rounded-full bg-[#6d9e37]">
<svg className="border-[2px] border-[#fff] rounded-full" fill="#FFFFFF" viewBox="-5.76 -5.76 35.52 35.52" xmlns="http://www.w3.org/2000/svg"><g id="SVGRepo_bgCarrier" stroke-width="0"></g><g id="SVGRepo_tracerCarrier" stroke-linecap="round" stroke-linejoin="round"></g><g id="SVGRepo_iconCarrier"> <path fill-rule="evenodd" d="M12.3023235,7.94519388 L4.69610276,15.549589 C4.29095108,15.9079238 4.04030835,16.4092335 4,16.8678295 L4,20.0029438 L7.06398288,20.004826 C7.5982069,19.9670062 8.09548693,19.7183782 8.49479322,19.2616227 L16.0567001,11.6997158 L12.3023235,7.94519388 Z M13.7167068,6.53115006 L17.4709137,10.2855022 L19.8647941,7.89162181 C19.9513987,7.80501747 20.0000526,7.68755666 20.0000526,7.56507948 C20.0000526,7.4426023 19.9513987,7.32514149 19.8647932,7.23853626 L16.7611243,4.13485646 C16.6754884,4.04854589 16.5589355,4 16.43735,4 C16.3157645,4 16.1992116,4.04854589 16.1135757,4.13485646 L13.7167068,6.53115006 Z M16.43735,2 C17.0920882,2 17.7197259,2.26141978 18.1781068,2.7234227 L21.2790059,5.82432181 C21.7406843,6.28599904 22.0000526,6.91216845 22.0000526,7.56507948 C22.0000526,8.21799052 21.7406843,8.84415992 21.2790068,9.30583626 L9.95750718,20.6237545 C9.25902448,21.4294925 8.26890003,21.9245308 7.1346,22.0023295 L2,22.0023295 L2,21.0023295 L2.00324765,16.7873015 C2.08843822,15.7328366 2.57866679,14.7523321 3.32649633,14.0934196 L14.6953877,2.72462818 C15.1563921,2.2608295 15.7833514,2 16.43735,2 Z"></path> </g></svg>
</span>
</button>
</>
)} )}
{loading && !topics.length ? ( {loading && !topics.length ? (

View File

@ -45,9 +45,10 @@ const { title, description, ogImage, canonicalURL = new URL(Astro.url.pathname,
<link rel="apple-touch-icon" href="https://siliconpin.com/assets/logo.svg" /> <link rel="apple-touch-icon" href="https://siliconpin.com/assets/logo.svg" />
<!-- Structured Data --> <!-- Structured Data -->
<script type="application/ld+json" set:html={newSchema1}></script> <script is:inline type="application/ld+json" set:html={newSchema1}></script>
<!-- <script type="application/ld+json" set:html={JSON.stringify(organizationSchema)}></script>
<script type="application/ld+json" set:html={JSON.stringify(organizationSchema)}></script> --> <!-- For markdown editor css -->
<link rel="stylesheet" href="/assets/md-editor/mdeditor.css" />
</head> </head>
<body class="min-h-screen flex flex-col"> <body class="min-h-screen flex flex-col">
<!-- Top header - visible on all devices --> <!-- Top header - visible on all devices -->
@ -186,21 +187,24 @@ const { title, description, ogImage, canonicalURL = new URL(Astro.url.pathname,
<svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M3 9l9-7 9 7v11a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2z"></path><polyline points="9 22 9 12 15 12 15 22"></polyline></svg> <svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M3 9l9-7 9 7v11a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2z"></path><polyline points="9 22 9 12 15 12 15 22"></polyline></svg>
<span class="text-xs mt-1">Home</span> <span class="text-xs mt-1">Home</span>
</a> </a>
<a href="/services" class="flex flex-col items-center justify-center w-full h-full text-[#6d9e37] hover:text-white transition-colors"> <a href="/topic" class="flex flex-col items-center justify-center w-full h-full text-[#6d9e37] hover:text-white transition-colors">
<svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="12" r="3"></circle><path d="M19.4 15a1.65 1.65 0 0 0 .33 1.82l.06.06a2 2 0 0 1 0 2.83 2 2 0 0 1-2.83 0l-.06-.06a1.65 1.65 0 0 0-1.82-.33 1.65 1.65 0 0 0-1 1.51V21a2 2 0 0 1-2 2 2 2 0 0 1-2-2v-.09A1.65 1.65 0 0 0 9 19.4a1.65 1.65 0 0 0-1.82.33l-.06.06a2 2 0 0 1-2.83 0 2 2 0 0 1 0-2.83l.06-.06a1.65 1.65 0 0 0 .33-1.82 1.65 1.65 0 0 0-1.51-1H3a2 2 0 0 1-2-2 2 2 0 0 1 2-2h.09A1.65 1.65 0 0 0 4.6 9a1.65 1.65 0 0 0-.33-1.82l-.06-.06a2 2 0 0 1 0-2.83 2 2 0 0 1 2.83 0l.06.06a1.65 1.65 0 0 0 1.82.33H9a1.65 1.65 0 0 0 1-1.51V3a2 2 0 0 1 2-2 2 2 0 0 1 2 2v.09a1.65 1.65 0 0 0 1 1.51 1.65 1.65 0 0 0 1.82-.33l.06-.06a2 2 0 0 1 2.83 0 2 2 0 0 1 0 2.83l-.06.06a1.65 1.65 0 0 0-.33 1.82V9a1.65 1.65 0 0 0 1.51 1H21a2 2 0 0 1 2 2 2 2 0 0 1-2 2h-.09a1.65 1.65 0 0 0-1.51 1z"></path></svg> <!-- <svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="12" r="3"></circle><path d="M19.4 15a1.65 1.65 0 0 0 .33 1.82l.06.06a2 2 0 0 1 0 2.83 2 2 0 0 1-2.83 0l-.06-.06a1.65 1.65 0 0 0-1.82-.33 1.65 1.65 0 0 0-1 1.51V21a2 2 0 0 1-2 2 2 2 0 0 1-2-2v-.09A1.65 1.65 0 0 0 9 19.4a1.65 1.65 0 0 0-1.82.33l-.06.06a2 2 0 0 1-2.83 0 2 2 0 0 1 0-2.83l.06-.06a1.65 1.65 0 0 0 .33-1.82 1.65 1.65 0 0 0-1.51-1H3a2 2 0 0 1-2-2 2 2 0 0 1 2-2h.09A1.65 1.65 0 0 0 4.6 9a1.65 1.65 0 0 0-.33-1.82l-.06-.06a2 2 0 0 1 0-2.83 2 2 0 0 1 2.83 0l.06.06a1.65 1.65 0 0 0 1.82.33H9a1.65 1.65 0 0 0 1-1.51V3a2 2 0 0 1 2-2 2 2 0 0 1 2 2v.09a1.65 1.65 0 0 0 1 1.51 1.65 1.65 0 0 0 1.82-.33l.06-.06a2 2 0 0 1 2.83 0 2 2 0 0 1 0 2.83l-.06.06a1.65 1.65 0 0 0-.33 1.82V9a1.65 1.65 0 0 0 1.51 1H21a2 2 0 0 1 2 2 2 2 0 0 1-2 2h-.09a1.65 1.65 0 0 0-1.51 1z"></path></svg> -->
<span class="text-xs mt-1">Services</span> <svg fill="#6d9e37" width="20" height="20" viewBox="-4 -2 24 24" xmlns="http://www.w3.org/2000/svg" preserveAspectRatio="xMinYMin" class="jam jam-document-f"><g id="SVGRepo_bgCarrier" stroke-width="0"></g><g id="SVGRepo_tracerCarrier" stroke-linecap="round" stroke-linejoin="round"></g><g id="SVGRepo_iconCarrier"><path d="M3 0h10a3 3 0 0 1 3 3v14a3 3 0 0 1-3 3H3a3 3 0 0 1-3-3V3a3 3 0 0 1 3-3zm1 7a1 1 0 1 0 0 2h8a1 1 0 0 0 0-2H4zm0 8a1 1 0 0 0 0 2h5a1 1 0 0 0 0-2H4zM4 3a1 1 0 1 0 0 2h8a1 1 0 0 0 0-2H4zm0 8a1 1 0 0 0 0 2h8a1 1 0 0 0 0-2H4z"></path></g></svg>
<span class="text-xs mt-1">Topic</span>
</a> </a>
<a href="/services" class="flex flex-col items-center justify-center w-full h-full text-[#6d9e37] hover:text-white transition-colors"> <a href="/services" class="flex flex-col items-center justify-center w-full h-full text-[#6d9e37] hover:text-white transition-colors">
<div class="w-10 h-10 rounded-full bg-[#6d9e37] flex items-center justify-center -mt-5 shadow-lg"> <div class="w-10 h-10 rounded-full bg-[#6d9e37] flex items-center justify-center -mt-5 shadow-lg">
<svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="white" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><line x1="12" y1="5" x2="12" y2="19"></line><line x1="5" y1="12" x2="19" y2="12"></line></svg> <svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="white" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><line x1="12" y1="5" x2="12" y2="19"></line><line x1="5" y1="12" x2="19" y2="12"></line></svg>
</div> </div>
<span class="text-xs mt-1">Start</span> <span class="text-xs mt-1">Services</span>
</a> </a>
<a href="/about-us" class="flex flex-col items-center justify-center w-full h-full text-[#6d9e37] hover:text-white transition-colors"> <a href="/about-us" class="flex flex-col items-center justify-center w-full h-full text-[#6d9e37] hover:text-white transition-colors">
<svg width="20px" height="20px" viewBox="0 0 512 512" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" fill="#6d9e37"><g id="SVGRepo_bgCarrier" stroke-width="0"></g><g id="SVGRepo_tracerCarrier" stroke-linecap="round" stroke-linejoin="round"></g><g id="SVGRepo_iconCarrier"> <title>about</title> <g id="Page-1" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd"> <g id="about-white" fill="#6d9e37" transform="translate(42.666667, 42.666667)"> <path d="M213.333333,3.55271368e-14 C95.51296,3.55271368e-14 3.55271368e-14,95.51168 3.55271368e-14,213.333333 C3.55271368e-14,331.153707 95.51296,426.666667 213.333333,426.666667 C331.154987,426.666667 426.666667,331.153707 426.666667,213.333333 C426.666667,95.51168 331.154987,3.55271368e-14 213.333333,3.55271368e-14 Z M213.333333,384 C119.227947,384 42.6666667,307.43872 42.6666667,213.333333 C42.6666667,119.227947 119.227947,42.6666667 213.333333,42.6666667 C307.44,42.6666667 384,119.227947 384,213.333333 C384,307.43872 307.44,384 213.333333,384 Z M240.04672,128 C240.04672,143.46752 228.785067,154.666667 213.55008,154.666667 C197.698773,154.666667 186.713387,143.46752 186.713387,127.704107 C186.713387,112.5536 197.99616,101.333333 213.55008,101.333333 C228.785067,101.333333 240.04672,112.5536 240.04672,128 Z M192.04672,192 L234.713387,192 L234.713387,320 L192.04672,320 L192.04672,192 Z" id="Shape"> </path> </g> </g> </g></svg> <svg width="20px" height="20px" viewBox="0 0 512 512" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" fill="#6d9e37"><g id="SVGRepo_bgCarrier" stroke-width="0"></g><g id="SVGRepo_tracerCarrier" stroke-linecap="round" stroke-linejoin="round"></g><g id="SVGRepo_iconCarrier"> <title>about</title> <g id="Page-1" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd"> <g id="about-white" fill="#6d9e37" transform="translate(42.666667, 42.666667)"> <path d="M213.333333,3.55271368e-14 C95.51296,3.55271368e-14 3.55271368e-14,95.51168 3.55271368e-14,213.333333 C3.55271368e-14,331.153707 95.51296,426.666667 213.333333,426.666667 C331.154987,426.666667 426.666667,331.153707 426.666667,213.333333 C426.666667,95.51168 331.154987,3.55271368e-14 213.333333,3.55271368e-14 Z M213.333333,384 C119.227947,384 42.6666667,307.43872 42.6666667,213.333333 C42.6666667,119.227947 119.227947,42.6666667 213.333333,42.6666667 C307.44,42.6666667 384,119.227947 384,213.333333 C384,307.43872 307.44,384 213.333333,384 Z M240.04672,128 C240.04672,143.46752 228.785067,154.666667 213.55008,154.666667 C197.698773,154.666667 186.713387,143.46752 186.713387,127.704107 C186.713387,112.5536 197.99616,101.333333 213.55008,101.333333 C228.785067,101.333333 240.04672,112.5536 240.04672,128 Z M192.04672,192 L234.713387,192 L234.713387,320 L192.04672,320 L192.04672,192 Z" id="Shape"> </path> </g> </g> </g></svg>
<span class="text-xs mt-1">About</span> <span class="text-xs mt-1">About</span>
</a> </a>
<div class="flex flex-col items-center justify-center w-full h-full text-[#6d9e37] hover:text-white transition-colors">
<LoginProfile deviceType="mobile" client:load /> <LoginProfile deviceType="mobile" client:load />
</div>
<!-- <a href="/profile" class="flex flex-col items-center justify-center w-full h-full text-[#6d9e37] hover:text-white transition-colors"> <!-- <a href="/profile" class="flex flex-col items-center justify-center w-full h-full text-[#6d9e37] hover:text-white transition-colors">
<svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="12" r="10"></circle><circle cx="12" cy="10" r="3"></circle><path d="M7 20.662V19c0-1.18.822-2.2 2-2.5a5.5 5.5 0 0 1 6 0c1.178.3 2 1.323 2 2.5v1.662"></path></svg> <svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="12" r="10"></circle><circle cx="12" cy="10" r="3"></circle><path d="M7 20.662V19c0-1.18.822-2.2 2-2.5a5.5 5.5 0 0 1 6 0c1.178.3 2 1.323 2 2.5v1.662"></path></svg>
<span class="text-xs mt-1">Profile</span> <span class="text-xs mt-1">Profile</span>

View File

@ -24,7 +24,7 @@ const schema1 = {
"sameAs": [ "sameAs": [
"https://www.linkedin.com/company/siliconpin", "https://www.linkedin.com/company/siliconpin",
"https://x.com/dwd_consultancy", "https://x.com/dwd_consultancy",
"https://www.facebook.com/profile.php?id=100088549643337", "https://www.facebook.com/dwdsiliconpin",
"https://instagram.com/siliconpin.com_" "https://instagram.com/siliconpin.com_"
] ]
}; };