improve
This commit is contained in:
parent
f717eba7d4
commit
800ad525f8
File diff suppressed because it is too large
Load Diff
@ -1,194 +1,208 @@
|
||||
import { useEffect, useState } from "react";
|
||||
import * as THREE from "three"
|
||||
import * as THREE from "three";
|
||||
import { useFrame, useThree } from "@react-three/fiber";
|
||||
import { getChunkCoordinates3D, offset } from "./chunkutils"
|
||||
import { getChunkCoordinates3D, offset } from "./chunkutils";
|
||||
import useStore from "@/lib/store";
|
||||
import { supabase } from "@/lib/supabaseClient";
|
||||
import { CSS2DRenderer, CSS2DObject } from "three/examples/jsm/Addons.js";
|
||||
import { UNIT, CHUNK_SIZE, RADIUS } from "@/lib/constants";
|
||||
import starData from "./data.json"
|
||||
import starData from "./data.json";
|
||||
|
||||
export default function Chunks() {
|
||||
const { scene, camera } = useThree();
|
||||
|
||||
const { scene, camera } = useThree()
|
||||
|
||||
const focus = useStore((s)=>s.focus)
|
||||
const [chunk, setChunk] = useState({chunkX: 0,chunkY: 0,chunkZ: 0})
|
||||
const update = useStore((s)=>s.update)
|
||||
const colors = [0xf9c54b, 0xa891fb, 0xff9933, 0x00ccff, 0xccb0e9]
|
||||
const [loaded] = useState({data:new Map()})
|
||||
const [labelRenderer] = useState(new CSS2DRenderer())
|
||||
const chunkMap = starData.chunkMap
|
||||
const names = starData.names
|
||||
const focus = useStore((s) => s.focus);
|
||||
const [chunk, setChunk] = useState({ chunkX: 0, chunkY: 0, chunkZ: 0 });
|
||||
const update = useStore((s) => s.update);
|
||||
const colors = [0xf9c54b, 0xa891fb, 0xff9933, 0x00ccff, 0xccb0e9];
|
||||
const [loaded] = useState({ data: new Map() });
|
||||
const [labelRenderer] = useState(new CSS2DRenderer());
|
||||
const chunkMap = starData.chunkMap;
|
||||
const names = starData.names;
|
||||
|
||||
const createStar = (pos:THREE.Vector3, data:any, constellationIndex:number, chunkIndex:number) => {
|
||||
const _rr = data? Math.cbrt( data.amount * 0.239 ) / 5000 : 0.2
|
||||
const rr = (_rr>2.5)?2.5:(_rr<0.2)?0.2:_rr
|
||||
const color = colors[Math.floor(Math.random() * 4.5)]
|
||||
const material = new THREE.MeshLambertMaterial({color:color})
|
||||
const geometry = new THREE.SphereGeometry(rr, 16, 16)
|
||||
const mesh = new THREE.Mesh(geometry, material)
|
||||
if(data) {
|
||||
data.constellationIndex = constellationIndex
|
||||
data.chunkIndex = chunkIndex
|
||||
}
|
||||
mesh.name = data ? data.transaction_signature : undefined
|
||||
mesh.userData = data ? data : undefined
|
||||
mesh.position.copy(pos)
|
||||
return mesh
|
||||
}
|
||||
|
||||
const createConstellation =(_size:number, data:any[], constellationIndex:number, chunkIndex:number) =>{
|
||||
// constellationIndex=== 1 && console.log(constellationIndex, data)
|
||||
const starGroup = new THREE.Group()
|
||||
const points: any[] = []
|
||||
data.map((item)=>{
|
||||
if(item){
|
||||
const pos = new THREE.Vector3(item.x, item.y, item.z)
|
||||
const star = createStar(pos, item, constellationIndex, chunkIndex)
|
||||
starGroup.add(star)
|
||||
points.push(pos)
|
||||
}
|
||||
})
|
||||
if (points.length>0)
|
||||
points.push(points[0])
|
||||
const material = new THREE.LineBasicMaterial({
|
||||
color: 0x888888
|
||||
});
|
||||
const geometry = new THREE.BufferGeometry().setFromPoints( points );
|
||||
const line = new THREE.Line( geometry, material );
|
||||
line.name = "line"
|
||||
line.userData = {constellation:constellationIndex}
|
||||
starGroup.add(line)
|
||||
// starGroup.scale.setScalar(1.5)
|
||||
|
||||
const label = document.createElement('div');
|
||||
label.className = "scene-label"
|
||||
label.textContent = names[constellationIndex % names.length];
|
||||
|
||||
const labelObject = new CSS2DObject(label);
|
||||
labelObject.name = `constellation${constellationIndex}_label`
|
||||
starGroup.add( labelObject );
|
||||
starGroup.name = `constellation${constellationIndex}`
|
||||
const mesh = new THREE.Mesh(new THREE.BoxGeometry(UNIT/CHUNK_SIZE, UNIT/CHUNK_SIZE, UNIT/CHUNK_SIZE), new THREE.MeshBasicMaterial({color:0x990000, wireframe:true}))
|
||||
// starGroup.add(mesh)
|
||||
return starGroup
|
||||
}
|
||||
|
||||
const createChunk = async (chunkX:number, chunkY:number, chunkZ:number, chunkKey:string) =>{
|
||||
const newChunk = new THREE.Group(); // Each chunk is a Group (or Object3D)
|
||||
newChunk.name = chunkKey
|
||||
const chunkIndex = chunkMap[chunkKey as keyof typeof chunkMap]
|
||||
newChunk.userData = {index:chunkIndex}
|
||||
// Add geometry or objects to the chunk
|
||||
const _size = UNIT/CHUNK_SIZE
|
||||
const low = (chunkIndex-1)*8*5
|
||||
const high = low + 40 + 1
|
||||
const { data, error } = await supabase.from('transaction-data-updated').select('*').gt('transaction_id', low).lt('transaction_id', high).order('transaction_id', { ascending: true });
|
||||
|
||||
if (error) {
|
||||
console.error('Error fetching data:', error);
|
||||
return null
|
||||
}
|
||||
let _index = 0
|
||||
for (let x = 0; x < CHUNK_SIZE; x++) {
|
||||
for (let y = 0; y < CHUNK_SIZE; y++) {
|
||||
for (let z = 0; z < CHUNK_SIZE; z++) {
|
||||
if(data[_index*5]){
|
||||
const constellationIndex = (chunkMap[chunkKey as keyof typeof chunkMap]-1) * 8 + _index
|
||||
const newArray = [data[_index*5], data[_index*5+1], data[_index*5+2], data[_index*5+3], data[_index*5+4]]
|
||||
const constellation = createConstellation(_size, newArray, constellationIndex, chunkIndex)
|
||||
const _offset = offset(constellationIndex)
|
||||
constellation.position.set((x-0.5)*_size + _offset.x, (y-0.5)*_size + _offset.y, (z-0.5)*_size + _offset.z);
|
||||
newChunk.add(constellation);
|
||||
}
|
||||
_index ++
|
||||
const createStar = (pos: THREE.Vector3, data: any, constellationIndex: number, chunkIndex: number) => {
|
||||
const _rr = data ? Math.cbrt(data.amount * 0.239) / 5000 : 0.2;
|
||||
const rr = _rr > 2.5 ? 2.5 : _rr < 0.2 ? 0.2 : _rr;
|
||||
const color = colors[Math.floor(Math.random() * 4.5)];
|
||||
const material = new THREE.MeshLambertMaterial({ color: color });
|
||||
const geometry = new THREE.SphereGeometry(rr, 16, 16);
|
||||
const mesh = new THREE.Mesh(geometry, material);
|
||||
if (data) {
|
||||
data.constellationIndex = constellationIndex;
|
||||
data.chunkIndex = chunkIndex;
|
||||
}
|
||||
}
|
||||
}
|
||||
newChunk.position.set(chunkX*UNIT, chunkY*UNIT, chunkZ*UNIT)
|
||||
|
||||
const mesh = new THREE.Mesh(new THREE.BoxGeometry(UNIT, UNIT, UNIT), new THREE.MeshBasicMaterial({color:0x227722, transparent:true, opacity:0.5}))
|
||||
// newChunk.add(mesh)
|
||||
return newChunk
|
||||
}
|
||||
mesh.name = data ? data.transaction_signature : undefined;
|
||||
mesh.userData = data ? data : undefined;
|
||||
mesh.position.copy(pos);
|
||||
return mesh;
|
||||
};
|
||||
|
||||
const updateChunks = async (chunkX: number, chunkY: number, chunkZ: number) =>{
|
||||
// Load chunks in a grid around the camera
|
||||
const network = scene.getObjectByName("network")
|
||||
if(network){
|
||||
for (let x = -RADIUS; x <= RADIUS; x++) {
|
||||
for (let y = -RADIUS; y <= RADIUS; y++) {
|
||||
for (let z = -RADIUS; z <= RADIUS; z++) {
|
||||
const chunkKey = `${chunkX + x},${chunkY + y},${chunkZ + z}`; // Unique key for the chunk
|
||||
if (loaded.data.has(chunkKey))
|
||||
continue;
|
||||
loaded.data.set(chunkKey, true);
|
||||
const chunk = await createChunk(chunkX + x, chunkY + y, chunkZ + z, chunkKey);
|
||||
if(chunk) network.add(chunk)
|
||||
}
|
||||
}
|
||||
}
|
||||
// Unload chunks that are too far away
|
||||
const removeGroup : any = []
|
||||
for (const chunkKey of loaded.data.keys()) {
|
||||
const [x, y, z] = chunkKey.split(",").map(Number);
|
||||
if ( Math.abs(x - chunkX) > RADIUS || Math.abs(y - chunkY) > RADIUS || Math.abs(z - chunkZ) > RADIUS ) {
|
||||
removeGroup.push(chunkKey)
|
||||
loaded.data.delete(chunkKey); // Free memory
|
||||
}
|
||||
}
|
||||
removeGroup.map((item:string)=>{
|
||||
const _obj = scene.getObjectByName(item)
|
||||
if(_obj){
|
||||
_obj?.children.map((item)=>{
|
||||
const name = item.name
|
||||
const child:any =_obj.getObjectByName(`${name}_label`)
|
||||
if(child && child.element && child.element.parentNode){
|
||||
child.element.parentNode.removeChild(child.element);
|
||||
const createConstellation = (_size: number, data: any[], constellationIndex: number, chunkIndex: number) => {
|
||||
// constellationIndex=== 1 && console.log(constellationIndex, data)
|
||||
const starGroup = new THREE.Group();
|
||||
const points: any[] = [];
|
||||
data.map((item) => {
|
||||
if (item) {
|
||||
const pos = new THREE.Vector3(item.x, item.y, item.z);
|
||||
const star = createStar(pos, item, constellationIndex, chunkIndex);
|
||||
starGroup.add(star);
|
||||
points.push(pos);
|
||||
}
|
||||
})
|
||||
network.remove(_obj)
|
||||
});
|
||||
if (points.length > 0) points.push(points[0]);
|
||||
const material = new THREE.LineBasicMaterial({
|
||||
color: 0x888888,
|
||||
});
|
||||
const geometry = new THREE.BufferGeometry().setFromPoints(points);
|
||||
const line = new THREE.Line(geometry, material);
|
||||
line.name = "line";
|
||||
line.userData = { constellation: constellationIndex };
|
||||
starGroup.add(line);
|
||||
// starGroup.scale.setScalar(1.5)
|
||||
|
||||
const label = document.createElement("div");
|
||||
label.className = "scene-label";
|
||||
label.textContent = names[constellationIndex % names.length];
|
||||
|
||||
const labelObject = new CSS2DObject(label);
|
||||
labelObject.name = `constellation${constellationIndex}_label`;
|
||||
starGroup.add(labelObject);
|
||||
starGroup.name = `constellation${constellationIndex}`;
|
||||
const mesh = new THREE.Mesh(
|
||||
new THREE.BoxGeometry(UNIT / CHUNK_SIZE, UNIT / CHUNK_SIZE, UNIT / CHUNK_SIZE),
|
||||
new THREE.MeshBasicMaterial({ color: 0x990000, wireframe: true })
|
||||
);
|
||||
// starGroup.add(mesh)
|
||||
return starGroup;
|
||||
};
|
||||
|
||||
const createChunk = async (chunkX: number, chunkY: number, chunkZ: number, chunkKey: string) => {
|
||||
const newChunk = new THREE.Group(); // Each chunk is a Group (or Object3D)
|
||||
newChunk.name = chunkKey;
|
||||
const chunkIndex = chunkMap[chunkKey as keyof typeof chunkMap];
|
||||
newChunk.userData = { index: chunkIndex };
|
||||
// Add geometry or objects to the chunk
|
||||
const _size = UNIT / CHUNK_SIZE;
|
||||
const low = (chunkIndex - 1) * 8 * 5;
|
||||
const high = low + 40 + 1;
|
||||
const { data, error } = await supabase
|
||||
.from("celestia-data")
|
||||
.select("*")
|
||||
.gt("transaction_id", low)
|
||||
.lt("transaction_id", high)
|
||||
.order("transaction_id", { ascending: true });
|
||||
|
||||
if (error) {
|
||||
console.error("Error fetching data:", error);
|
||||
return null;
|
||||
}
|
||||
})
|
||||
let _index = 0;
|
||||
for (let x = 0; x < CHUNK_SIZE; x++) {
|
||||
for (let y = 0; y < CHUNK_SIZE; y++) {
|
||||
for (let z = 0; z < CHUNK_SIZE; z++) {
|
||||
if (data[_index * 5]) {
|
||||
const constellationIndex = (chunkMap[chunkKey as keyof typeof chunkMap] - 1) * 8 + _index;
|
||||
const newArray = [
|
||||
data[_index * 5],
|
||||
data[_index * 5 + 1],
|
||||
data[_index * 5 + 2],
|
||||
data[_index * 5 + 3],
|
||||
data[_index * 5 + 4],
|
||||
];
|
||||
const constellation = createConstellation(_size, newArray, constellationIndex, chunkIndex);
|
||||
const _offset = offset(constellationIndex);
|
||||
constellation.position.set(
|
||||
(x - 0.5) * _size + _offset.x,
|
||||
(y - 0.5) * _size + _offset.y,
|
||||
(z - 0.5) * _size + _offset.z
|
||||
);
|
||||
newChunk.add(constellation);
|
||||
}
|
||||
_index++;
|
||||
}
|
||||
}
|
||||
}
|
||||
newChunk.position.set(chunkX * UNIT, chunkY * UNIT, chunkZ * UNIT);
|
||||
|
||||
update.flag = false
|
||||
}
|
||||
}
|
||||
const mesh = new THREE.Mesh(
|
||||
new THREE.BoxGeometry(UNIT, UNIT, UNIT),
|
||||
new THREE.MeshBasicMaterial({ color: 0x227722, transparent: true, opacity: 0.5 })
|
||||
);
|
||||
// newChunk.add(mesh)
|
||||
return newChunk;
|
||||
};
|
||||
|
||||
useEffect(()=>{
|
||||
const { chunkX, chunkY, chunkZ } = getChunkCoordinates3D(focus.x, focus.y, focus.z);
|
||||
if(chunk.chunkX !== chunkX || chunk.chunkY !== chunkY || chunk.chunkZ !== chunkZ){
|
||||
// update.flag = true
|
||||
setChunk({ chunkX, chunkY, chunkZ })
|
||||
updateChunks(chunkX, chunkY, chunkZ)
|
||||
}
|
||||
},[focus])
|
||||
const updateChunks = async (chunkX: number, chunkY: number, chunkZ: number) => {
|
||||
// Load chunks in a grid around the camera
|
||||
const network = scene.getObjectByName("network");
|
||||
if (network) {
|
||||
for (let x = -RADIUS; x <= RADIUS; x++) {
|
||||
for (let y = -RADIUS; y <= RADIUS; y++) {
|
||||
for (let z = -RADIUS; z <= RADIUS; z++) {
|
||||
const chunkKey = `${chunkX + x},${chunkY + y},${chunkZ + z}`; // Unique key for the chunk
|
||||
if (loaded.data.has(chunkKey)) continue;
|
||||
loaded.data.set(chunkKey, true);
|
||||
const chunk = await createChunk(chunkX + x, chunkY + y, chunkZ + z, chunkKey);
|
||||
if (chunk) network.add(chunk);
|
||||
}
|
||||
}
|
||||
}
|
||||
// Unload chunks that are too far away
|
||||
const removeGroup: any = [];
|
||||
for (const chunkKey of loaded.data.keys()) {
|
||||
const [x, y, z] = chunkKey.split(",").map(Number);
|
||||
if (Math.abs(x - chunkX) > RADIUS || Math.abs(y - chunkY) > RADIUS || Math.abs(z - chunkZ) > RADIUS) {
|
||||
removeGroup.push(chunkKey);
|
||||
loaded.data.delete(chunkKey); // Free memory
|
||||
}
|
||||
}
|
||||
removeGroup.map((item: string) => {
|
||||
const _obj = scene.getObjectByName(item);
|
||||
if (_obj) {
|
||||
_obj?.children.map((item) => {
|
||||
const name = item.name;
|
||||
const child: any = _obj.getObjectByName(`${name}_label`);
|
||||
if (child && child.element && child.element.parentNode) {
|
||||
child.element.parentNode.removeChild(child.element);
|
||||
}
|
||||
});
|
||||
network.remove(_obj);
|
||||
}
|
||||
});
|
||||
|
||||
useEffect(()=>{
|
||||
labelRenderer.setSize( window.innerWidth, window.innerHeight );
|
||||
labelRenderer.domElement.style.position = 'absolute';
|
||||
labelRenderer.domElement.style.top = '0px';
|
||||
labelRenderer.domElement.style.color = 'white';
|
||||
labelRenderer.domElement.style.fontStyle = 'bold';
|
||||
labelRenderer.domElement.style.fontSize = '10px';
|
||||
labelRenderer.domElement.style.pointerEvents = 'none'
|
||||
const dom = document.getElementById( 'canvas-wrapper' )
|
||||
if(dom){
|
||||
dom.appendChild( labelRenderer.domElement );
|
||||
}
|
||||
const { chunkX, chunkY, chunkZ } = getChunkCoordinates3D(focus.x, focus.y, focus.z);
|
||||
update.flag = true
|
||||
updateChunks(chunkX, chunkY, chunkZ)
|
||||
},[])
|
||||
update.flag = false;
|
||||
}
|
||||
};
|
||||
|
||||
useFrame(()=>{
|
||||
labelRenderer.render(scene, camera);
|
||||
})
|
||||
useEffect(() => {
|
||||
const { chunkX, chunkY, chunkZ } = getChunkCoordinates3D(focus.x, focus.y, focus.z);
|
||||
if (chunk.chunkX !== chunkX || chunk.chunkY !== chunkY || chunk.chunkZ !== chunkZ) {
|
||||
// update.flag = true
|
||||
setChunk({ chunkX, chunkY, chunkZ });
|
||||
updateChunks(chunkX, chunkY, chunkZ);
|
||||
}
|
||||
}, [focus]);
|
||||
|
||||
return (
|
||||
<group name="network">
|
||||
|
||||
</group>
|
||||
)
|
||||
useEffect(() => {
|
||||
labelRenderer.setSize(window.innerWidth, window.innerHeight);
|
||||
labelRenderer.domElement.style.position = "absolute";
|
||||
labelRenderer.domElement.style.top = "0px";
|
||||
labelRenderer.domElement.style.color = "white";
|
||||
labelRenderer.domElement.style.fontStyle = "bold";
|
||||
labelRenderer.domElement.style.fontSize = "10px";
|
||||
labelRenderer.domElement.style.pointerEvents = "none";
|
||||
const dom = document.getElementById("canvas-wrapper");
|
||||
if (dom) {
|
||||
dom.appendChild(labelRenderer.domElement);
|
||||
}
|
||||
const { chunkX, chunkY, chunkZ } = getChunkCoordinates3D(focus.x, focus.y, focus.z);
|
||||
update.flag = true;
|
||||
updateChunks(chunkX, chunkY, chunkZ);
|
||||
}, []);
|
||||
|
||||
useFrame(() => {
|
||||
labelRenderer.render(scene, camera);
|
||||
});
|
||||
|
||||
return <group name="network"></group>;
|
||||
}
|
||||
|
@ -1,183 +1,187 @@
|
||||
import useStore from "@/lib/store";
|
||||
import React, { useEffect, useRef, useState } from "react";
|
||||
import Styles from "./styles.module.scss";
|
||||
import { supabase } from "@/lib/supabaseClient";
|
||||
import SearchResults from "./SearchResults";
|
||||
import RecentTXNs from "./RecentTXNs";
|
||||
import starData from "@/components/MyScene/Chunk/data.json";
|
||||
import Notifications from "./Notifications";
|
||||
|
||||
import useStore from '@/lib/store';
|
||||
import React, { useEffect, useRef, useState } from 'react'
|
||||
import Styles from "./styles.module.scss"
|
||||
import { supabase } from '@/lib/supabaseClient';
|
||||
import SearchResults from './SearchResults';
|
||||
import RecentTXNs from './RecentTXNs';
|
||||
import starData from "@/components/MyScene/Chunk/data.json"
|
||||
import Notifications from './Notifications';
|
||||
export default function BottomPanel({ flag, changeFlag }: { flag: boolean; changeFlag(value: boolean): void }) {
|
||||
const [results, setResults] = useState<any[] | undefined>(undefined);
|
||||
const ref = useRef<HTMLDivElement>(null);
|
||||
const [Observatory, setObservatory] = useState({ stars: 0, constellations: 0, wallets: 0 });
|
||||
const [recentTXNs, setRecentTXNs] = useState<any[] | undefined>(undefined);
|
||||
const [latestConstellations, setLatestConstellations] = useState<string[]>([]);
|
||||
const names = starData.names;
|
||||
const tutorial = useStore((s) => s.tutorial);
|
||||
const tabs = useStore((s) => s.tabs);
|
||||
|
||||
export default function BottomPanel({flag, changeFlag}:{flag:boolean, changeFlag(value:boolean):void}) {
|
||||
|
||||
const [results, setResults] = useState<any[] | undefined>(undefined)
|
||||
const ref = useRef<HTMLDivElement>(null);
|
||||
const [Observatory, setObservatory] = useState({stars:0, constellations:0, wallets:0})
|
||||
const [recentTXNs, setRecentTXNs] = useState<any[] | undefined>(undefined)
|
||||
const [latestConstellations, setLatestConstellations] = useState<string[]>([])
|
||||
const names = starData.names
|
||||
const tutorial = useStore((s)=>s.tutorial)
|
||||
const tabs = useStore((s)=>s.tabs)
|
||||
|
||||
const fetchTableData = async (tableName: string, filter?: string) => {
|
||||
try {
|
||||
const { data, error } = await supabase.from(tableName).select('*').or(`transaction_signature.eq.${filter}, from_address.eq.${filter}`);
|
||||
// 5Q544fKrFoe6tsEbD7S8EmxGTJYAKtTVhAW5Q5pge4j1
|
||||
if (error) {
|
||||
throw new Error(error.message);
|
||||
}
|
||||
return data;
|
||||
} catch (error) {
|
||||
console.error('Error fetching data:', error);
|
||||
throw error;
|
||||
}
|
||||
};
|
||||
|
||||
const handleKeyDown = async (event: any) => {
|
||||
if (event.key === 'Enter') {
|
||||
if(event.target.value !== ""){
|
||||
const data = await fetchTableData('transaction-data-updated', event.target.value)
|
||||
setResults(data)
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
const changeInput = async (value: string) => {
|
||||
if(value === ""){
|
||||
setResults(undefined)
|
||||
useStore.setState({choose:undefined})
|
||||
}
|
||||
};
|
||||
|
||||
const fetchDataForObservatory = async () =>{
|
||||
try {
|
||||
const { data, error } = await supabase.from("transaction-data-updated").select('*').order('transaction_id', { ascending: false });
|
||||
// 5Q544fKrFoe6tsEbD7S8EmxGTJYAKtTVhAW5Q5pge4j1
|
||||
if (error) {
|
||||
console.log(error.message)
|
||||
throw new Error(error.message);
|
||||
}
|
||||
if(data.length>0){
|
||||
const stars = data.length
|
||||
const constellations = Math.floor((stars-1)/5)+1
|
||||
const temp : string[] = []
|
||||
setRecentTXNs(data.slice(0, 15))
|
||||
data.map((item)=>{
|
||||
if(!temp.includes(item["from_address"]))
|
||||
temp.push(item["from_address"])
|
||||
})
|
||||
const wallets = temp.length
|
||||
setObservatory({stars, constellations, wallets})
|
||||
const tempLatestConstellations : string[] = []
|
||||
data.slice(0, 15).map((item)=>{
|
||||
const k = Math.floor((item.transaction_id-1)/5)
|
||||
if(!tempLatestConstellations.includes(names[k])){
|
||||
tempLatestConstellations.push(names[k])
|
||||
}
|
||||
})
|
||||
setLatestConstellations(tempLatestConstellations)
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('Error fetching data:', error);
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
|
||||
useEffect(() => {
|
||||
fetchDataForObservatory()
|
||||
}, []);
|
||||
|
||||
useEffect(()=>{
|
||||
const handleClickOutside = (event: MouseEvent) => {
|
||||
if (ref.current && !ref.current.contains(event.target as Node)) {
|
||||
!tutorial && useStore.setState({tabs:0});
|
||||
}
|
||||
};
|
||||
if(!tutorial){
|
||||
document.addEventListener("mousedown", handleClickOutside);
|
||||
return () => {
|
||||
document.removeEventListener("mousedown", handleClickOutside);
|
||||
};
|
||||
}
|
||||
|
||||
},[tutorial])
|
||||
|
||||
const changeTabs = (value:number) =>{
|
||||
useStore.setState({tabs:value})
|
||||
}
|
||||
|
||||
return (
|
||||
<React.Fragment>
|
||||
<div ref={ref} className={(tabs === 1 || tabs === 3)?`${Styles.bottomPanel} ${Styles.activePanel}`:Styles.bottomPanel}>
|
||||
<div className='relative w-full h-fit'>
|
||||
<div className={Styles.tabs}>
|
||||
<div className={tabs===1?`${Styles.tab} ${Styles.active}`:Styles.tab} onClick={()=>changeTabs(1)}>
|
||||
<div className={Styles.text}>
|
||||
Search
|
||||
</div>
|
||||
</div>
|
||||
<div className={tabs===2?`${Styles.tab} ${Styles.active}`:Styles.tab} onClick={()=>changeTabs(2)}>
|
||||
<div className={Styles.text}>
|
||||
Stellar Births
|
||||
</div>
|
||||
</div>
|
||||
<div className={tabs===3?`${Styles.tab} ${Styles.active}`:Styles.tab} onClick={()=>changeTabs(3)}>
|
||||
<div className={Styles.text}>
|
||||
Celestial Observatory
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className='flex justify-end p-4'>
|
||||
{
|
||||
tabs === 1 ?
|
||||
<div className={Styles.wrapper}>
|
||||
<div className={Styles.inputContainter}>
|
||||
<input type='search' placeholder='transaction signature | wallet address' onKeyDown={handleKeyDown} onChange={(e)=>changeInput(e.target.value)}/>
|
||||
</div>
|
||||
</div>
|
||||
: tabs === 3 ?
|
||||
<div className='flex gap-12'>
|
||||
<div className={Styles.wrapper}>
|
||||
<div className={Styles.inputContainter}>
|
||||
<p>
|
||||
{Observatory.stars} Stars
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
<div className={Styles.wrapper}>
|
||||
<div className={Styles.inputContainter}>
|
||||
<p>
|
||||
{Observatory.constellations} Constellations
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
<div className={Styles.wrapper}>
|
||||
<div className={Styles.inputContainter}>
|
||||
<p>
|
||||
{Observatory.wallets} Cosmic Nurturers
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
:
|
||||
<div className={`${Styles.wrapper} hidden`}>
|
||||
<div className={Styles.inputContainter}>
|
||||
<div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
const fetchTableData = async (tableName: string, filter?: string) => {
|
||||
try {
|
||||
const { data, error } = await supabase
|
||||
.from(tableName)
|
||||
.select("*")
|
||||
.or(`transaction_signature.eq.${filter}, from_address.eq.${filter}`);
|
||||
// 5Q544fKrFoe6tsEbD7S8EmxGTJYAKtTVhAW5Q5pge4j1
|
||||
if (error) {
|
||||
throw new Error(error.message);
|
||||
}
|
||||
</div>
|
||||
|
||||
{
|
||||
latestConstellations?.length>0 && <Notifications data={latestConstellations}/>
|
||||
return data;
|
||||
} catch (error) {
|
||||
console.error("Error fetching data:", error);
|
||||
throw error;
|
||||
}
|
||||
</div>
|
||||
<SearchResults results={results} setResults={setResults}/>
|
||||
<RecentTXNs tabs={tabs} data={recentTXNs} setTabs={changeTabs}/>
|
||||
</div>
|
||||
</React.Fragment>
|
||||
)
|
||||
}
|
||||
};
|
||||
|
||||
const handleKeyDown = async (event: any) => {
|
||||
if (event.key === "Enter") {
|
||||
if (event.target.value !== "") {
|
||||
const data = await fetchTableData("celestia-data", event.target.value);
|
||||
setResults(data);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
const changeInput = async (value: string) => {
|
||||
if (value === "") {
|
||||
setResults(undefined);
|
||||
useStore.setState({ choose: undefined });
|
||||
}
|
||||
};
|
||||
|
||||
const fetchDataForObservatory = async () => {
|
||||
try {
|
||||
const { data, error } = await supabase
|
||||
.from("celestia-data")
|
||||
.select("*")
|
||||
.order("transaction_id", { ascending: false });
|
||||
// 5Q544fKrFoe6tsEbD7S8EmxGTJYAKtTVhAW5Q5pge4j1
|
||||
if (error) {
|
||||
console.log(error.message);
|
||||
throw new Error(error.message);
|
||||
}
|
||||
if (data.length > 0) {
|
||||
const stars = data.length;
|
||||
const constellations = Math.floor((stars - 1) / 5) + 1;
|
||||
const temp: string[] = [];
|
||||
setRecentTXNs(data.slice(0, 15));
|
||||
data.map((item) => {
|
||||
if (!temp.includes(item["from_address"])) temp.push(item["from_address"]);
|
||||
});
|
||||
const wallets = temp.length;
|
||||
setObservatory({ stars, constellations, wallets });
|
||||
const tempLatestConstellations: string[] = [];
|
||||
data.slice(0, 15).map((item) => {
|
||||
const k = Math.floor((item.transaction_id - 1) / 5);
|
||||
if (!tempLatestConstellations.includes(names[k])) {
|
||||
tempLatestConstellations.push(names[k]);
|
||||
}
|
||||
});
|
||||
setLatestConstellations(tempLatestConstellations);
|
||||
}
|
||||
} catch (error) {
|
||||
console.error("Error fetching data:", error);
|
||||
throw error;
|
||||
}
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
fetchDataForObservatory();
|
||||
}, []);
|
||||
|
||||
useEffect(() => {
|
||||
const handleClickOutside = (event: MouseEvent) => {
|
||||
if (ref.current && !ref.current.contains(event.target as Node)) {
|
||||
!tutorial && useStore.setState({ tabs: 0 });
|
||||
}
|
||||
};
|
||||
if (!tutorial) {
|
||||
document.addEventListener("mousedown", handleClickOutside);
|
||||
return () => {
|
||||
document.removeEventListener("mousedown", handleClickOutside);
|
||||
};
|
||||
}
|
||||
}, [tutorial]);
|
||||
|
||||
const changeTabs = (value: number) => {
|
||||
useStore.setState({ tabs: value });
|
||||
};
|
||||
|
||||
return (
|
||||
<React.Fragment>
|
||||
<div
|
||||
ref={ref}
|
||||
className={
|
||||
tabs === 1 || tabs === 3 ? `${Styles.bottomPanel} ${Styles.activePanel}` : Styles.bottomPanel
|
||||
}
|
||||
>
|
||||
<div className="relative w-full h-fit">
|
||||
<div className={Styles.tabs}>
|
||||
<div
|
||||
className={tabs === 1 ? `${Styles.tab} ${Styles.active}` : Styles.tab}
|
||||
onClick={() => changeTabs(1)}
|
||||
>
|
||||
<div className={Styles.text}>Search</div>
|
||||
</div>
|
||||
<div
|
||||
className={tabs === 2 ? `${Styles.tab} ${Styles.active}` : Styles.tab}
|
||||
onClick={() => changeTabs(2)}
|
||||
>
|
||||
<div className={Styles.text}>Stellar Births</div>
|
||||
</div>
|
||||
<div
|
||||
className={tabs === 3 ? `${Styles.tab} ${Styles.active}` : Styles.tab}
|
||||
onClick={() => changeTabs(3)}
|
||||
>
|
||||
<div className={Styles.text}>Celestial Observatory</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="flex justify-end p-4">
|
||||
{tabs === 1 ? (
|
||||
<div className={Styles.wrapper}>
|
||||
<div className={Styles.inputContainter}>
|
||||
<input
|
||||
type="search"
|
||||
placeholder="transaction signature | wallet address"
|
||||
onKeyDown={handleKeyDown}
|
||||
onChange={(e) => changeInput(e.target.value)}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
) : tabs === 3 ? (
|
||||
<div className="flex gap-12">
|
||||
<div className={Styles.wrapper}>
|
||||
<div className={Styles.inputContainter}>
|
||||
<p>{Observatory.stars} Stars</p>
|
||||
</div>
|
||||
</div>
|
||||
<div className={Styles.wrapper}>
|
||||
<div className={Styles.inputContainter}>
|
||||
<p>{Observatory.constellations} Constellations</p>
|
||||
</div>
|
||||
</div>
|
||||
<div className={Styles.wrapper}>
|
||||
<div className={Styles.inputContainter}>
|
||||
<p>{Observatory.wallets} Cosmic Nurturers</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
) : (
|
||||
<div className={`${Styles.wrapper} hidden`}>
|
||||
<div className={Styles.inputContainter}>
|
||||
<div></div>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
|
||||
{latestConstellations?.length > 0 && <Notifications data={latestConstellations} />}
|
||||
</div>
|
||||
<SearchResults results={results} setResults={setResults} />
|
||||
<RecentTXNs tabs={tabs} data={recentTXNs} setTabs={changeTabs} />
|
||||
</div>
|
||||
</React.Fragment>
|
||||
);
|
||||
}
|
||||
|
@ -9,55 +9,54 @@ import Head from "next/head";
|
||||
import React, { useEffect } from "react";
|
||||
|
||||
const geistSans = localFont({
|
||||
src: "./fonts/GeistVF.woff",
|
||||
variable: "--font-geist-sans",
|
||||
weight: "100 900",
|
||||
src: "./fonts/GeistVF.woff",
|
||||
variable: "--font-geist-sans",
|
||||
weight: "100 900",
|
||||
});
|
||||
const geistMono = localFont({
|
||||
src: "./fonts/GeistMonoVF.woff",
|
||||
variable: "--font-geist-mono",
|
||||
weight: "100 900",
|
||||
src: "./fonts/GeistMonoVF.woff",
|
||||
variable: "--font-geist-mono",
|
||||
weight: "100 900",
|
||||
});
|
||||
|
||||
export default function Home() {
|
||||
useEffect(() => {
|
||||
const fetchRowCount = async () => {
|
||||
try {
|
||||
const { count, error } = await supabase
|
||||
.from("celestia-data")
|
||||
.select("*", { count: "exact", head: true }); // `head: true` fetches only the count, not the data
|
||||
|
||||
useEffect(()=>{
|
||||
const fetchRowCount = async () => {
|
||||
try {
|
||||
const { count, error } = await supabase
|
||||
.from("transaction-data-updated")
|
||||
.select('*', { count: 'exact', head: true }); // `head: true` fetches only the count, not the data
|
||||
|
||||
if (error) {
|
||||
throw new Error(error.message);
|
||||
}
|
||||
useStore.setState({count:Number(count)})
|
||||
return; // This is the total number of rows
|
||||
} catch (error) {
|
||||
console.error('Error fetching row count:', error);
|
||||
throw error;
|
||||
}
|
||||
};
|
||||
if (error) {
|
||||
throw new Error(error.message);
|
||||
}
|
||||
useStore.setState({ count: Number(count) });
|
||||
return; // This is the total number of rows
|
||||
} catch (error) {
|
||||
console.error("Error fetching row count:", error);
|
||||
throw error;
|
||||
}
|
||||
};
|
||||
|
||||
// fetchRowCount();
|
||||
},[])
|
||||
// fetchRowCount();
|
||||
}, []);
|
||||
|
||||
return (
|
||||
<React.Fragment>
|
||||
<Head>
|
||||
<title>Celestia</title>
|
||||
<meta httpEquiv="Content-Type" content="text/html; charset=utf-8"/>
|
||||
<meta name="title" content="Celestia"/>
|
||||
{/* <link rel="icon" href="/logo.png" /> */}
|
||||
</Head>
|
||||
<Canvas id="canvas-wrapper" camera={{fov:90, near:0.5, far:1500}} linear>
|
||||
<MyScene/>
|
||||
</Canvas>
|
||||
<div
|
||||
className={`absolute top-0 left-0 w-screen h-screen overflow-hidden z-50 pointer-events-none ${geistSans.variable} ${geistMono.variable} font-[family-name:var(--font-geist-sans)]`}
|
||||
>
|
||||
<MyContent/>
|
||||
</div>
|
||||
</React.Fragment>
|
||||
);
|
||||
return (
|
||||
<React.Fragment>
|
||||
<Head>
|
||||
<title>Celestia</title>
|
||||
<meta httpEquiv="Content-Type" content="text/html; charset=utf-8" />
|
||||
<meta name="title" content="Celestia" />
|
||||
{/* <link rel="icon" href="/logo.png" /> */}
|
||||
</Head>
|
||||
<Canvas id="canvas-wrapper" camera={{ fov: 90, near: 0.5, far: 1500 }} linear>
|
||||
<MyScene />
|
||||
</Canvas>
|
||||
<div
|
||||
className={`absolute top-0 left-0 w-screen h-screen overflow-hidden z-50 pointer-events-none ${geistSans.variable} ${geistMono.variable} font-[family-name:var(--font-geist-sans)]`}
|
||||
>
|
||||
<MyContent />
|
||||
</div>
|
||||
</React.Fragment>
|
||||
);
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user