Initial add backend stuff

This commit is contained in:
2026-07-08 15:45:16 -04:00
commit a7964f9410
89 changed files with 25924 additions and 0 deletions

123
csv/csv.go Normal file
View File

@@ -0,0 +1,123 @@
package csv
import (
"encoding/csv"
"errors"
"fmt"
"net/http"
"reflect"
"strings"
)
func WriteCSVtoHTTP(w http.ResponseWriter, csv string, filename string) {
w.Header().Set("Content-Type", "text/csv")
w.Header().Set("Content-Disposition", "attachment; filename="+filename+".csv")
w.Write([]byte(csv))
}
func MakeCSV(headers []string, records [][]string) (string, error) {
if len(records) > 0 {
if len(headers) != len(records[0]) {
return "", errors.New("data contains more columns then specified by headers")
}
}
// Write to CSV
var csvBuilder strings.Builder
writer := csv.NewWriter(&csvBuilder)
// Write headers
if err := writer.Write(headers); err != nil {
return "", fmt.Errorf("failed to write headers: %v", err)
}
// Write records
for _, record := range records {
if err := writer.Write(record); err != nil {
return "", fmt.Errorf("failed to write record: %v", err)
}
}
writer.Flush()
if err := writer.Error(); err != nil {
return "", fmt.Errorf("csv writer error: %v", err)
}
return csvBuilder.String(), nil
}
func StructToCSV(data any) (string, error) {
val := reflect.ValueOf(data)
if val.Kind() != reflect.Slice {
return "", fmt.Errorf("input must be a slice of structs")
}
if val.Len() == 0 {
return "", nil
}
var headers []string
var records [][]string
// Get the first element to determine struct fields
first := val.Index(0)
if first.Kind() == reflect.Ptr {
first = first.Elem()
}
if first.Kind() != reflect.Struct {
return "", fmt.Errorf("slice elements must be structs or pointers to structs")
}
// Get field names as headers
t := first.Type()
for i := 0; i < t.NumField(); i++ {
field := t.Field(i)
// Use json tag if present, otherwise use field name
tag := field.Tag.Get("json")
if tag != "" && tag != "-" {
headers = append(headers, tag)
} else {
headers = append(headers, field.Name)
}
}
// Convert each struct to a record
for i := 0; i < val.Len(); i++ {
item := val.Index(i)
if item.Kind() == reflect.Ptr {
item = item.Elem()
}
var record []string
for j := 0; j < item.NumField(); j++ {
fieldVal := item.Field(j)
record = append(record, fmt.Sprintf("%v", fieldVal.Interface()))
}
records = append(records, record)
}
// Write to CSV
var csvBuilder strings.Builder
writer := csv.NewWriter(&csvBuilder)
// Write headers
if err := writer.Write(headers); err != nil {
return "", fmt.Errorf("failed to write headers: %v", err)
}
// Write records
for _, record := range records {
if err := writer.Write(record); err != nil {
return "", fmt.Errorf("failed to write record: %v", err)
}
}
writer.Flush()
if err := writer.Error(); err != nil {
return "", fmt.Errorf("csv writer error: %v", err)
}
return csvBuilder.String(), nil
}